CakeDC Blog

TIPS, INSIGHTS AND THE LATEST FROM THE EXPERTS BEHIND CAKEPHP

CakePHP Migrations plugin: easily version and deploy whole applications

This article is a quick introduction to the Migrations plugin, open sourced a few weeks ago by our company. You will see how simple it is to use the plugin and what you could do with it. I hope this article will show you the benefits of using migrations in your CakePHP applications and make you give it a try right after the reading!

Here is a one-sentence description of the plugin: the Migrations plugin allows developers to easily version and automate the creation / update process of any database schema and application data from the command line.

For information, CakeDC uses this plugin on its project since several years to make team collaboration and deployment easier. The plugin has been entirely rewritten a few months ago and fully tested (code coverage >95% as always at CakeDC) before being open sourced under the MIT license. It is now available to the community along with its documentation... and it is free!

Why is it useful?

It has been a while since companies integrated Source Code Management in their development process and CVS, SVN, Mercurial or Git are now common tools. Inspired from the open source movement it is also a good practice for single developers to version application source code.

As you might know, an application almost always depends of the database schema it is aimed to use... however it is not easy to version both the source code and database schema with a SCM. Let's take the example of a CakePHP application: until now the only way to do was to version a single file, either a sql dump or a CakePHP schema.php file generated with the cake schema shell. These two approaches are not very convenient to use on a daily basis, the first one forcing the developer to drop and recreate the whole database every time!

Moreover, a web application development is never really finished (there are always new features to add, software updates or bug fixing to do...) and deploying these change on a test or production server is always a delicate task.

Here comes the Migrations plugin! It provides a simple and easy way to version a database... and to perform many other different tasks thanks to its callback system. Here are some features:

  • keep a local database schema up-to-date: you just have to run all non applied migrations to update the local database schema to the latest version
  • make team work easier: when several developers work on the same application it is important that all of them work with the same database schema during all the development cycle. With migrations every commit is tied to the database schema at this precise instant, which makes easy switching branches and resetting a branch to a specific commit.
  • make installation and updates easier: ready to push the new version of your application live? You will only have to push the sources on the server and run all non applied migrations!
  • migrate more than database schema: the callback system allows you to do everything you want before (or after) applying (or reverting) each migration. Here are some examples: creating an initial admin account, add initial or test data to the application (lorem ipsums, categories, content...), update values from the database, send an email if debug > 0... The only limit may be your imagination ;)

Where can I find the code?

Announced a few weeks ago, a packaged version of the plugin can be downloaded from the "Plugins" section of CakeDC.com. This page contains a link to download the 1.0 version, the plugin documentation and the Github project for tickets and direct Git access to the repository.

To make people aware of the need to show their support to the Cake Software Fundation by donating a few bucks (this is unfortunately not done enough), the plugin was first available to donors only. The "Download without donation" button was added later, when the repository was made public! However, if you find this plugin useful please consider making a donation to the CSF... that is the best thing you could do for thanking us.

Even better! A sample application was also released for those who want to see how migrations could be used and integrated in an application. To play with it, Download the code or git clone the project using:

git clone git://codaset.com/cakedc/sample-migrations-application.git sample_migrations

You will only need to create a database.php configuration file and update CakePHP's core location to make the application work. Git users, run

git submodule init
git submodule update

to automatically add the migrations plugin as a submodule!

What do I need to use it in my application?

Note: the packaged plugin is for the CakePHP 1.3 version only. You can either download the 1.3-beta package of the framework, or use the 1.2 branch available in the Git repository.

Adding the plugin to an existing application is very simple. If you downloaded the archive containing the plugin code, unzip it in the "/plugins/migrations" folder of your application. Git users can add it as a submodule with the following command:

git submodule add git://codaset.com/cakedc/migrations.git plugins/migrations

To check that it is installed correctly, execute the following command from your application root (it will display the available command to use the plugin):

cake migration help

If you encounter any problem here, please read the official documentation about CakePHP's console usage.

How does it work?

This post is not aimed at providing a comprehensive tutorial on how to use the plugin, thus I will just introduce the most useful commands along with some use cases.

For a complete documentation, please read the official documentation provided on the plugin page. For a simple (but useful for understanding purpose) use case you can take a look at the sample application introduced above. Going through the commit history will allow you to understand how migrations could be used in a development process.

Create a migration

To generate a new migration, type the following command

cake migration generate

The tool will ask you to give a name to the migration and suggest to do a dump of the current database schema. If a "schema.php" file is found in the application, it will ask you if you want to generate a diff between this schema and your current database one.

Generated migration files will be added to the "/config/migrations" application directory.

