CakeDC Blog

TIPS, INSIGHTS AND THE LATEST FROM THE EXPERTS BEHIND CAKEPHP

The updates that CakePHP 3 brings to the table – why we love it and so should you!

 

With a year under its belt and 34 releases, we are still in love with CakePHP 3; and some of you are already on board and loving it. With an average of nearly 3 releases a month, you can easily tell that the team is working against a rapid release cycle where they are tirelessly working at adding and improving features. - but do you know the philosophy behind it?

Looking at all of the improvements and benefits that this updated framework brings, you can clearly see that the biggest turning point for the core team was the increased functionality with clear foresight and thinking brought to the table. A plan was had right from the start, to be a framework well documented, one that was simple (as the Core Team live by – less lines the better!). Another big input from the team, was the ability to integrate and make newer versions of PHP compatible with the framework, never before has the movement in the code base been so fast paced. And as the team comments, this is brought to the fore by the rotating code between open source teams – truly, we live in a space where without each other’s contributions to the code base there would be no movement and action.

That is why we are in love with CakePHP 3, because the team have put forward a framework that integrates, pulls in outside assistance, accepts community help and specifically puts itself out there for the community’s input.

Some quick backgrounds to the updated framework. The first commit to CakePHP 3 was done on May 24 2012, by Juan Basso. A long time coming, but as the common phrase goes, good things come with time. – that and the fact that the core team and lead developers were working in their spare time, after work, late nights, to bring this forward.

We thought that we would reflect, and bring to you the top changes/improvements/benefits/total awesomeness of this framework!

  • All of the core feature development was done as pull requests. This was done intentionally, to encourage people to get involved and the main core team is distributed across the world. The community is vital to the framework, and without them, we wouldn’t be here!

  • To give you an idea of what this has meant. It ended up with over 6000 commits before launch! – from over 20 contributors.

  • CakePHP 3 documentation had over 1500 commits – from 51 contributors! – the document writing was so important to the team, every time there was a feature or a break in backwards compatibility, it was documented.

  • More big news for CakePHP 3 is that it targets PHP 5.5 and newer. It is designed with composer support (Although you don’t need to use composer). It has also required a couple of additional extensions (the mb_string and the intl extension) – this was for 2 reasons, we were handling multi-byte internally, if you didn’t have the mb_string extension, we would fall back to pure PHP code; and for internationalization - there are really powerful tools built into the language that CakePHP 2 wasn’t capitalizing on and the team wanted to leverage those tools – to give the CakePHP community better tools.

  • Now the entire CakePHP code is Unicode aware, and additionally through the intl extension, everything is localized. All of the core classes localize depending on your locale (so if you switch your locale to Germany..) – everything will work, your numbering, date formatting, language formatting (provided you have the translation file) etc.

Over above these changes (and associated benefits), a few other things came out of the cracks..

Such as, through the use of composer, you have to have separate repos for separate things - so the team created a new app skeleton, basically this is the app directory of the old framework but in a separate repo. – What this allows you to do is mold or easily customize and fork it when you want to pull in changes. You don’t have to worry about merge conflicts with the app directory or similar types of issues.

It also gives us the ability to release them independently in the future, so for instance, the app can be upgraded and add or remove dependencies while having no need to modify the framework.

Many of us have had that experience and confusion of configuring classes; you don’t know if it’s a property or method, or even what the method name is.

Well getting more into the detailed features, we all know that there were a lot of different method names for configuring things, some classes used properties, others used methods of various names.

For CakePHP 3 however, it was decided that this is a little silly, so all of the static/instance/runtime classes use one method called config (YAY!). More can be found at http://book.cakephp.org/3.0/en/development/configuration.html

The ORM has also been replaced, we have moved on with the model layer, and CakePHP has advanced quite a bit over the past years. Now you have Tables and Entity objects (no more arrays!), and a powerful Query class to build your queries using a fluent interface. You'll be amazed how easy is to create deep filters, custom finders (and stacking!), subqueries. Validation was also refactored, improving flexibility and customization.

The router was also noted as being a performance bottleneck for a lot of applications in the past, and it was also, somewhat, verbose when you were connecting a lot of routes.

So with CakePHP 3, the old way of connecting routes is still there, but a new scope system has been added. This allows you to declare routes in a much clearer way – so if you have a common prefix, you can put this in the scope, and don’t have to re-declare this in each route. Less typing necessary, but more importantly it allows you to partition your routes so that you can create a much faster parse tree.

