This content originally appeared on Level Up Coding - Medium and was authored by Daniel Haven
As a Laravel developer, my current tastes revolve around using Vue as a frontend and Inertia as a connector. Throughout my work, I believe I’ve found the perfect architecture to model any Laravel/Inertia codebase.
Frontend Folder Structure
My resources/js is structured the following way:
- Pages: Holds any Vue file that is returned by a GET request.
- Components: Holds reusable components that can be extended to other repositories.
- Layouts: Holds all layouts that are implicitly wrapped around the frontend.
- Partials:
Unlike components, these global partials are identified specifically with the repository they’re working in. They can be applied to any Vue file within the repository, but they cannot be reused outside of it.
For local partials, those are nested within the Pages/Components/Layouts directories if they apply to one or more Vue files within those directories.
- …all other files
This setup is, quite conveniently, nearly the same as the setup used by Nuxt. With this kind of setup, I found it very easy to structure my controllers in a way that mirrors the way my resources/js directory looks.
Invokable or Normal Controllers? Also, Folder Structure
If you don’t know anything about invokable (or single action) controllers, read here.
Below is my App/Http/Controllers setup:
Structure: App/Http/Controllers
- API
- Web
- Actions
- Pages
API is meant to store all controllers that are used for the website’s API and in the routes/api.php file.
Web, obviously, is meant to hold all the web-based controllers or the ones where the routes are located in routes/web.php.
Below web, there are two subfolders: Actions and Pages. Here, every single file in the Pages folder is meant to align with the file in resources/js/Pages directory.
So, as a side-by-side comparison, it would look exactly like this:
Structure: App/Http/Controllers/Web/
- Pages
- Item
- Index.php
Structure: resources/js
- Pages
- Item
- Index.vue
The Index.php file contains the Index invokable controller class and the Index.vue contains the frontend.
By performing it this way, you can improve organization. Furthermore, you reduce the number of lines per controller by separating each method into its own invokable controller class file.
However, if you don’t want to use invokable for every single controller, you can have this alternative setup.
Structure: App/Http/Controllers/Web/Pages
- Pages
- ItemController.php
Structure: resources/js
- Pages
- Item
- Index.vue
Within ItemController.php, you would have the index method. While it can be a bit harder to relate these to their equivalent Vue pages at first glance, they do give you the ability to use Laravel’s built-in route::resource functionality, thus allowing you to shorten your routes/web.php file.
However, for any controller method that does not fit neatly into [Index, Create, Store, Edit, Update, Destroy] paradigm (e.g., “Publish”), then I would suggest making it an invokable and putting in the App/Http/Controllers/Web/Actions directory.
Service Layer
Finally, to handle repetitious behavior, I rely on Service classes.
I add a directory App/Services, and I put two subdirectories. You can name the second one whatever you like (e.g., “Other”), but I name my first one “Client”, and in that subdirectory, I put any service class where the methods interact with an external API. If I want to connect to an API of a particular organization, I will build a directory that describes that organization and then create a service class file that describes a grouping of what that API is trying to accomplish.
Let’s take this example where I’m making a client service class that connects to Widget Inc’s Payment API (widget/v2/getPayments, widget/v2/postPayment).
Structure: App/Services/Client
- Services
- Client
- Widget
- V2
- PaymentService.php
PaymentService.php contains all methods that make calls to related Payment API.
File: App/Services/Client/Widget/V2/PaymentService.php
<?php
namespace App/Services/Client/PaymentService;
...
class PaymentService {
public function getPayments(...)
{
...
}
publc function postPayment(...)
{
...
}
}
By doing it like this, I’m able to write reusable functionality with the sole purpose of interacting with an external entity’s API in a clear and readable manner. I can easily grab this logic, copy and paste it to any other PHP-based project and have it work.
Pros & Cons
Pros
- Shorter controller code w/o the use of service classes.
- Controller class matches page on front end.
- Not having to think of an abstract controller name to group your logic (usually the name of a model), since the naming scheme is based on how you like to group your pages and actions.
- Service classes can be injected fairly ubiquitously thanks to the shortened controllers usually requiring only one service class.
e.g.,
e...
$this->service = $service;
...
Cons
- Longer route files.
Since your controllers are kept in separate files, you can’t leverage Route::resource.
You may use the typical Controller structure if it fits the [Index, Create, Store, Edit, Update, Destroy] paradigm and just abstract any lengthy logic to a service class to reduce length of lines used.
- Refactoring can be a nightmare if you want to change the location of several Vue files and, subsequently, their equivalent controller files.
- Some people like having one controller per model to store their model CRUD logic, but I’m not a fan of that approach. Any kind of abstract typical model-action logic should be in its own class (e.g., Repository pattern). Not in the controllers, which are primarily designed to abstract route logic and keep the route files looking clean.
Laravel: My Proposal for the Inertia-Based File Structure and Invokable Controllers was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.
This content originally appeared on Level Up Coding - Medium and was authored by Daniel Haven
Daniel Haven | Sciencx (2022-04-18T00:58:51+00:00) Laravel: My Proposal for the Inertia-Based File Structure and Invokable Controllers. Retrieved from https://www.scien.cx/2022/04/18/laravel-my-proposal-for-the-inertia-based-file-structure-and-invokable-controllers/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.