-
Notifications
You must be signed in to change notification settings - Fork 0
Tutorial
Laravel in my opinion is a fantastic PHP framework for the backend of your software. I love Laravel and will always love it. Laravel follows the MVC (Model, view, controller) design pattern, however, I don't really enjoy the Blade template engine. It's a great engine but I prefer single-paged web applications. They feel more like actual software than a traditional web page (Must reload the browser for another resource or view).
I chose ReactJS as it's a fantastic framework for creating a template of HTML that adds state and properties to your components and allows you to remove code duplication in your application. I don't like code duplication and anything I find that is duplicated I remove it.
Of course implementing ReactJS to Laravel is trivial but can be tedious when you want a full working application without having to always set things up from the getgo. This template starts you out at square one with everything you need on the backend and the frontend. You just need Node Package Manager, Composer, and PHP installed on your development environment.
I recommend using XAMMP as a development server for this template. You'll notice that in your webpack.min.js file at the top you have two variables that are defined.
let AppName = 'PhatChat';
let AppRoot = 'htdocs';
These are used in a post-script after you build your frontend using npm run dev
or npm run watch
. htdocs
is the naming scheme that XAMPP uses. Though if you use any other server you need not worry because you want to build your app.js
file in the public
directory when you deploy your application. (More on that later for the noobs). The post-script only runs when you run npm run dev
this will copy everything in your public
directory to htdocs
. You can adjust this script to your liking though if you're more advanced. (webpack.min.js is in the root directory of this template, ~line 51 is where the copy happens).
I'm not going to go into full details with this but I setup Auth to match what is on the frontend. You can change how these forms look but the backend shouldn't need too much tweaking. Everything else though would be the same as you would expect for Laravel. Follow the design patterns Laravel uses and everything will workout great.
This is where everything is, once you setup your backend you want to create a perfect frontend for your users. The frontend as mentioned above uses ReactJS and the Flux design pattern. You can remove everything and rebuild it for Redux but I like Flux as it is similar to MVC. Your Models are your Stores, your Views are your Components, and your Controllers are your Actions. Sorta. The location of the front end is resources/assets/js/
There are a couple classes I put in that I'll go over first.
- The Router
- The AppDispatcher
- The RenderManager
I setup the Router as a "Store" for your Routes. These routes are defined in the routes.js
file. The names of your routes should follow the names of your Actions. I.e. why I said your Controllers are your like your Actions. For instance LOG_OUT
is an action but it is also a route /logout
. So your URL should match your Action since an Action is something the application needs to do, a Uniform Resource Locator is a way to do something, or find something.
First register your constants. For instance const GET_ADDRESS = 'get-address'
You can use this to Identify your Action and Route. Register your route in routes.js
at the root of the frontend. Next go into the directory actions
and you'll find a file called ActionRepo.js
. Include your actions here. If you don't the action won't be registered.
There are examples for Routes, Actions, Stores, and even Components for you to look at.
This project uses Axios
as an HTTP service rather than Fetch (before it was used as a PoC) When you send a request you want to use the Router via request
function. This function will prepare everything Axios needs to send an HTTP request. The function signature is Router.request(type, routeName, requestData, headers)
type
is of course post
get
put
etc. your routeName is what you used to register your route in routes.js
. The requestData
is slightly more tricky, you need to specify args
and/or data
here. Headers can remain empty unless you want your own headers. But be sure to always include the X-CSRF-TOKEN to your headers with Laravel. You can get the csrf token using the function getCSRF
from the Router import. import { getCSRF } from './router.js'
When you register a route you have the following
Router.registerRoute(Constants.GET_EXAMPLE_MESSAGE, args => {
return `/getExampleMessage/${args.id}`;
});
args injects into your URL the thing you need. Maybe an ID or whatever.
data
is used in the body of your request. It's not part of the URI.
You can see here
return {
method: type,
url: this.partialRoute(routeName, requestData.args),
headers: HEADERS,
data: requestData.data
}
Axios allows you to defined the data that is being sent. Axios will "Stringify" this data and send it to the backend.
So the most complex Router.request
you'll see is like the following...
Axios(Router.request('GET', GET_EXAMPLE_MESSAGE, {
args: {id: payload.id}
data: {
message: 'hello'
}
}))
.then(checkStatus)
.then(response => {
ExampleStore.setExampleMessage(response.data.message);
Actions.finish(payload);
}).catch(handleError);
There really should only be one dispatcher for a single app. However if your app gets larger (Please wait as I want to be able to scale this Template to have multiple modules).
When you dispatch
an action to the dispatcher you want to have the following
AppDispatcher.dispatch({
action: <The constant that defines your Action i.e. GET_SOMETHING>
something: data
id: whatever
emitOn: [{
store: AStore,
componentIds: [id1, id2, ... ]
}, {
store: BStore,
componentIds: [id1, id2, ... ]
}]
});
I made it so that you can emit on multiple stores and components. Normally you really only need to emit a change on one store and one component, maybe two components. Keep it simple and clean. But this allows you to do so. In many cases you shouldn't need to.
In order for emitOn to work you need to finish your action using Actions.finish(payload)
in your action.
Here is an example to remind you of that...
Actions.register(GET_EXAMPLE_MESSAGE, payload => {
Axios(Router.request('GET', GET_EXAMPLE_MESSAGE, {
args: {id: payload.id}
}))
.then(checkStatus)
.then(response => {
ExampleStore.setExampleMessage(response.data.message);
Actions.finish(payload); // <--- FINISH YOUR ACTION, unless you don't want to emit a change on a Store(s)
}).catch(handleError);
});
This is a simple section. To remove the Blade template stuff I cleaned out each template-out-of-the-box to only return a simple div
with an id that defines what it was. You can see these in each view.
The RenderManager will only render what div
Laravel serves up to the front end.
Most of the time you probably won't need to worry about this but it is in place to expand the Template to have multiple modules in the future.
To register a main component to be rendered you must supply the id
of the div and the component that will be rendered in it. For example.
RenderManager.registerElement('app', <App />);
If the 'app' id is present in the DOM the component App
will be rendered in it. This registering can be done in render.js
.
You'll notice in the views
directory the home view is same as the code below
@extends('layouts.app')
@section('content')
<div id='app'></div>
@endsection
This view is sent to the client, everything in the app layout will be used for each content section. here the 'app' div is present and the render manager will be able to find this div in the DOM.