CakeDC Blog

TIPS, INSIGHTS AND THE LATEST FROM THE EXPERTS BEHIND CAKEPHP

CakePHP ORM 3.0 Unleashes New, Flexible, and Powerful Functions

 

In line with its overall goal of eliminating redundancy and increasing efficiency, the new ORM has replaced several functions in the earlier versions with newer and significantly improved functions or functionality. Among the functions affected, we will confine ourselves here to three functions, commands, or processes:

1. afterFind or virtual fields

Developers of previous versions will recall how extensively they had to use afterFind callback and virtual fields to generate data properties. In the new CakePHP 3.0, this is no longer necessary and has been removed in favor of virtual properties on entities which are easier and more powerful. For example, using this method, properties can be generated on the fly to user entities with both first and last names by adding an accessor for full_name. Here is a code example.

By defining accessors you can provide access to fields/properties that do not actually exist. For example if your users table has first_name and last_name you could create a method for the full name:

namespace App\Model\Entity;

use Cake\ORM\Entity;

class User extends Entity
{

    protected function _getFullName()
    {
        return $this->_properties['first_name'] . '  ' .
            $this->_properties['last_name'];
    }

}

You can access virtual fields as if they existed on the entity. The property name will be the lower case and underscored version of the method:

echo $user->full_name;

Do bear in mind that virtual fields cannot be used in finds.

Once a code segment similar to the above has been defined, the new property can be accessed easily using $user->full_name. Moreover, you can build aggregated data sets from your results. Note also that though virtual fields no longer constitute an explicit feature of ORM, you will still be able to achieve the same result using query builder and expression objects which are more powerful and flexible. Here is a code example that will make this clear.

2. Definition of Associations

Another extremely important feature introduced in CakePHP 3.0 is the use of methods to create associations. Instead of defining associations using properties like $belongsTo and $hasMany, this significant attribute uses methods that bypass the many inherent limitations of class definitions by allowing only one way of defining associations. Furthermore, the same API handles the “initialize” method and all other parts of your application code when manipulating associations. This is much more efficient and significantly improves productivity. Here is a code snippet to illustrate this.

class ArticlesTable extends Table
{

   public function initialize(array $config)
   {
       $this->belongsTo('Authors');

       $this->hasMany('Comments', [
           'className' => 'Comments',
           'conditions' => ['approved' => true]
       ]);

       $this->hasMany('UnapprovedComments', [
           'className' => 'Comments',
           'conditions' => ['approved' => false],
           'propertyName' => 'unapproved_comments'
       ]);
   }
}

Beside the use of methods to create associations as shown in the example above, the awkward name hasAndBelongsToMany has been renamed to belongsToMany.

As if the above enhancements were not enough, CakePHP 3.0 has equipped developers with the ability to create custom association classes which will be a welcome relief as a safety valve for situations where the built-in relation types do not meet specific requirements. For more details on creating associations, please consult our section: Associations – Linking Tables together.

3. Validation Rules

Validation plays a crucial role in all software development efforts but if they are to contribute to the overall productivity of the development cycle, the way they are defined and used must be straightforward and easy. When it comes to validation rules, CakePHP 3.0 team introduced an elegant solution to many problems with earlier versions through the use of Validator object to generate validation rules. With this feature, defining multiple sets of rules has become a breeze! Here is an example:

 

class UsersTable extends Table
{

    public function validationPasswordConfirm(Validator $validator)
    {
        $validator
            ->requirePresence('password_confirm', 'create')
            ->notEmpty('password_confirm');

        $validator->add('password', 'custom', [
            'rule' => function ($value, $context) {
                $confirm = Hash::get($context, 'data.password_confirm');
                if (!is_null($confirm) && $value != $confirm) {
                    return false;
                }
                return true;
            },
            'message' => __d('Users', 'Your password does not match your confirm password. Please try again'),
            'on' => ['create', 'update'],
            'allowEmpty' => false
        ]);

        return $validator;
    }

}

In Patch entity validationPasswordConfirm will be applied if is passed in ‘validate’ param.

 

 $user = $this->Users->patchEntity($user, $this->request->data(), ['validate' => 'passwordConfirm']);

What is noteworthy about the above code segment is the ability to define as many validation methods as needed. Notice how each method should be prefixed with validation and should be structured to accept a $validator argument.

Latest articles

Using a vagrant box as quick environment for the Getting Started with...

We've decided to create a simple vagrant box with all the required packages to improve the environment setup step in our free Getting Started with CakePHP training session. We used other tools in the past, but we hope vagrant will help users to install a common environment before the session to get the most of it.

Requirements

Setup

  • Create a new folder where the code will be located
  • Create a new file called Vagrantfile with the following contents
# -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| config.vm.box = "cakedc/cakephp-training" config.vm.network :forwarded_port, guest: 8765, host: 8765 config.vm.network :private_network, ip: "192.168.33.33" config.vm.provider "virtualbox" do |vb| vb.memory = "1024" vb.customize ['modifyvm', :id, '--cableconnected1', 'on'] end end
  • Run vagrant up
  • Wait (download could take several minutes depending on your internet connection)
  • Run vagrant ssh