Apply / Revert migrations

When you pull an application containing migrations, several commands are available to apply or revert migrations. The simplest one is:

cake migration

It will display all the found migrations along with their status (applied or not applied) and id number. Just enter a migration number to update your database to the correct version. Some convenience commands are also available. You can use:

cake migration up, down, all or reset

These commands will respectively:

  • apply the next migration
  • revert the latest applied migration
  • apply all non applied migrations (and thus update the schema to the most recent version)
  • revert all applied migrations (and empty the database)

Migrations for plugins

Adding plugins to an existing application often implies adding new tables to the database or altering existing ones. The Migrations plugin brings a quick and efficient way to automate this installation. On the one hand developers can easily add necessary migrations to their plugin (making upgrades easier), on the other hand users can apply them as easily.

The only difference compared with commands introduced above is the parameter "-plugin pluginname" that needs to be added. Here is how the user will install the database for the newly added / updated plugin "test":

cake migration run all -plugin test

I would like to highlight the fact that callbacks allow the developer to do everything they want before / after each migration. It is convenient for adding initial data, and one can even implement a callback method opening the bootstrap.php file to append plugin's configuration entries there (it is just an example ;)).

... going further

Of course, feel free to add any remark or example of migrations use in the comments.

As this post is not aimed at providing support for the plugin, I recommend you to use the official tools available:

  • If you found a bug or want to suggest enhancements: open a ticket!
  • An installation problem or a question about the plugin usage? Ask your question to the community!
  • You would like a custom version of this plugin, or professional related services... contact us, it is our job ;)

I hope you enjoyed this post, it is now time for you to start playing with the Migrations plugin...

Latest articles

Build a Single Page Application Using CakePHP and InertiaJS

Build a Single Page Application using CakePHP and InertiaJS

  The Inertia Plugin allows a CakePHP application to integrate Vue 3 components in the front end, without the need to write a specific API for data transfer. This is done  by adding a Middleware and view classes that facilitate the conversion of objects and data in JSON almost automatically, as well as the direct load in the components. The plugin is thought of as a base to extend and use your app’s specific controllers and views from. Just because  it works out of the box doesn't mean it is intended to be used exactly as is,  but this will  provide you a good kick start. See the repo here: https://github.com/CakeDC/cakephp-inertia

Requirements

  • CakePHP 4.5
  • PHP >= 8.1
  • NodeJS 18.9 (only for build Vue Components, not required on running site)

 

Step 1: Create a basic CakePHP install

  For this example I will use a basic installation using Docker and Composer.  First you must create project from cakephp/app  
$> composer create-project --prefer-dist cakephp/app:~4.5 inertia_app $> cd inertia_app $> cp config/app_local.example.php config/app_local.php
  Then write an docker-compose.yml file as:
version: '3' services:   psql13:     image: postgres:13     container_name: inertia-app-postgres13     volumes:       - ./tmp/data/inertia-postgres13__db:/var/lib/postgresql:delegated     environment:       - POSTGRES_USER=my_app       - POSTGRES_PASSWORD=secret       - POSTGRES_DB=my_app       - PGUSER=my_app       - PGDATABASE=my_app       - PGPASSWORD=secret     ports:       - '7432:5432'     cakephp:     image: webdevops/php-nginx:8.1     container_name: inertia-app-cakephp     working_dir: /application     volumes:       - ./:/application:cached       - ~/.ssh:/home/application/.ssh:ro     environment:       - WEB_DOCUMENT_ROOT=/application/webroot       - DATABASE_URL=postgres://my_app:secret@inertia-app-postgres13:5432/my_app     ports:       - "9099:80"
  Launch the container and go to http://localhost:9099/  
$> docker-compose up -d
 

Step 2: Add CakePHP Inertia plugin

  Install plugin via command line:
$> composer require cakedc/cakephp-inertia
  Once installed enable it in src/Application.php, adding at the bottom of bootstrap function:
$this->addPlugin('CakeDC/Inertia');
  or by command line:
$> bin/cake plugin load CakeDC/Inertia

 

Step 3: Create Vue App and install it

  To create Vue App type in command line:
$> bin/cake create_vue_app
  This command create in the resources directory the files that use our App, also create in root directory the files:
  • webpack.mix.js
  • package.json
  Then in root directory install with NPM:
$> npm install

 

Step 4: Create simple SPA (Single Page Application)

  Create a single page called dashboard that show values sets in a controller action We need to first add InertiaResponseTrait  
use CakeDC\Inertia\Traits\InertiaResponseTrait;   class PagesController extends AppController {    use InertiaResponseTrait;    ...  ...   }
  Create a new function that would look like this:
