PHP with React JS: Combined

Abdulbasit Rubeya
6 min readMar 1, 2024

--

reactJS components in Blade

Disclaimer: I am just a couple of hours reactJS old (by the time I was writing this), yes that’s how long I have been using reactJS and this here is my first project with reactJS, so obviously there will be things that I have missed or could have done them better.

Backstory

I have been working as a web developer for about five years now. Although I am familiar with other tools like Node.js, my preferred stack has always revolved around PHP due to its ease of use without requiring additional configurations or installations. This stack typically involves HTML, CSS, and JS, complemented by a few other minimal UI frameworks and libraries such as Bootstrap and jQuery.

Since the beginning of this year (2024), I have been actively job hunting (still no luck 😀), which prompted me to broaden my skill set. While browsing and exploring new technologies, I stumbled upon ReactJS. After trying it with Node.js and finding it promising, I, as a hardcore PHP fan, had two questions: Does ReactJS work with PHP, and if so, how?

The answer to the first question is obviously yes. However, concerning the second question, it’s generally agreed upon that to integrate ReactJS with PHP, one needs to utilize APIs. In essence, this entails having two separate app implementations for a single application: one to handle API requests and the other for the front end. While this approach is effective, it requires both time and resources.

After a few minutes of searching and brainstorming, I thought of an alternative solution. By utilizing ReactJS alongside the Blade template, one can employ ReactJS in a manner akin to directly using vanilla tools like HTML, CSS, and JS. Let's see how this method works out.

1. Requirement

Blade template is required, if you’re using a framework like Laravel, the Blade template engine is shipped with it, if you’re using Symfony here’s a guide you can use to integrate the Blade template engine with your Symfony app, now to those using core php without a framework I’d suggest you installjenssegers/blade stand-alone Blade template and follow the documentation to set it up

composer require jenssegers/blade

As for me I already have my very own basic implementation of an MVC framework which has some initial tools pre-installed including the Blade template engine.

ReactJS and Babel Modules (CDN)

<!-- React CDN -->
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>

<!-- Babel CDN for JSX -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

2. Hello world

It is commonly known that a simple reactJS app would look something like this if we are going to use the CDNs

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Simple React App</title>

<!-- React CDN -->
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>

<!-- Babel CDN for JSX -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>

<script type="text/babel">

const App = () => {
return (
<h1>Hello World</h1>
);
};

// Render the component to the DOM
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

</script>
</body>
</html>

Blade TE allows us to place and reuse components neatly and conveniently, hence we’ll have to define a file organization

📁 Views/
├── 📁 layouts/
│ ├── 🌐 app.blade.php
│ ├── 📁 components/
│ │ ├── ⚛ global.blade.jsx
│ │ ├── ⚛ local.blade.jsx
├── ⚛ home.blade.jsx

Please note that if you examine my files, some of them have the extension .blade.jsx. In your case, to allow the compilation of JSX files to be compiled as views, one will have to add support for the extension initializing the Blade template engine

$blade->addExtension('blade.jsx', 'blade');

mainFile.blade.jsx Structure

@extends('layouts.app')

@section('components')

// include/declare new local components from here

@endsection

@section('content')

// JSX content falls in here

@endsection

Since we’ve declared that our main app files will be extending layouts/app.blade.php we’ll have to make sure that the app is compatible with any other file extending it, therefore app.blade.php should look something like this.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Simple React App</title>

<!-- React CDN -->
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>

<!-- Babel CDN for JSX -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>

<script type="text/babel">

@yield('components') // contents of section 'components'

const App = () => {
return (
@yield('content') // contents of section 'content'
);
};

// Render the component to the DOM
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

</script>
</body>
</html>

As you can see that now our app.blade.php can yield and place the sections of the extending file in their respective areas, let’s try populating the ‘content’ section of home.blade.jsx

...

@section('content')

<div>
<h1>Hedy Lamarr's Todos</h1>
<img
src="https://cdn-icons-png.flaticon.com/256/6619/6619606.png"
alt="Hedy Lamarr"
className="photo"
/>
<ul>
<li>Invent new traffic lights</li>
<li>Rehearse a movie scene</li>
<li>Improve the spectrum technology</li>
</ul>
</div>

@endsection

This should give us something like

Something about Reusable components, if you review our directory structure and our file skeleton you notice 3 things

  • layouts/components/global.blade.jsx : This file will have all the components that we need to reuse across our application
  • layouts/components/local.blade.jsx : This file will restore components that are only reusable in certain files, you can add your components to the components directory
  • section('components') : Can be used to include other components or declare its own components to be used in that specific file.

Thanks to Blade’s @include directive we can use it to call and include other components from anywhere we need, let’s start with the header, we’ll declare this one inglobal.blade.jsx located in layout components

... global.blade.jsx

const Header = () => {

return (
<header>

<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>

</header>
)

}

// other global components

Let’s load the global components to our application root file layouts/app

... app.blade.php

<script type="text/babel">

@include('layouts.components.global') // here it is

@yield('components')

const App = () => {
return (
<div className="appContainer">

<Header /> // use your component just like that 😊
@yield('content')

</div>
);
};

...
</script>

That should do the trick with loading the Header component and the content section, but let’s make it interesting, let’s assume while rendering our view, we passed some data through it.

view ( 
'home', [ 'todos' => [
'Go to the store',
'Finish the tutorial',
'Clean the house'
]]
);

# now we've got a variable array $todos to work with
@extends('layouts.app')

@section('components')

var owner = 'Hedy Lamarr';

// called and parsed our variable to JSON (for option 1)
var initialTodos = JSON.parse('{!! json_encode($todos) !!}');

const TodoApp= () => {
return (
<ul>

// option 1
{initialTodos.map((todo, index) => (
<li key={index}>{todo}</li>
))}

/** Option 2
* directly use blade directives like @php, @foreach, etc
* to complete the render or you component with PHP
*/
</ul>
);
};

@endsection

@section('content')

<div>
<h1> {owner} </h1>
<img
src="https://cdn-icons-png.flaticon.com/256/6619/6619606.png"
className="photo"
/>

<TodoApp />
</div>

@endsection

NOTE: make sure you’re careful with the curly brackets

  • { content } : That’s for reactJS and will be parsed in the browser
  • {{ content }} , {!! content !!} : That will be parsed during processing on the server

Let’s make things more interesting, by adding a form that would allow us to change the state of our list

... home.blade.jsx

@section('components')

var owner = 'Hedy Lamarr';
var initialTodos = JSON.parse('{!! json_encode($todos) !!}');

const TodoApp = () => {
const [todos, setTodos] = React.useState(initialTodos);

// new component to process our todo form
const TodoFormSubmit = (e) => {
e.preventDefault();

const newTodo = e.target.elements.todo.value;
setTodos([...todos, newTodo]); // update list
e.target.reset(); // Reset the form after submission

};

return (
<div>
<ul id="toDoList">
{todos.map((todo, index) => (
<li key={index}>{todo}</li>
))}
</ul>

<form onSubmit={TodoFormSubmit}>
<input type="text" name="todo" placeholder="Add a todo" />
<button type="submit">Add</button>
</form>

</div>
);
};

@endsection

That should give us something like this

I believe that wraps up our tutorials on integrating ReactJS with PHP without completely separating the application layers.

You can find the code for this tutorial here.

Additionally, I’m currently developing a PHP+ReactJS (mimosa) framework. If you find it helpful, be sure to keep an eye on the GitHub repository @ibnsultan/mimosa.

--

--

Abdulbasit Rubeya
Abdulbasit Rubeya

Responses (1)