Now you have ssh access to a training ubuntu (16.04) based virtual machine, with all the requirements to run your training CakePHP application.
  • Setup a new CakePHP project
cd /vagrant composer create-project cakephp/app
  • Start the local server
cd /vagrant/app php bin/cake.php server --host 0.0.0.0
  • From your host machine, open a browser and navigate to http://localhost:8765
  • You should be able to see the CakePHP welcome page
  We think this VM will enable faster environment setups, and an easier entry point to the training session. Please let us know if you find issues with this process.

Boosting your API with CakePHP API and PHP-PM (ReactPHP)

A couple days ago AlexMax commented in CakePHP's IRC channel about the https://github.com/php-pm/php-pm project and it rang a bell for us. We did a couple tests internally and found this could be a great companion to our API plugin, so we wrote a new Bridge for CakePHP and ran some benchmarks.

The Cast

We put all together and created a sample application (1 posts table with 30 records) to do some benchmarks.

Benchmark configuration

We are not aiming to provide detailed or production figures, just a reference of the results obtained for your comparison. Results are generated from a development box, using PHP 7.1.12-3+ubuntu16.04.1+deb.sury.org+1 with xdebug enabled on ubuntu xenial, 8x Intel(R) Core(TM) i7-4771 CPU @ 3.50GHz We baked the application using the latest CakePHP 3.5.10, and set application debug to false, and log output to syslog. As we are interested in boosting API response times the most, we tested the following scenarios
  • A) CakePHP json output, served from nginx+phpfpm
  • B) CakePHP + API Plugin Middleware integration json output, served from nginx+phpfpm
  • C) CakePHP + API Plugin Middleware integration json output, served from php-pm
Benchmark figures were obtained using ab -n 5000 -c 100 URL

Results

Scenario requests/second avg time
A) CakePHP json output, served from nginx+phpfpm 372.97 [#/sec] (mean) 268.120 [ms] (mean)
B) CakePHP + API Plugin Middleware integration json output, served from nginx+phpfpm 399.79 [#/sec] (mean) 250.133 [ms] (mean)
C) CakePHP + API Plugin Middleware integration json output, served from php-pm 911.95 [#/sec] (mean) 109.656 [ms] (mean)
  These results for a NOT OPTIMIZED CakePHP application are promising, and the improvement using PHP-PM is huge in this case. There are some important considerations though:
  • PHP-FPM is mature and stable, PHP-PM is still in early development, although there is a 1.0 version released already.
  • Processes need monitoring, specially regarding memory leaks, we would need to manage a restart policy and be able to hot-restart individual workers
  • System integration, init scripts are not provided, even if this is something easy to manage nowadays via systemd or monit, would be good to have for production
  • Application bootstrapping should not be affected by the request. If your application bootstrapping depends on the request params, or logged in user, you'll need to refactor your code
  • Session handling was not tested, issues are reported for PHP-PM for other frameworks. We were aiming to stateless API's so we don't know if this would be an issue for a regular application
Performance is always a concern for the API developer, applying proven paradigms like the event driven development (https://reactphp.org/) to your existing code would be the way to go and ensure backend frameworks like CakePHP will perform as required when dealing with the peaks we all love and hate.

Giving back to the community

This Plugin's development has been sponsored by the Cake Development Corporation. Contact us if you are interested in:      

Why an independent code review is important

Passbolt recently contacted us about doing a code review so we thought now would be a great time to share more about our code review process with you. While in-house and peer reviews are important to maximise code quality, it is still incredibly important to get an independent third party to review your code - that is where CakeDC can step in. Passbolt is free, open-source, self hosted password manager for teams which makes collaboration and sharing company account credentials within a team much easier. It's based on open security standards and uses OpenPGP to authenticate users and verify secrets server side. Passbolt consists of server side web app built in CakePHP providing web interface and API, and Chrome extension for client side. The overall aspects that are reviewed in our code review include a review of quality, implementation, security, performance, documentation and test coverage. When looking into quality, the team reviews aspects concerning the code following CakePHP conventions, coding standards and coding quality. Overall, passbolt’s code review revealed that CakePHP conventions and coding standards are largely followed, no concerns were detected. Implementation outlines key issues with framework use and approach. It includes reviewing the code for framework usage, separation of concerns as well as code reuse and modularity. Key recommendations are outlined at this point and guidance is given into how to solve any issues. For the Passbolt review, bigger or concerning issues were uncovered, but improvements were recommended and outlined within the closing documentation. The security portion of the code review deals with how secure the code is in terms of CakePHP usage. No security flaws were found in the passbolt code review. Our in depth code review focuses on performance, specifically investigating any bottlenecks in the code base and database as well as indexes optimization. For the full passbolt code review results, check out the Code review results. Passbolt has also posted about their review, check out their post here. If you or your company has a CakePHP application and you aren’t sure if its running at the optimum, then get in touch - Code reviews can offer insights and learning into how to improve your application.

We Bake with CakePHP