A lot of work has also been done on fixing reverse routing, previously it was based on a linear search but now, the key parts of the route are taken (the action or controller name) and generate a list of what that route may be and then search a much smaller subset of routes.

Another change is the helper layer. Previously HTML formatted through arrays, and that had both good and bad points.

The team got rid of the sprintf and replaced it with a very simple templating system, that has no conditions. This lets you define templates file, and you consistently use those templates throughout. This also yields a bit of a performance gain and it doesn’t use number replacements, it uses named replacements.

The way the event subsystems were handled is another change that CakePHP 3 brings to the table, allowing a much more consistent approach to handling events. The new changes have also led to another performance enhancement!

The framework has also gotten some outside help - in the past CakePHP has been criticized for being insular and not making use of the existing ecosystem. This has since changed and one of the reasons was the team wanted to make the install really easy. Because composer is now being use, you can include dependencies and when you create your application or install your applications dependencies, CakePHP 3’s can be installed at the same time.

CakePHP 3 has used:

Chronos (A fork of Carbon) has been used for date time improvements, (but now its part of CakePHP itself and maintained by the core)

Aura/Intl – improved i18n and L10n features

A great wrap up to these things is the fact that the team has hugely increased functionality and features, while keeping performance constant (in most cases, actually increasing it!!). There are so many reasons that you should start and continue using CakePHP 3 but more importantly, there are so many reasons for being a part of this insanely great, collaborative community.

Latest articles

CakePHP 4 - First Look

Last december, the CakePHP team announced the immediate availability of 4.0.0. This release begins a new chapter for CakePHP, as 4.0 is now API stable. With this release, Cake 3.x moves into maintenance mode, while 2.x moves into security release mode. The promise of the version is: cleaner, faster and still tasty as usual. I had the opportunity to bake a new application from scratch and I will give my feedback about my process.  

Skeleton Design

The new version refreshes the skeleton design of the application. Now we have 2 new folders on root:
  • Templates

The templates folder has presentational files placed here: elements, error pages, layouts, and view template files. Pay attention for subfolders: 
  • Core templates are lowercase: cell, element, email, layout
  • App templates still uppercase: Error, Pages
  • Resources

The resources folder has subfolders for various types of resource files.  The locales* sub folder stores string files for internationalization.   If you are familiar with i18n, you will see the difference:
  • src/Locale/pt_BR/default.po (3.x)
  • resources/locales/pt_BR/default.po (4.x)
  Another important change was the .ctp files. They are moved for .php. CakePHP template files have a default extension of .php now. We have a new config/app_local.php file, which contains the configuration data that varies between environments and should be managed by configuration management, or your deployment tooling.  

PHP Strict Type Mode

In PHP the declare (strict_types = 1); directive enables strict mode. In strict mode, only a variable of exact type of the “type declaration” will be accepted, or a TypeError will be thrown. The only exception to this rule is that an integer may be given to a function expecting a float. This is a feature from PHP 7 - which we strongly recommended. All codebase from the skeleton and files generated by bake will include the function.  

Entities

The preferred way of getting new entities is using the newEmptyEntity() method: $product = $this->Products->newEmptyEntity();  

Authentication

After 10 years baking, that's a really big change for me. I’m not usually use plugins for authentication, I really like the Auth Component. I think many bakers would agree, as I remember on the first international meetup, the co-host shared the same opinion.   The Auth Component is deprecated, so it's better move on and save the good memories. The new way for implementing Authentication is more verbose. It requires a few steps, I don’t will detail that,  because you can easily check on book:
  • Install Authentication Plugin
  • Load the Plugin
  • Apply the Middleware
  • Load the Component
  My first look is like I said,  too verbose, for me anyway. We need to write a lot of code. Also it is not included on the skeleton of CakePHP applications, you need include by your own. https://book.cakephp.org/authentication/2/en/index.html  

HTTPS Enforcer Middleware

