CakeDC Blog

TIPS, INSIGHTS AND THE LATEST FROM THE EXPERTS BEHIND CAKEPHP

Basic CakePHP markup for designers

This article assumes you practice semantic markup and have a fairly good understanding of CSS.

CakePHP does a number of things automatically that designers might not expect, which can cause confusion for designers and difficulty for developers in implementing markup. I hope to provide some general purpose information and guidelines to designing for a CakePHP site. I would like to make a couple quick notes first however. CakePHP is a very flexible platform where markup can be re-used very easily. The more you as a designer try to make reusable markup, the easier your developers life will be. One of the most important things that you can do is to avoid id's other than for top level wrappers such as columns. This allows the developer to change content to address shifting specifications without having to rewrite chunks of CSS in order to avoid Id conflicts in the generated markup.

CakePHP has a flexible output system that lets developers easily specify how output is generated. Unlike some applications such as older CMS systems which have a specified header and footer that are called before and after the content, Cake applications render their (x)html into a layout. Two main types of output are rendered into a layout, Views and Elements. Views are the page specific content, such as a blog post, or an entry form. Elements are blocks of markup that can be used across multiple pages, and can be used in the layout, in the view, or even from inside another element.

Form related tags can appear in any of the output region types, but it is helpful if you as a designer try to avoid having forms span multiple elements or different sections. Doing so makes it much easier to ensure that the form will work correctly every time it appears. By default most form elements are wrapped in a div with descriptor classes such as “input text” for a text field. Check boxes, and radio buttons are wrapped in a fieldset instead of a div. Also by default the form helper automatically generates id's for the form input widget, and a label that matches it. This is another situation where it is easier to avoid an id attribute and use a class name as a designer. If you specify and ID, your developer has to check that it has not been used in CSS to specify a style, or choose to override it with your specified value and loose flexibility in the future.

Examples of form widgets:

Select box:


 

Blog blog.

Text field:


 

Title

Check Boxes:


 

Status

Published

Allow Comments

Moderate

 

The other CakePHP core utility that generates a fair amount of HTML is the paginator helper. While the helper itself has been covered on the bakery before and is worthy of several blog posts itself, I'd at least like to touch on the default markup generated by the helper.


 

You can easily specify a string that will appear in between the spans, and each of the other elements are called separately, so they can be in other spots on the page, or have markup between. Unfortunately it is not easily possible to remove the span from the markup, but it would be fairly easy to change the pagination output to something similar to this:


 
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