public function dashboard() {   //set default php layout of plugin that use vue   $this->viewBuilder()->setTheme('CakeDC/Inertia');     $page = [       'text' => 'hello world 1',       'other' => 'hello world 2',   ];   $this->set(compact('page')); }
  in config/routes.php uncomment lines to catch all routes:
$builder->connect('/{controller}', ['action' => 'index']); $builder->connect('/{controller}/{action}/*', []);
and comment line:
$builder->connect('/pages/*', 'Pages::display');
  Then create file resources/js/Components/Pages/Dashboard.vue that would look like this:
<script setup> import Layout from '../Layout' import { Head } from '@inertiajs/vue3' import {onMounted} from "vue";   defineProps({     csrfToken: String,     flash: Array,     page: Array, })     onMounted(() => {     console.log('Component Dashboard onMounted hook called') }) </script>   <template>     <Layout>         <Head title="Welcome" />         <h1>Welcome</h1>         <p>{{page.text}}</p>         <p>{{page.other}}</p>     </Layout> </template>
  On root directory execute:
$> npm run dev
  IMPORTANT: Whenever you modify the .vue templates, you must run this script. Go to http://localhost:9099/pages/dashboard to see that Dashboard Vue Component prints values assignments on Dashboard CakePHP function.
   

 

Step 5: Bake CRUD system

  For this example, we use sql file on config/sql/example/postgresql.pgsql   That creates a database with the relations     Once the database has been created, bake models and controllers as normal using:
$> bin/cake bake model Pages --theme CakeDC/Inertia $> bin/cake bake controller Pages --theme CakeDC/Inertia $> bin/cake bake model Tags --theme CakeDC/Inertia $> bin/cake bake controller Tags --theme CakeDC/Inertia $> bin/cake bake model Categories --theme CakeDC/Inertia $> bin/cake bake controller Categories --theme CakeDC/Inertia
  and bake templates using vue_template instead of template as:
$> bin/cake bake vue_template Pages --theme CakeDC/Inertia $> bin/cake bake vue_template Tags --theme CakeDC/Inertia $> bin/cake bake vue_template Categories --theme CakeDC/Inertia
  Again run:
$> npm run dev
  You can the results from this example by going to http://localhost:9099/pages/index   In the following recording you can see how to add, edit and delete a record without reloading the page at any time.

 

Step 6: Using prefix and adding a navigation menu

  Add route to prefix Admin on config/routes.php
$builder->prefix('admin', function (RouteBuilder $builder) {    $builder->fallbacks(DashedRoute::class); });
  To generate controllers and template with a prefix use --prefix option of bake command as:
$> bin/cake bake controller Pages --prefix Admin --theme CakeDC/Inertia $> bin/cake bake controller Tags --prefix Admin --theme CakeDC/Inertia $> bin/cake bake controller Categories --prefix Admin --theme CakeDC/Inertia $> bin/cake bake vue_template Pages --prefix Admin --theme CakeDC/Inertia $> bin/cake bake vue_template Tags --prefix Admin --theme CakeDC/Inertia $> bin/cake bake vue_template Categories --prefix Admin --theme CakeDC/Inertia
  You can add a horizontal menu to navigate through controllers   Edit resources/Components/Layout.vue and put inside header tag links as:
<header>    <Link as="button" href="/pages/index" class="button shadow radius right small">Pages</Link>    <Link as="button" href="/tags/index" class="button shadow radius right small">Tags</Link>    <Link as="button" href="/categories/index" class="button shadow radius right small">Categories</Link> </header>
  Again run:
$> npm run dev
  You can see the results from this  example by going to http://localhost:9099/admin/pages/index   In the following recording you can see how to add, edit and delete a record without reloading the page at any time and navigate through pages, tags and categories.

  Hopefully this example will make your experience easier! Let us know: [email protected].

When and why should you upgrade to CakePHP 5?

CakePHP 5.0.0 was released on September 10th. The current version as of today is 5.0.3 (released Nov 28th and compatible with PHP 8.3 https://github.com/cakephp/cakephp/releases/tag/5.0.3). You might be asking yourself some questions related to the upgrade… here's what we've been recommending to our clients to do since version 5 was released. Leaving aside the obvious reasons for an upgrade, today we're going to categorize the decision from 2 different points of view: Your current CakePHP version, and your role in the project.

When should you upgrade? 

  We are going to use current CakePHP version as the main criteria: * If you are in CakePHP <= 2   * We strongly recommend an upgrade as soon as possible. If you are unable to upgrade, try to keep your PHP version and all the underlying dependencies as fresh as you can and isolate the application as much as possible. If your application is internal, consider using a VPN blocking all outside traffic. If your site is open to the public, consider using an isolated environment, hardened. Adding a web application firewall and a strict set of rules could also help to mitigate potential security issues. Even if CakePHP is very secure, the older versions of CakePHP, like  1 and 2  have a very old code base , and other vendors/ libraries could be a serious security risk for your project at this point.   * If you are in CakePHP 3.x   * The effort to upgrade at least to CakePHP 4.x should not be a blocker. We would recommend upgrading at least to the latest CakePHP 4.5.x. You can actually "ignore" the deprecations for now, you don't need to plan for upgrading your authentication/authorization layers just yet, focus on getting your project stable and up to CakePHP 4.5.x in the first round.   * If you are in CakePHP 4.x   * Upgrading to CakePHP 5.x is not an immediate priority for you.   * I would say, 2024 is a good time to start planning for an upgrade. Feature and bugfix releases for 4.x will continue until September 2025. Security fixes will continue for 4.x until September 2026. You have plenty of time to consider an upgrade, and take advantage of newer (and faster!) PHP versions.  

Why should you upgrade? 

  We are going to use your role in the project to provide some good reasons: * If you are a developer   * More strict types, meaning better IDE support and more errors catched at development time.   * New features in CakePHP 5.x will make your code more readable, like Typed finder parameters https://book.cakephp.org/5/en/appendices/5-0-migration-guide.html#typed-finder-parameters      * Quality of life features, reducing development time like https://book.cakephp.org/5/en/appendices/5-0-migration-guide.html#plugin-installer   * Compatibility with PHP 8.3 for extra performance & support   * If you are a manager   * Ensure your development team is forced to drop old auth code and embrace the new authentication/authorization layer https://book.cakephp.org/5/en/appendices/5-0-migration-guide.html#auth   * The new authentication layer will allow you to easily integrate features like single sign on, two factor authentication or hardware keys (like Yubikeys), as there are plugins available handling all these features.   * Get an extended support window. CakePHP is one of the longest maintained frameworks out there, upgrading to CakePHP 5 will keep your core maintained past 2026.   * Upgrade to PHP 8.3 and force legacy vendors to be up to date with the new version, this will also push your team to get familiar with the new PHP core features.   * If you are an investor, not directly related with the project day-to-day operations   * Secure your inversion for a longer period.   * Reduce your exposure to security issues.   * Send a strong message to your partners, keeping your product updated with the latest technology trends.   * Send a strong message to your team, investing in the upgrade of your application will let them know the project is aiming for a long term future.   In conclusion, upgrading to CakePHP 5 is a good move for 2024 whether you're a developer, manager, or investor. The version 5 is stable and ready to go. Staying current becomes not just a best practice but a strategic advantage.   If you are in doubt, feel free to contact us. We'll review your case (for free) and provide an actionable recommendation based on your current situation in the next business day.  

A quick CakePHP Local environment with DDEV

In the realm of web development, a seamless local environment is the bedrock for efficient and stress-free coding. Enter DDEV, a powerful tool that simplifies the setup process and empowers developers to dive into their projects with ease. In this blog post, we'll embark on a journey to demystify the process of setting up a local development environment using DDEV. Whether you're a seasoned developer or just starting in the world of web development, optimizing your local environment can significantly enhance your workflow.

Pre Conditions :

Install Docker https://docs.docker.com/get-docker/ and install DDEV https://ddev.readthedocs.io/en/stable/

Step 1: Create a new CakePHP project skeleton 

composer create-project cakephp/app myproject A new folder "myproject" will be created with a CakePHP project skeleton inside. Go to this new directory and proceed with the following instructions.

Step 2: Initial ddev setup

Run ddev config
This will do the initial ddev setup, press enter for all questions.  Run ddev auth ssh
This will add ssh key authentication to the ddev-ssh-auth container

Step 3: Adjust the settings

Inside "myproject" a new .ddev folder will be created, open config.yaml  and adjust there: php version, database and the database url environment.  For PHP:
php_version: "8.1"

For the database: database: type: mysql version: "8.0" For the environment variable: web_environment: - DATABASE_URL=mysql://db:db@db/db

Step 4: Start ddev

ddev start  This will spin up the project.

Step 5: Open your application

ddev launch This will open your project in a browser.   Once you have the application up and running, some useful commands you could run are:
  • ddev composer to execure composer
  • ddev mysql to get into the database
  • ddev ssh takes you into the web container.
In this link https://ddev.readthedocs.io/en/latest/users/usage/cli/ you can see more useful commands.   Hope you enjoy playing with DDEV!

 

   

 

 

We Bake with CakePHP