Contrary to the Authentication, I was really surprised how easy it was to force my Application to use HTTPS. If you are familiar with CakePHP, you will use the Security Component for that: class AppController extends Controller {      public function initialize()    {        parent::initialize();        $this->loadComponent('Security', [            'blackHoleCallback' => 'forceSSL',        ]);    }      public function beforeFilter(Event $event)    {        if (!Configure::read('debug')) {            $this->Security->requireSecure();        }    }      public function forceSSL()    {        return $this->redirect(            'https://' .            env('SERVER_NAME') .            Router::url($this->request->getRequestTarget())        );    }   }
  The implementation on version 4 is less verbose and easy, kudos for the new version:    public function middleware(MiddlewareQueue $middlewareQueue)    {        $middlewareQueue            ->add(new HttpsEnforcerMiddleware([                'redirect' => true,                'statusCode' => 302,                'disableOnDebug' => true,            ]));          return $middlewareQueue;    }   What I know is a drop, what I don’t know is an ocean. The new version is here to stay, and this article it's a just one overview of basic usage of the new version. * Version 4.1.0 is released already with more improvements and features.  

Links 

[1] Book https://book.cakephp.org/4/en/contents.html [2] Migration Guide https://book.cakephp.org/4/en/appendices/migration-guides.html  

CakeDC API plugin - Authentication and Authorization

This article covers new changes for CakePHP 4 version of plugin. So it covers versions starting from 8.x (8.0) and later.  

Permissions system. RBAC

By default, the plugin uses CakeDC Users and CakeDC Auth plugins for authentication. For RBAC it uses the same style as defined in the Auth plugin RBAC system with minor changes required for the API plugin. First, let's consider the case when we want public api without any authorization. In this case the most simple way would be is to define in config/api_permissions.php next rule   return [     'CakeDC/Auth.api_permissions' => [         [             'role' => '*',             'service' => '*',             'action' => '*',             'method' => '*',             'bypassAuth' => true,         ],      ], ];   Now, consider the case we want to use users plugin authentication. Since Api is supposed to be used from another domain, we should allow all requests with OPTIONS type. To do this we should add this rule as first on in config/api_permissions.php       [         'role' => '*',         'service' => '*',         'action' => '*',         'method' => 'OPTIONS',         'bypassAuth' => true,     ],    Here, method define OPTIONS and bypassAuth means that such actions should work for any users, including not authenticated. Now we should allow Auth service methods       [         'role' => '*',         'service' => '*',         'action' => ['login', 'jwt_login', 'register', 'jwt_refresh',],         'method' => ['POST'],         'bypassAuth' => true,     ],    All other services/actions should be declared in api_permissions file to define what user roles are allowed to access them. Imagine we want to allow the admin role to access the add/edit/delete posts and make index and view public. We can do it based on method or based on action names.       [         'role' => 'admin',         'service' => 'posts',         'action' => '*',         'method' => ['POST', 'PUT', 'DELETE'],     ],      [         'role' => 'admin',         'service' => 'posts',         'action' => ['index', 'view'],         'method' => '*',         'bypassAuth' => true,     ],   

 Routers and Middlewares

Starting from the 8.x version, API Plugin uses router middlewares. This gives great abilities to configure the plugin. So now it is possible to have separate authentication and authorization configuration for website and for api. Also, It is possible to have more then one api prefix, and as result provide more then single api for website with different configuration. Let’s take a look on the default configuration for middlewares   'Middleware' => [     'authentication' => [         'class' => AuthenticationMiddleware::class,         'request' => ApiInitializer::class,         'method' => 'getAuthenticationService',     ],     'bodyParser' => [         'class' => BodyParserMiddleware::class,     ],     'apiParser' => [         'class' => ParseApiRequestMiddleware::class,     ],     'apiAuthorize' => [         'class' => AuthorizationMiddleware::class,         'request' => ApiInitializer::class,         'params' => [             'unauthorizedHandler' => 'CakeDC/Api.ApiException',         ],     ],     'apiAuthorizeRequest' => [         'class' => RequestAuthorizationMiddleware::class,     ],     'apiProcessor' => [         'class' => ProcessApiRequestMiddleware::class,     ], ],   First we see the order of middlewares that proceed api request. It passes through AuthenticationMiddleware, AuthorizationMiddleware, and RequestAuthorizationMiddleware to perform generic auth tasks. It passes through BodyParserMiddleware to unpack the json request. And finally ParseApiRequestMiddleware does initial service analysis and ProcessApiRequestMiddleware performs the request. Also we can note CakeDC\Api\ApiInitializer class used to define Authentication and Authorization configuration. It can be redefined in the application layer to provide needed Identifiers and  Authenticators.  

 Jwt authentication - Refreshing tokens

