CakePHP is a free and open source PHP framework. Built with MVC (model-view-controller) pattern, it provides a powerful structure for the creation of well-organised Web applications.
There are many MVC frameworks available like CakePHP, Zend, Laravel, Yii, Codeigniter, etc. CakePHP is one of the top MVC frameworks. It is suitable for small, medium and large scale applications, and provides most of the tools we need to build an application. Instead of building from scratch, just copy CakePHP and start building your application. CakePHP has a very active development team and a large community for help. Its key features are inbuilt CRUD operations, automatic code generation, inbuilt validations, ACL, caching, etc.
In this tutorial, we will learn the basic concept of a component, how to create our own components and use them in our application. We will use the CakePHP 2.x version.
A CakePHP component
A component is a class file which contains the common code or logic. The component can be shared between the applications controllers. CakePHP comes with some good components, so you can perform various common tasks like session handling, cookies and security related things, etc.
A component is a good option when you need the same logic or functions in multiple controllers. It helps you to reuse the code and make your controllers tiny and clean. Apart from the built-in components of CakePHP, you can create your own components for common functionality such as handling file uploads, image processing or any common logic of our application.
Creating a component
Creating a component is a simple task. Just like a normal PHP class, you need to create a class file in your Component directory. The name of the class must be in CamelCase format and the word Component must be appended to it. For example, if you want to create a password component, the class name will be PasswordComponent and the file name will be PasswordComponent.php.
Note: As per CakePHPs naming conventions, if the component name contains multiple words, like RememberMe, the class name will be RememberMeComponent and the file name will be RememberMeComponent.php.
Lets continue with our password component example. As the name suggests, our component will be used for generating random passwords in our application.
Now, lets create a file in the app/Controller/Component directory and name it PasswordComponent.php. The basic structure of our component looks like whats shown below:
App::uses(Component, Controller); class PasswordComponent extends Component { // some code goes here }
Note: Every component class must extend the main Component class. And we need to load the main component class by using the App:uses (Component, Controller) method.
Now, our basic component is ready. Lets add a function to it that generates a random password string and returns it.
App::uses(Component, Controller); class PasswordComponent extends Component { public function generate() { $length = 10; $chars = ABCDEFGHIJKLMNOPQRS TUVWXYZabcdefghijklmnopqrstuvwxyz .0123456789``-=~!@#$%^&*()_+,./<>?;:[]{}\|; $passwordStr = ; $max = strlen($chars) - 1; for ($i = 0; $i < $length; $i++) { $passwordStr .= $chars[mt_rand(0, $max)]; } return $passwordStr; } }
So we have now added our password generator function to the component. When we call this function, it will return a randomly generated password string.
If you see the generate() function, it generates a fixed length string of 10 characters. As with any normal PHP function, we can make it more dynamic by adding length as a function parameter, so that we can pass the desired length for our password string.
Lets modify our function to use dynamic length:
function generate($length = 8) { $chars = ABCDEFGHIJKLMNOPQRSTU VWXYZabcdefghijklmnopqrstuvwxyz . 0123456789``-=~!@#$%^&*()_+,./<>?;:[]{}\|; $passwordStr = ; $max = strlen($chars) - 1; for ($i = 0; $i < $length; $i++) { $passwordStr .= $chars[mt_rand(0, $max)]; } return $passwordStr; }
We have set the default value of $length to 8. So, if we dont pass the length, it will generate an eight character long string.
Our final component code should look like what follows:
App::uses(Component, Controller); class PasswordComponent extends Component { public function generate($length = 8) { $chars = ABCDEFGHIJKLMNOPQRST UVWXYZabcdefghijklmnopqrstuvwxyz .0123456789``-=~!@#$%^&*()_+,./<>?;:[]{}\|; $passwordStr = ; $max = strlen($chars) - 1; for ($i = 0; $i < $length; $i++) { $passwordStr .= $chars[mt_rand(0, $max)]; } return $passwordStr; } }
Now our component is ready to be used in our applications controllers.
How to include the component in the controller
We can include our component in the controller by simply adding its name to the $components array. Here, $components is a public property of the Controller class. Please note that we only need to add the class name of the component, without the Component suffix. For example, to use our PasswordComponent in any controller, add the following command:
public $components = array(Session, Password);
After adding this, we can access this component by using $this->Password, similar to other components.
If we include the component in our AppController, it will be available in all the other controllers and there is no need to include it in each controller file.
For example, to use our PasswordComponent and its generate() method in UsersController, issue the following code:
App::uses(AppController, Controller); class UsersController extends AppController { public $components = array(Session, Password); public function some_action() { $password = $this->Password->generate(12); } }
We can use this generated password in the view file by setting the view variable or saving it to the database.
Note: In the latest version of CakePHP, which is 3.0, loading of a component is a little different. There is a method called loadComponent() to load any component in the controller. So, to include our password component, we can use $this->loadComponent(Password). After this, we can use the component in the same way as we do in CakePHP 2.0: $this->Password->generate().
Using other components in our component
We can use other componentsbuilt-in or custominside our own component. CakePHP provides an easy way to do this. Similar to controllers, we can define other components in the $components property of our component.
For example, if there is an existing component named ExampleComponent, and we want to use it in our PasswordComponent, we can issue the following code:
App::uses(Component, Controller); class PasswordComponent extends Component { public $components = array(Example); public function some_function_name() { $foo = $this->Example->bar(); } /* other code goes here*/ }
As you can see, we can use another component and its methods in the same way using $this->Component->method().
Magic methods of a component
CakePHP provides some callback functions known as magic methods for components. We can use these callback methods to fulfil our needs. These methods are automatically called by CakePHP, so we can define the logic that needs to be performed before or after some action or event.
Given below is a list of the available magic methods.
initialize (Controller $controller): This method is called before the controllers beforeFilter method. We can use this method to initialise our variables or objects and use them later.
startup (Controller $controller): This method is called after the controllers beforeFilter method, but before the controller executes its current action handler. This method can also be used to carry out some processes before our main action executes, like checking a session for a logged-in user, or setting cookies, etc.
beforeRender (Controller $controller): This method is called after the controller executes the requested actions logic, but before the controller renders its views and layout. Here we can set the view variables, so that we can use them in our view/layout files.
shutdown (Controller $controller): This method is called before the output is sent to the browser. We can use it to unset the unnecessary variables and objects to free up the memory.
beforeRedirect (Controller $controller, $url, $status=null, $exit=true): This method is called when the controllers redirect method is called but before any further action is taken. In this method, we can check some conditions and reset the redirect URL or disable the redirection from here.