CakePHP 2.x to CakePHP 3.x

Converting to the new version of CakePHP was supposed to be a breeze I thought.
Not really. They changed a lot of stuff regarding Models and database manipulation, so we have to rewrite a lot of code.
Most notable changes are:


  • The folder structure obviously, every important MVC part is now hidden in the src/ folder instead of the App/ folder.
  • The usage of namespaces, finally!


  • Models are no longer used to access data from a database. This is now done through the tables, the Model\Table classes. A Model\Table class represents a database Table. Models as we knew them are no longer used, and instead the logic will need to be moved to the Model\Table classes.
  • Model\Table query results no longer return Arrays. Instead they return a list of Entity objects.
  • Entity objects are a representation of 1 database row. As such they can be manipulated from the object itself.
  • To save a change to any Entity you will need to pass the complete Entity to the Model\Table class’ save function; Model\Table::save(Entity);
  • Model associations are saved automatically when you add the associated Entities to the Entity you wish to add them to, and save the Entity;
    // Load weekschedule entity
    $currentLoadedWeekschedule = $this->Weekschedules->get(34);
    // Create new Timetable entity
    $newTimetable = $this->Timetables->newEntity(['name' => 'test', 'desc' => 'test2']);
    // Add related Timetable to weekschedule
    $currentLoadedWeekschedule->timetables = $newTimetable;
    // Eventually, save this weekschedule and its related Timetable
  • All time fields from the database are now returned as a Cake\I18n\Time object instead of as a string. You can easily manipulate these object to view as a string again though:
    echo $period['startdatetime']->i18nFormat("YYYY-MM-dd HH:mm:ss");
  • Same goes for saving the DATETIME fields, create a new Time() object for that field.
    use Cake\I18n\Time;
    $entity['startdatetime'] = new Time($data['startdate'] . ' 00:00:00');
  • Because you get an object with entities returned now, there are now longer big arrays you need to unwind, things like $var[‘Table’][‘TableLinked’][‘LinkedTable2’][‘data’]; are no longer needed!
  • Support for cascading deletes! If the Model associations are set correctly and to ‘dependent’ and ‘cascadeCallbacks’, you will automagically remove all associated underlying entities.
    $this->hasMany('Weekschedules', [
        'foreignKey' => 'period_id',
        'dependent' => true,
        'cascadeCallbacks' => true
    $this->hasMany('Timetables', [
        'foreignKey' => 'weekschedule_id',
        'dependent' => true,
        'cascadeCallbacks' => true
    $deletedPeriod = $this->Periods->get($this->request->data['data']['Period']['id']);
  • Copying Entities with child-entities is a breeze! Where as we previously needed a script to;
    create a copy of the parent entity, submit that, get its id, use that to save the new children with the parents id, and save each child.

    We can now easily copy a complete entity and its children with the following lines (in the Model);

    public function copy($weekschedule_id){
        // Find original weekschedule
        $originalWeekschedule = $this->get($weekschedule_id, ['contain' => 'Timetables']);
        // Create new weekschedule entity with the same properties 
        // and timetables as the original one
        $copiedWeekschedule = $this->newEntity($originalWeekschedule->toArray());
        $copiedWeekschedule->set('name', __('Copy of ') . $copiedWeekschedule['name']);
        // Save this new weekschedule
        $newWeekschedule = $this->save($copiedWeekschedule);
        return $newWeekschedule;

Views / Helpers

  • The FormHelper has been rewritten to use the new ORM. The FormHelper action ‘end()’ no longer creates a submit button. Instead, call the following:
    // Cake\View\Helper\FormHelper\submit(string $caption, array $options);
    echo $this->Form->submit(__('Rearrange weekschedules'), ['class' => 'btn']);
    // Dont forget to close your Form or it will include all other input fields on the page
    echo $this->Form->end();

There will be more changes, but these are the ones I found important and most changing for us for now.

Leave a Reply

Your email address will not be published. Required fields are marked *