New plugin feature is embedded jwt_login action which allows the user to get access_token and refresh_token included into the login response. Tokens should be passed in the Authorization header with bearer prefix. Access token is supposed to be used as default token and refresh token needed to get a new access token when it's expired. So for refreshing provided additional jwt_refresh action which should be used in this case.  

 Configuration

Configuration should be defined on application level in config/api.php. Need to note that it is important to enable this file to load by the Api plugin. It could be done in config/bootstrap_app.php using global configuration: Configure::write('Api.config', ['api']);       'Api' => [          ...                  'Jwt' => [             'enabled' => true,             'AccessToken' => [                 'lifetime' => 600,                 'secret' => 'accesssecret',             ],             'RefreshToken' => [                 'lifetime' => 2 * WEEK,                 'secret' => 'refreshsecret',             ],         ],    Hopefully, this was helpful. Our team is always working on adding new features and plugins. You can check out more available plugins HERE.

CakePHP Meetup: Unit Test Fixtures, Queue Plugin, PPM Bridge

Developers are used to living in a virtual world, so adjusting has been easier than expected. Recently, we’ve been holding virtual meetups, and we are so happy with the feedback. Digital training sessions allow bakers from all over the world to come together and enjoy. Our plan is to host one each month, and coordinate time zones so that everyone gets a chance to attend. Our latest one was based around a good time for our Japanese community.  If you missed the meetup, no problem. We always post the recording for playback, and I’ll even give you a quick rundown of the topics covered. Let’s jump in:

CakePHP Fixture Factory Plugin

by Juan Pablo Ramirez CakePHP Fixture Factory Plugin https://github.com/pakacuda/cakephp-fixture-factories  helps to improve the way fixtures are generated, when having a big database writing fixtures can get so complicated. This plugin provides Fixture Factories in replacement of the fixtures found out of the box in CakePHP.
Generating fixtures can be done in a few code lines reducing the effort of writing and maintaining tests. There are some other plugins to manage fixtures: 

CakePHP Queue Plugin

By Mark Scherer @dereuromark CakePHP Queue Plugin https://github.com/dereuromark/cakephp-queue is a simple Queue solution, it can be used for small applications and it’s a good one to get started with Job Queues, having something easy to maintain at the beginning is a good starting point.
Queues are a good option for functionalities like: image processing, email sending, PDF generation; to improve the response-time for heavy-processing tasks. For more robust solutions can be used:
  • CakePHP Queuesadilla  https://github.com/josegonzalez/cakephp-queuesadilla This plugin is a simple wrapper around the Queuesadilla queuing library, providing tighter integration with the CakePHP framework. We have used this plugin in CakeDC in several projects, we also had to build  a Mongo Engine for a specific client.

CakePHP PHP PM Bridge

By Jorge Gonzalez @steinkel CakePHP Bridge https://github.com/CakeDC/cakephp-phppm  to use with PHP-PM project.
PPM is a process manager, supercharger and load balancer for modern PHP applications. PHP PM It's based on ReactPHP, the approach of this is to kill the expensive bootstrap of PHP (declaring symbols, loading/parsing files) and the bootstrap of feature-rich frameworks.
It’s a good option If you want to significantly improve the responsiveness of an application that could have spikes. PM works as PHP FPM, it’s a replacement for it.  Below some benchmark:  50 Concurrent threads in 10 seconds
  • FPM 83 transactions per second, Failed 0,  Concurrency 6.58.
  • PPM 90.30 transactions per second, Failed 0, Concurrency 3.86.
200 Concurrent threads in 10 seconds
  • FPM 116,49 transactions per second, Failed 142,  Concurrency 116.64.
  • PPM 207.35 transactions per second, Failed 0, Concurrency 85.59.
1000 Concurrent threads in 10 seconds
  • FPM 109,88 transactions per second, Failed 1759, Concurrency 187.49.
  • PPM 214.91 transactions per second, Failed 0,  Concurrency 302.39.
PPM is able to handle a lot of concurrency connections coming in spike to the server  in a better way than PHP FPM.
For watching the Meetup visit the following link https://www.youtube.com/watch?v=POI0IwyqULo Stay up to date on all virtual meetups here  https://cakephp.org/pages/meetups      

We Bake with CakePHP