Best practices
DOs and DONT's of common CakePHP problems.
Config
The easiest approach for the beginning is a local config file that is not under version control per environment/server.- app.php (CakePHP core configs)
- app_custom.php (project overwriting on top)
- app_local.php (env specific, contains sensitive keys/pwds, in gitignore!)
Configure::load('app', 'default', false);
Configure::load('app_custom');
Configure::load('app_local');
The main idea here is to ease upgrading in minors as the app.php one is the one from cakephp/app repo always and it makes it easy to diff and know what new config keys are added with each minor. If you overwrite it directly, this will get very messy otherwise.
Check this applications's config folder on how it is done.
Note: You can also leave out the app_local file, and instead use env()
wrapper to read from environment variables.
People often use the env() approach on the server, and the local file on the development machine locally.
Routing
Best to use the DashedRoute class (see conventions) as default one:
use Cake\Routing\Route\DashedRoute;
Router::defaultRouteClass(DashedRoute::class);
This way your URLs are `my-prefix/my-plugin/controller-name/action-name` whereas your URL contains the CamelCase variants:
'prefix' => 'my-prefix // unmodified
'plugin' => 'MyPlugin, // camelCased
'controller' => 'ControllerName', // camelCased
'action' => 'actionName' // camelBacked
The idea is to inflect internally as less as possible.
URLs
Use array URLs wherever possible, this saves you a lot of trouble once you actually want to customize the routing:// URL /my-controller/my-action
echo $this->Html->link($title, ['controller' => 'MyController', 'action' => 'myAction']);
You can then alter the URLs via Routing and all those URLs change cleanly. The speed issue can be neglected compared to the advantages of the flexibility.
You can also use "named routes", of course (`['_name' => 'admin:account:password']`). This centralizes the arrays into the routes config.
Don't sanitize the heck out your data
Use Sanitization wisely, and not blindly.Not without reason the Sanitize class has been kicked out of the core files.
Sanitization is useful and necessary, when working with HTML content, that needs to be stripped of invalid/dangerous markup. But here it is best to use plugins specifically written for this job.
For most normal use cases, by using save(), SQL injections are already prevented. No need to modify the data upon save. Only use h() in the view to secure (stringish) output by escaping potentially dangerous chars:
echo h($entity->name);
Logging
By default the log streams catch all, even scoped logs that should only go to those scoped listeners. As a result they are duplicated.So I would change the scopes to `null` here for all default listeners:
// in your app.php config
'Log' => [
'debug' => [
'scopes' => null,
],
'error' => [
'scopes' => null,
],
...
],
Another very useful addition is to log 404s separately from actual (internal) errors happening using Tools.ExceptionTrap.
Use AJAX wisely
Don't over-ajaxify your views. It can easily create complications and become error-prone. Use it wisely where it makes sense.
Also always try to provide a non-JS fallback solution in case the JS breaks or cannot work properly in some browsers. It might also be a good idea for search engines to properly pick up your site content (e.g. when using pagination and AJAX).
So the smart approach is: First code the non-JS functionality. And then you can add JS-functionality for it on top. In case the JS breaks, the non-js part can take over without users being unable to proceed.
Deployment
You should automate your deployment process, e.g. via basic deploy.sh file. Then you can just execute `./deploy.sh`.
Always use your `www-data` user for this and never root, otherwise you will have some serious permissions problems afterwards.
The following file is an example sh script for a very very basic single server update process:
#!/bin/bash
bin/cake maintenance_mode activate
echo "### CODE ###";
git pull
php composer.phar install --prefer-dist --no-dev --optimize-autoloader --no-interaction
mkdir -p ./tmp
mkdir -p ./logs
mkdir -p ./webroot/js/cjs/
mkdir -p ./webroot/css/ccss/
echo "### DB MIGRATION ###";
bin/cake migrations migrate -p Geo // and all other plugin migrations
bin/cake migrations migrate
echo "### ASSETS ###";
bower install // or npm -i etc
mkdir -p ./webroot/css/fonts
cp -R ./webroot/assets/bootstrap/dist/fonts/* ./webroot/css/fonts/
bin/cake asset_compress build
echo "### CLEANUP ###";
bin/cake cache clear_all
echo "### CACHE WARMING ###;
bin/cake schema_cache build
echo "### DONE ###";
bin/cake maintenance_mode deactivate
It should at least contain:
- composer install (from lock file!)
- DB Migration
- Asset update
- Cache invalidation
Wrapping it with maintenance mode can help to avoid side effects for users currently on the website.
Note that the above script is after initial deployment. For a first checkout, you will need to clone the repository and probably set up a few more things like your app_local.php.