Cakephp create a simple API

This tutorial for cakephp version 4, here we will learn how we can create a simple API using cakephp.

Our goal is we will create an API to save category if doesn’t exist !

Very beginning we will create a resources route in cakephp. Here, you may ask what is the resource route ? Answer is resource route will accept all http VERBS. Example GET,POST,PUT,DELETE,PUT

Now let’s go in cakephp source in location config/routes.php Go to the end of the line and create a new route scope for your API. Example 

$routes->scope('/api', function (RouteBuilder $routes) {
   $routes->setExtensions(['json']);
   $routes->resources('Categories',[

       'path' => 'category',
       'prefix' => 'Api',
       'map' => [

           'addCategory' => [
               'action' => 'addCategory',
               'method' => 'POST',
               'path' => '/add-category'
           ],
       ]
   ]);
});

Here , You can see I have created a route for my categories controller where I have an action called addCategory

So, Let’s create a class in location src/Controller/Api
Note : Create a folder with name Api, because in route we have used prefix Api

Now your CategoriesController.php will looks like below.

 

<?php

namespace App\Controller\Api;
use App\Controller\AppController;
use Cake\Event\EventInterface;
use Cake\ORM\TableRegistry;

Class CategoriesController extends AppController 
{
   public function addCategory()
   {

       $this->request->allowMethod(['post']);
       $category = $this->Categories->patchEntity($this->Categories->newEmptyEntity(), $this->request->getData());
       $this->set('category',$this->Categories->findOrCreate(
                   ['name'=>$this->request->getData('name')],
                   function()use($category){
                       return $category;
                   }
               )
           )
       ;
       $this->viewBuilder()->setOption('serialize', ['category']);
    }
}

Don’t forget to create a model for categories ! You can use a simple bake command to create a model for categories table.

bin/cake bake model categories

So, We have done it ! Now let’s test in postman , you can test it postman using below URL

http://localhost/api/category/add-category.json

Set body name = your-category-name

Also send a post request !

Cakephp get last month summary report.

Example we have a table called transactions.Where transactions has 3 fields 

Id | amount | created 

We need to fetch last month’s summary by the created date. So, in cakephp we can write like below

public function report()

{
       $targetDate = FrozenTime::now()->modify('1 month ago');
       $query = $this->Transactions->find();
       $query
          ->select(
           [
               'created',
               'amount'=> $query->func()->sum('Transactions.amount')
           ]
       )
       ->where([
           'Transactions.created >=' => $targetDate->startOfMonth(),
           'Transactions.created <=' => $targetDate->endOfMonth()
       ])
       ->group('Transactions.created');
       $this->set("transactions",$this->paginate($query));
   }

Here I have used cakephp FrozenTime class.
So, top in our class we have to use

use Cake\I18n\FrozenTime;

In view you can write below foreach loop to print data.

<?php foreach ($transactions as $transaction): ?>
        <tr>
             <td><?= $transaction->created->format("Y-m-d") ?></td>
             <td><?= $transaction->amount ?></td>
        /tr>
 <?php endforeach; ?>

Cakephp gives a limit on associative/relational data.

Example we have two tables, one is articles and another is comments table. Articles hasMany relations with comments. 

Example our articles table looks like 

articles 

id |  title | created | modifier 

Comments

Id | comment | article_id | created | modified 

Assuming in articles table we have build  a  hasMany relation with comments like below example

 

$this->hasMany('Comments', [
     'foreignKey' => 'article_id',
 ]);

Here, article_id is the foreign key.

Now, in the ArticlesController/index method we will write a query where we want only the last two comments. 

So, we can write our index method like below

public function index()
{
   $article = $this->Articles->find()
       ->contain('Comments', function($q){
       return $q
              ->limit(2)
              ->order(['Comments.created' => 'DESC']);
       }
   );
   $this->set(compact('articles'));
}

So now in view you will get articles with 2 recent comments.

CakePHP sum a column then group by month.

I have below sql query to get summation of a column name amount , where the result will be grouped by month.

SELECT 
  MONTHNAME( created ) as monthname,
  sum( amount ) as total
FROM 
  transactions
GROUP BY
  monthname

Example, In transactions table I have an amount field where the amount is a numeric value field and transactions have created and modified fields.

So, we can write this query in query builder like below way

public function index()
{
    $query = $this->Transactions->find();
    $query->select([
        ‘monthname’ => $query->func()->monthname([
            ‘created’ => ‘identifier’
         ]),
         ‘total’ => $query->func()->sum(‘Transactions.amount’)
    ])
    ->group([‘month’]);
}

After iteration we should get the result like below

monthname  total
July                    100
May                  300
….. …..

What is VAR hosting in JavaScript ?

If you write a variable and assigned it before declare, like below example

a = 10
console.log(a+20)
var a

It will work perfectly.
Here, I have assigned a variable by value 10, and I also used this variable in console.log() , and it has given output 30.
This behavior is called “hoisting“. Where a variable can appear to be used before it’s declared.

In JavaScript new feature they has introduced LET . Now if you change var a  to let a . You will get an error. If we want to avoid var hosting we can write like below example.

let a
a = 10 
console.log(a+20)

Display a simple object using Vue js.

We will display below object using Vue js

links: [
   {
     name:'facebook',
     href:'http://facebook.com'
   },
   {
     name:'google',
     href:'http://google.com'
   },
   {
     name:'yahoo',
     href:'http://yahoo.com'
   }
]

We have some link name and url. We will display it in a list.

<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="UTF-8">
      <title>Document</title>
   </head>
   <body>
      <div class="container" id="el">
      <p>{{name}}</p>
      <ul>
         <li v-for='link in links'>
         <a :href='link.href'>
            {{ link.name }}
         </a>
         </li>
      </ul>
      </div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<script>
   var vue = new Vue({
   el:'#el',
   data: {
     name:'Top Nav',
     links: [
             {
                name:'facebook',
                href:'http://facebook.com'
             },
             {
                name:'google',
                href:'http://google.com'
             },
             {
                name:'yahoo',
                href:'http://yahoo.com'
             }
     ]
   }
 });
</script>
</body>
</html>

Output :

CakePHP 3 : Change Default Layout

To change default layout in CakePHP, We need to go in cakephp AppController.php

In AppController we have to write cakephp beforeFilter method.
beforeFilter() method is executed before every action in the controller.

It will like below example :

Location : src/Controller/AppController.php

Note : Write this method after initialize() method in AppController
Continue reading “CakePHP 3 : Change Default Layout”