When people say they want to use  CakePHP with React typically the recommendation is to convert CakePHP into an API server and then add ReactJS as the front-end served on a different URL then CakePHP.

But what about when you have a CakePHP application and you want to use CakePHP authentication and routing and even a lot of the CRUD views that you have baked?

The following is how to Embed React into a view in CakePHP using the following:

  • An existing CakePHP 3.6+ application
  • create-react-app

How it works

  • The create-react-app build command is modified to copy the production build static react files to the cakephp webroot/react folder.
  • The CakePHP Controller action and view file is then modified to read the create-react-app provided asset-manifest.json file which contains relative paths to the JS and CSS files needed for the react app.

Example asset-manifest.json

When react compiles a production build it inserts a random string in the assets. But handily provides asset-manifest.json to map the resources

    "main.css": "static/css/main.ed1a35cf.css", 
    "main.css.map": "static/css/main.ed1a35cf.css.map", 
    "main.js": "static/js/main.bdb0c67c.js", 
    "main.js.map": "static/js/main.bdb0c67c.js.map"

Change the React Projects package.json to build and move react to CakePHP webroot

"scripts": {
    "start": "react-scripts start",
	"build": "react-scripts build && rm -rf /Path/To/CakePHP/app/webroot/pick-app && cp -rv build /Path/To/CakePHP/app/webroot/pick-app",
    "test": "react-scripts test",
    "eject": "react-scripts eject"

Modify the CakePHP Controller Action to Read the React asset-manifest.json

public function react(){
        $filePath = WWW_ROOT . '/react/asset-manifest.json';
        $file = new File($filePath);

        $manifest = json_decode($file->read());

        $maincss = 'main.css';
        $mainjs = 'main.js';

        $css = '/react/' . $manifest->$maincss;
        $js = '/react/' . $manifest->$mainjs;

        $this->set(compact('css', 'js'));  

Modify Template File to Create React Mount Point

// src/Template/Articles/react.ctp
$this->Html->css($css, [
    'block' => true,
]); ?>
<!-- this is where the react page mounts -->
<div id="root"></div>

<?=$this->Html->script($js); ?>

Handling Access CORS headers

// create this file in
// src/App/Middleware/HttpOptionsMiddleware.php
// modify src/Application.php to hook this into
// the CakePHP middleware chain
namespace App\Middleware;

class HttpOptionsMiddleware
    public function __invoke($request, $response, $next)

        $response = $response
            ->withHeader('Access-Control-Allow-Origin', 'http://localhost:3000')
            ->withHeader('Access-Control-Allow-Credentials', 'true');

        if ($request->getMethod() == 'OPTIONS') {

            $method = $request->getHeader('Access-Control-Request-Method');
            $headers = $request->getHeader('Access-Control-Request-Headers');
            $allowed = empty($method) ? 'GET, POST, PUT, DELETE' : $method;

            $response = $response
                ->withHeader('Access-Control-Allow-Headers', $headers)
                ->withHeader('Access-Control-Allow-Methods', $allowed)
                ->withHeader('Access-Control-Allow-Credentials', 'true')
                ->withHeader('Access-Control-Max-Age', '86400');

            return $response;

        return $next($request, $response);

Example Fetch Configuration

        mode: 'cors',
        method: 'POST',
        cache: 'no-cache',
        credentials: "include",
        headers: {
            // need X-Requested-With header
            // so you CakePHP can check it's ajax 
            // with $this->request->is('ajax');
            'X-Requested-With': 'XMLHttpRequest',
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        body: JSON.stringify({
            user_id: 1,
            title: e.target.elements.title.value,
            body: e.target.elements.body.value
    }).then((response) => {
        if (response.ok) {

            // do another fetch here
            // to update state after
            // creating an article

        return response.json()
        throw new Error(response.status + " " + response.statusText)
    }).catch((e) => console.log(e))

I put it on GitHub

Here is a link to the github repository for cakephp-react-backend