Run server locally:
bin/cake server

Migrations

Run migrations:
bin/cake migrations migrate

Rollback migrations:
bin/cake migrations rollback

Create migration:
bin/cake bake migration CreateProducts name:string description:text created modified

  • The primary key column named id will be added implicitly.
  • default column type will be string if not mentioned
  • created and modified will be created as datetime

Add Column to an existing table:
bin/cake bake migration AddPriceToProducts price:decimal

Add Column and Index to an existing table:
bin/cake bake migration AddNameIndexToProducts name:string:index

And for more on migrations, check this page

Create Model, Views, Controllers (equivalent to scaffolding in Rails)

  1. Create the migration
  2. Run the migrations
  3. Run bake all command for the resource. For products that would be:
    bin/cake bake all products

Model Validations

Model validations are done in:
src/Model/Table/ProductTable.php inside validationDefault method

Example validation:

public function validationDefault(Validator $validator)
{
  $validator
    ->notEmpty('name')
    ->add('name', 'unique', ['rule' => 'validateUnique', 'provider' => 'table', 'message' => 'Name should be unique']);

  return $validator;
}

Model Associations

Model associations are done in: (same file as above)
src/Model/Table/ProductTable.php inside initialize method

public function initialize(array $config)
{
  ....
  $this->belongsTo('Projects', [
      'foreignKey' => 'project_id'
  ]);
  ....
}

Console

Is there a console similar to bin/rails c ? Yes there is one

bin/cake console

To find a list of all projects:

>>> $projects = Cake\ORM\TableRegistry::get('Projects');
=> App\Model\Table\ProjectsTable {#208
     +"registryAlias": "Projects",
     +"table": "projects",
     +"alias": "Projects",
     +"entityClass": "App\Model\Entity\Project",
     +"associations": [],
     +"behaviors": [
       "Timestamp",
     ],
     +"defaultConnection": "default",
     +"connectionName": "default",
   }

>>> $projects->find()->all();
=> Cake\ORM\ResultSet {#242
     +"items": [
       App\Model\Entity\Project {#256
         +"id": 1,
         +"name": "Project one update",
         +"description": "description here ",
         +"created": Cake\I18n\FrozenTime {#257
           +"time": "2016-09-02T14:43:29+00:00",
           +"timezone": "UTC",
           +"fixedNowTime": false,
         },
         +"modified": Cake\I18n\FrozenTime {#244
           +"time": "2016-09-02T14:43:38+00:00",
           +"timezone": "UTC",
           +"fixedNowTime": false,
         },
         +"[new]": false,
         +"[accessible]": [
           "*" => true,
         ],
         +"[dirty]": [],
         +"[original]": [],
         +"[virtual]": [],
         +"[errors]": [],
         +"[invalid]": [],
         +"[repository]": "Projects",
       },
     ],
   }

List Routes:

bin/cake routes

Creating namespaced controllers

for creating routes like /admin/users/5

To bake everything:
bin/cake bake all Users --prefix=admin

To bake controller:
bin/cake bake controller Users --prefix Admin

To bake views:
bin/cake bake template Users --prefix Admin

How to do User password hashing?

Open the user entity file src/Model/Entity/User.php
Add use Cake\Auth\DefaultPasswordHasher;
Add this method:

protected function _setPassword($password)
{
  return (new DefaultPasswordHasher)->hash($password);
}

Now user password will be hashed whenever a user is created or updated.

How to add Authentication component and allow user to login and logout.

Open src/Controller/AppController.php
Add the below inside initialize method. $this->loadComponent('Auth');

$this->loadComponent('Auth', [
  'authenticate' => [
    'Form' => ['fields' => ['username' => 'username']]
  ]
]);

CakePHP standard is to use an username and password for loging in. If email is used instead of username, the code will look as below:

$this->loadComponent('Auth', [
  'authenticate' => [
    'Form' => ['fields' => ['username' => 'email']]
  ]
]);

Next we need to setup a login and logout method:

Open src/Controller/UsersController.php

and paste the login and logout methods

public function login()
{
    if ($this->request->is('post')) {
        $user = $this->Auth->identify();
        if ($user) {
            $this->Auth->setUser($user);
            return $this->redirect($this->Auth->redirectUrl());
        }
        $this->Flash->error(__('Invalid email or password, try again'));
    }
}

public function logout()
{
    return $this->redirect($this->Auth->logout());
}

create Login Form at: src/Template/Users/login.ctp

<div class="users form">
<?= $this->Flash->render('auth') ?>
<?= $this->Form->create() ?>
    <fieldset>
        <legend><?= __('Please enter your email and password') ?></legend>
        <?= $this->Form->input('email') ?>
        <?= $this->Form->input('password') ?>
    </fieldset>
<?= $this->Form->button(__('Login')); ?>
<?= $this->Form->end() ?>
</div>

How to show user logged in / logged out info in navbar

Add this in src/Template/Layout/default.ctp

<ul class="right">
  <?php if ($this->request->session()->read('Auth.User')): ?>
    <li><a>Logged in as <?php echo $this->request->session()->read('Auth.User.email') ?></a></li>
    <li><a href="/users/logout">Logout</a></li>
  <?php else: ?>
    <li><a href="/users/login">Login</a></li>
  <?php endif; ?>
  <li><a href="/">Home</a></li>
</ul>

How to print to log files?

In the controller
$this->log($this->request->params);

tail log files from the application root path:
tail -f logs/error.log logs/debug.log

current_user ?

$this->request->session()->read('Auth.User')

current_user email: $this->request->session()->read('Auth.User.email')