How to generate PDF in CakePHP 2.x with dompdf

For some applications, generating PDF file is crucial. Let’s imagine invoicing applications, created with CakePHP, generating PDF is a must. But how to do this? How to generate the file without using CLI? We will be using dompdf for this task. You can get it free and licensed under LGPL.

Make sure your meet the requirements:

  1. Using latest version of CakePHP 2.2.x
  2. Running server with PHP 5.3.x (never tested with PHP 5.2)
  3. Latest version of dompdf 0.6.0 Beta 3

Let’s get started!

Change CakePHP 2.x default routing after login

Few days ago, I’m giving a training of CakePHP framework for AMDI-USM‘s Bio-ICT staff. We were developing one sample application and the default route will go to /users/login page. One of them ask me whether we can change the default routing after the user logged in.

  1. Before user login, the default routing will be /users/login
  2. After user logged in, default routing will go to /submissions/index

Nice question! Let’s try this and see if we could make it happen.

The Bootstrap

First of all, we need to do it in our /config/bootstrap.php, then we need to load SessionComponent to check whether user logged in to the system.

// include the Session Component to our application
App::uses('SessionComponent', 'Controller/Component');

// now create new SessionComponent instance
$Session = new SessionComponent(new ComponentCollection());

// check if the user logged in
if ($Session->read('Auth.User')) {

    switch ($Session->read('Auth.User.group_id'))
    {
        // Administrator
        case 1:
            Configure::write('Route.default', array('controller' => 'pages', 'action' => 'dashboard', 'admin' => true));
            break;

        // Manager
        case 2:
            Configure::write('Route.default', array('controller' => 'pages', 'action' => 'dashboard', 'manager' => true));
            break;

        // Registered
        case 3:
            Configure::write('Route.default', array('controller' => 'pages', 'action' => 'dashboard'));
            break;
    }
}
// nope, user not logged in
else {
    Configure::write('Route.default', array('controller' => 'pages', 'action' => 'display'));
}

Change the default routing

We need to change the default route in /Config/routes.php, set the default route to:

Router::connect('/', Configure::read('Route.default'));

Done!

That’s all you need to make it work. Simple and straight forward.

Link to Homepage

If you need a link to your homepage, normally in your website logo, you can use this code instead:

echo $this->Html->link('Home', Configure::read('Route.default'));

That’s all. Please let me know if it’s not working for you.

How to use LESS CSS in CakePHP application

CakePHP is a marvelous framework, it helps us building powerful web application in short amount of time, even though it quite hard to get started, but once you know the flow and the conventions, it can saves at least 30% of your development time. Now I want to show you how to use LESS in CakePHP applications to increase productivity even further.

Introduction to LESS

For those who doesn’t know about LESS, it’s time to explore and start playing with it. LESS can help us writing less codes and at the same time offers reusable codes for our CSS. According to their website:

LESS extends CSS with dynamic behavior such as variables, mixins, operations and functions.

Let’s take a look the simple example. As you can see, the codes below is almost identical to normal CSS codes, exceptLESS introduce more features like variablesfunctionsoperations and mixins.

@shadow(@x: 0; @y: 2px; @blur: 3px; @color: rgba(0, 0, 0, 0.3)) {
    -moz-box-shadow: @x @y @blur @color;
    -webkit-box-shadow: @x @y @blur @color;
    box-shadow: @x @y @blur @color;
}

@rounded(@radius: 3px) {
    -moz-border-radius: @radius;
    -webkit-border-radius: @radius;
    border-radius: @radius;
}

#main_container {
    @rounded;
    @shadow;
}

#side_container {
    @rounded(10px);
    @shadow(0; 5px; 10px; rgba(0, 0, 0, 0.9));
}

#footer_container {
    @rounded(5px);
    @shadow(0; 3px; 5px; rgba(255, 255, 255, 0.5));
}

Now let’s take a look to the output produce by LESS.

#main_container {
    -moz-border-radius: 3px;
    -webkit-border-radius: 3px;
    border-radius: 3px;
    -moz-box-shadow: 0 2px 3px rgba(0,0,0,0.3);
    -webkit-box-shadow: 0 2px 3px rgba(0,0,0,0.3);
    box-shadow: 0 2px 3px rgba(0,0,0,0.3);
}

#side_container {
    -moz-border-radius: 10px;
    -webkit-border-radius: 10px;
    border-radius: 10px;
    -moz-box-shadow: 0 5px 10px rgba(0,0,0,0.9);
    -webkit-box-shadow: 0 5px 10px rgba(0,0,0,0.9);
    box-shadow: 0 5px 10px rgba(0,0,0,0.9);
}

#footer_container {
    -moz-border-radius: 5px;
    -webkit-border-radius: 5px;
    border-radius: 5px;
    -moz-box-shadow: 0 3px 5px rgba(255,255,255,0.5);
    -webkit-box-shadow: 0 3px 5px rgba(255,255,255,0.5);
    box-shadow: 0 3px 5px rgba(255,255,255,0.5);
}

Isn’t that great? With LESS we can define some most common styling as functions and we pass the argument to override the default values; just like other programming languages. And we don’t have to re-write all those CSS3 codes with vendor prefix over and over again. Define it as functions and re-use when we need.

Enough with the LESS already, you can learn more about it on their website. Now I want to show how to use LESS in our CakePHP applications and compile it every time we load our application, so we can link the output file directly.

Using LESS with CakePHP

At the moment, I’m in the middle building an e-commerce site for my client and I need to put some styling, so I decided to add LESS to my application. On their website, they offer Javascript to parse the LESS files. Nope, we not going to use it. Instead, we will use lessphp library to compile it on runtime and create the CSS file for our application.

Download lessphp

Get the source from the website or you can get the most latest version from Github.

Now extract the file and copy lessc.inc.php to your /app/vendors and rename it to lessc.php.

Call it in AppController

Open up your /app/app_controller.php and add the function below:

public function beforeRender()
{
    // only compile it on development mode
    if (Configure::read('debug') > 0)
    {
        // import the file to application
        App::import('Vendor', 'lessc');

        // set the LESS file location
        $less = ROOT . DS . APP_DIR . DS . 'webroot' . DS . 'less' . DS . 'main.less';

        // set the CSS file to be written
        $css = ROOT . DS . APP_DIR . DS . 'webroot' . DS . 'css' . DS . 'main.css';

        // compile the file
        lessc::ccompile($less, $css);
    }
    parent::beforeRender();
}

Create files and folders

On your /app/webroot directory, create new folder and name it as less, followed by creating an empty file and name it main.less.

Now create another empty file inside your /app/webroot/css directory and name it main.css. This will be the output file we will use in our application.

Link to application

Now you can link the CSS file in your /app/views/layouts/default.ctp using HtmlHelper.

$this->Html->css('main');

Done! Now write all your LESS codes to /app/webroot/less/main.less and every time the application running, lessphp will compile the code to CSS file automatically.