How To Integrate CakePHP with React

CakePHP’s View is weak compared to it’s Model and Control framework. Because of this, people often use React as a supplement or replacement to the frontend. This guide will provide information on how you can use React alongside CakePHP.

Embed React Components inside Cake’s View Templates

Store all of your React components inside a separate folder. In my case, they will live inside /src/React/components. Each embeddable React component will attach itself to the DOM.

//π™Έπš—πšœπš’πšπšŽ πšœπš›πšŒ/𝚁𝚎𝚊𝚌𝚝/πšŒπš˜πš–πš™πš˜πš—πšŽπš—πšπšœ/

πš’πš–πš™πš˜πš›πš 𝚁𝚎𝚊𝚌𝚝 πšπš›πš˜πš– 'πš›πšŽπšŠπšŒπš';
πš’πš–πš™πš˜πš›πš πšπšŽπšŠπšŒπšπ™³π™Ύπ™Ό πšπš›πš˜πš– 'πš›πšŽπšŠπšŒπš-πšπš˜πš–';

πšπšžπš—πšŒπšπš’πš˜πš— π™΄πš–πš‹πšŽπšπšπšŠπš‹πš•πšŽπ™²πš˜πš–πš™πš˜πš—πšŽπš—πš() {
	πš›πšŽπšπšžπš›πš— (
		<πš‘πŸ·>π™·πšŽπš•πš•πš˜ πš†πš˜πš›πš•πš</πš‘πŸ·>
	);
}
πšπšŽπšŠπšŒπšπ™³π™Ύπ™Ό.πš›πšŽπš—πšπšŽπš›(<π™΄πš–πš‹πšŽπšπšπšŠπš‹πš•πšŽπ™²πš˜πš–πš™πš˜πš—πšŽπš—πš/>, πšπš˜πšŒπšžπš–πšŽπš—πš.πšπšŽπšπ™΄πš•πšŽπš–πšŽπš—πšπ™±πš’π™Έπš('πš™πšŠπš›πšŽπš—πšπšƒπšŠπš'));

Note: The parentTag will be the bridge between React and CakePHP.

Configure webpack.config.js to compile each .jsx file into a JavaScript file. The code below compiles src/React/components/embedable-components.jsx to /webroot/js/embeddable-component.jsx.

// π™Έπš—πšœπš’πšπšŽ πš πšŽπš‹πš™πšŠπšŒπš”.πšŒπš˜πš—πšπš’πš.πš“πšœ

πšŒπš˜πš—πšœπš πš™πšŠπšπš‘ = πš›πšŽπššπšžπš’πš›πšŽ('πš™πšŠπšπš‘');

πš–πš˜πšπšžπš•πšŽ.πšŽπš‘πš™πš˜πš›πšπšœ = {
   πšŽπš—πšπš›πš’: {
      πšŽπš–πš‹πšŽπšπšŠπš‹πš•πšŽ_πšŒπš˜πš–πš™πš˜πš—πšŽπš—πš:
          πš™πšŠπšπš‘.πš›πšŽπšœπš˜πš•πšŸπšŽ(__πšπš’πš›πš—πšŠπš–πšŽ, "πšœπš›πšŒ", "𝚁𝚎𝚊𝚌𝚝", "πšŒπš˜πš–πš™πš˜πš—πšŽπš—πšπšœ", "πšŽπš–πš‹πšŽπšπšŠπš‹πš•πšŽ-πšŒπš˜πš–πš™πš˜πš—πšŽπš—πš.πš“πšœπš‘")
   },
   πš˜πšžπšπš™πšžπš: {
       πš™πšŠπšπš‘: πš™πšŠπšπš‘.πš›πšŽπšœπš˜πš•πšŸπšŽ(__πšπš’πš›πš—πšŠπš–πšŽ, "πš πšŽπš‹πš›πš˜πš˜πš", "πš“πšœ"),
	    πšπš’πš•πšŽπš—πšŠπš–πšŽ: '[πš—πšŠπš–πšŽ].πš“πšœ'
        },
  πš–πš˜πšπšžπš•πšŽ: { /** π™²πš˜πšπšŽ πšπš˜πš› πš‘πšŠπš—πšπš•πš’πš—πš 𝚁𝚎𝚊𝚌𝚝 πšŒπš˜πš–πš™πš’πš•πšŠπšπš’πš˜πš— **/}
};

Once we build the app, components inside webroot will be accessible inside Cake’s view templates and can easily be embedded:

<πšπš’πšŸ πš’πš="πš™πšŠπš›πšŽπš—πšπšƒπšŠπš">
	<?πš™πš‘πš™ 
		// πšƒπš‘πš’πšœ πš’πšœ πšπš‘πšŽ πš‹πš›πš’πšπšπšŽ πš‹πšŽπšπš πšŽπšŽπš— 𝙲𝙰𝙺𝙴𝙿𝙷𝙿 πšŠπš—πš πšπ™΄π™°π™²πšƒπ™Ήπš‚
		πšŽπšŒπš‘πš˜ $πšπš‘πš’πšœ->π™·πšπš–πš•->πšœπšŒπš›πš’πš™πš('πšŽπš–πš‹πšŽπšπšŠπš‹πš•πšŽ_πšŒπš˜πš–πš™πš˜πš—πšŽπš—πš.πš“πšœ');
	?>
</πšπš’πšŸ>

Note: Ensure that the parentTag appears before the call to the script import.

React as Single-Page Frontend with CakePHP

React Router is a library that can control the browser’s navigation and history interface. We can use React Router instead of CakePHP’s backend routing. However, we still need to tell CakePHP to load the initial page where our React app lives. 

// π™Έπš—πšœπš’πšπšŽ πšŒπš˜πš—πšπš’πš/πš›πš˜πšžπšπšŽπšœ.πš™πš‘πš™
$πš‹πšžπš’πš•πšπšŽπš›->πšŒπš˜πš—πš—πšŽπšŒπš('/*', ['πšŒπš˜πš—πšπš›πš˜πš•πš•πšŽπš›' => 'π™ΏπšŠπšπšŽπšœ', 'πšŠπšŒπšπš’πš˜πš—' => 'πš–πšŠπš’πš—']);

The following code disables Cake’s automatic template rendering via URL and routes all URL requests to a single webpage we’ve created called main.Β 

Moving forward, we still need to make sure that Cake’s REST APIs are accessible. The following code below will route your URLs that are prefixed with `api/` to the generic route.

𝚞𝚜𝚎 π™²πšŠπš”πšŽ\πšπš˜πšžπšπš’πš—πš\𝚁𝚘𝚞𝚝𝚎\π™³πšŠπšœπš‘πšŽπšπšπš˜πšžπšπšŽ;

$πš›πš˜πšžπšπšŽπšœ->πšœπšŒπš˜πš™πšŽ('/πšŠπš™πš’', πšπšžπš—πšŒπšπš’πš˜πš— (πšπš˜πšžπšπšŽπ™±πšžπš’πš•πšπšŽπš› $πš›πš˜πšžπšπšŽπšœ) {
    $πš›πš˜πšžπšπšŽπšœ->πšπšŠπš•πš•πš‹πšŠπšŒπš”πšœ(π™³πšŠπšœπš‘πšŽπšπšπš˜πšžπšπšŽ::πšŒπš•πšŠπšœπšœ);
});

Following the steps in the section above you can embed your entire React application in the single template rendered by PagesController::main().

References: