DEV Community

Cover image for Create Api With Cakephp
Meow
Meow

Posted on

Create Api With Cakephp

Before I have created API with prefixes. So I had API in the controller folder with everything else but when you have many controllers it can be hard to navigate between them. So I decided to move all API controllers to a new plugin that I called API (the similarity of the names is purely random). And the second good thing on this is that you can have easily versions of your API. So here I using prefixes for API versioning (V1, V2 ...).

How to do it

First of all create new plugin

php bin/cake.php bake plugin Api
Enter fullscreen mode Exit fullscreen mode

And load it in Application.php bootstrap function.

// src/Controller/AppController.php

// add this to bootstrap function at the end
$this->addPlugin('Api');
Enter fullscreen mode Exit fullscreen mode

Next, you need to allow to use URL extensions, for me it is .json. You can also allow .xml if you need this. If you want more extensions check the official documentation for CakePHP. Open and edit your plugin's AppController

// /plugins/Api/src/Controller/AppController.php

public function initialize(): void
{
    parent::initialize();

    // Load Request handler
    $this->loadComponent('RequestHandler');
}
Enter fullscreen mode Exit fullscreen mode

Update you plugin routing to allow Prefixes and extensions to look like following

// /plugins/Api/src/Plugin.php

public function routes(RouteBuilder $routes): void
{
    $routes->plugin(
        'Api',
        ['path' => '/api'],
        function (RouteBuilder $builder) {
            // Add custom routes here

            // API ver 1.0 routes
            // add new block for more prefixes
            $builder->prefix('V1', ['path' => '/v1'], function (RouteBuilder $routeBuilder) {;
                $routeBuilder->setExtensions(['json']); // allow extensins. this have to be here for each prefix
                $routeBuilder->fallbacks();
            });

            $builder->fallbacks();
        }
    );
    parent::routes($routes);
}
Enter fullscreen mode Exit fullscreen mode

Update or create your actions in the API controller as following

// plugins/Api/src/Controller/V1/HelloController.php

public function index()
{
    $this->Authorization->skipAuthorization();

    $text = [
        'message' => 'Hello'
    ];

    $this->set('text', $text);

    // Add this to serialize repose
    $this->viewBuilder()
        ->setOption('serialize', 'text');
}
Enter fullscreen mode Exit fullscreen mode

You can test it with curl. And if everything goes OK you will see the result

curl -i http://localhost:8765/api/v1/hello/index.json
Enter fullscreen mode Exit fullscreen mode

Skip Csrf checking on API related routes

Bonus If you want to post data to API you will be going to receive an error message as a response because the CSRF token doesn't match. By default CakePHP 4 using Middleware so you have
set it to skip verification CSRF for plugin routes. Here is how to do it.

Copy or write following function at the end to your Application.php

// src/Application.php
public function getCsrfProtectionMiddleware() : CsrfProtectionMiddleware
{
    $csrf = new CsrfProtectionMiddleware([
        'httponly' => true,
    ]);

    $csrf->skipCheckCallback(function ($request) {
        if ($request->getParam('plugin') == 'Api') { // Skip Checking if plugin is API
            return true;
        }
    });

    return $csrf;
}
Enter fullscreen mode Exit fullscreen mode

Find and update loading csrf middleware from

->add(new CsrfProtectionMiddleware([
        'httponly' => true,
  ]));
Enter fullscreen mode Exit fullscreen mode

to this

->add($this->getCsrfProtectionMiddleware());
Enter fullscreen mode Exit fullscreen mode

and you can check with

curl -i --data message="Hello from data" http://localhost:8765/api/v1/hello/index.json
Enter fullscreen mode Exit fullscreen mode

To see your message from a post, update the index function do following

// plugins/Api/src/Controller/V1/HelloController.php

public function index()
{
    $this->Authorization->skipAuthorization();

    $text = [
        'message' => $this->request->getData('message'),
    ];

    $this->set('text', $text);

    // Add this to serialize repose
    $this->viewBuilder()
        ->setOption('serialize', 'text');
}
Enter fullscreen mode Exit fullscreen mode

That's is how you can create APIs with CakePHP

Photo by Joey Kyber on Unsplash

Originally posted at themaymeow.com

Top comments (3)

Collapse
 
novslugger profile image
Novslugger

Do you sample API with authentication in cakephp 4?

Collapse
 
maymeow profile image
Meow

last time I've to do it on cakephp 3, I can write it for cakephp4.

Collapse
 
gayanhewa profile image
Gayan Hewa

Interesting read. I have never shipped an API in CakePHP before, the framework see to offer great tooling around building API's 👌