Create Api With Cakephp
Tags: php, cakephp, api
Published: 2020-09-25 09:42:54

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

```bash
php bin/cake.php bake plugin Api
```

And load it in `Application.php` bootstrap function.

```php
// src/Controller/AppController.php

// add this to bootstrap function at the end
$this->addPlugin('Api');
```

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`

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

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

    // Load Request handler
    $this->loadComponent('RequestHandler');
}
```

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

```php
// /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);
}
```

Update or create your actions in the API controller as following

```php
// 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');
}
```

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

```bash
curl -i http://localhost:8765/api/v1/hello/index.json
```

## 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`

```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;
}
```

Find and update loading csrf middleware from

```php
->add(new CsrfProtectionMiddleware([
        'httponly' => true,
  ]));
```

to this

```php
->add($this->getCsrfProtectionMiddleware());
```

and you can check with

```bash
curl -i --data message="Hello from data" http://localhost:8765/api/v1/hello/index.json
```

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

```php
// 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');
}
```

That's is how you can create APIs with CakePHP


Photo by [Joey Kyber](https://unsplash.com/@jtkyber1?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/traffic?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText)

Originally posted at [themaymeow.com](https://www.themaymeow.com/posts/2020/09/create-api-with-cakephp/)