Back

Architecture


Model

Models are classes that represent database tables. They allow you to interact with the corresponding data using object-oriented syntax.

In other words, models provide an easy way to query, insert, update, and delete data in a database table. Read more

Create command: php artisan make:model Product

1class Product extends Model
2{
3 use HasFactory;
4}

Naming

Singular without "Model" suffix (User, Product, Category...)

Best practices

  1. Follow the defined structure:
  • Attributes - $fillable, $casts
  • Lifecycle methods - boot(), booted()
  • Relationships - belongs, has, morphs…
  • Accessors & mutators
  • Other methods
  1. Models should contain only Laravel native things (relations, scopes…) and database-related code.
  • Your business logic should be written into Support or Action classes.
  1. Use mass assignment where possible.
  • The code for creating/updating the model is shorter and cleaner.
  1. Prefer $fillable over $guarded.
  • Generally safer method => reduces the risk of data issues.
  • Greater control over attributes.
  • Ability to easily find database column names by only opening the model.

Controller

Controllers handle requests and responses. In fact, they are intermediaries between the database, views, and business logic. Read more

Create command: php artisan make:controller UserController

1class UserController extends Controller
2{
3 //
4}

Naming

Singular with "Controller" suffix (UserController, ProductController, CategoryController...)

Types

  • resource - contains methods for each CRUD operation also with methods that present HTML templates such as create and edit
  • api - contains also a method for each CRUD operation, but does not provide HTML templates methods
  • invokable - controllers for single actions that do not match resources

Best practices

  1. Keep controller methods thin.
  • They should not contain huge business logic.
  • They are mainly responsible for one thing - returning a response.
  1. Use resource controllers for CRUD operations.
  • Resource defines CRUD methods by following naming conventions.

Namespacing

When you have multiple types of controllers (for API, for Admin...), you should group them by the following structure:

1Admin/UserController.php
2Api/Admin/UserController.php
3Api/UserController.php
4UserController.php

Request

Requests are objects that encapsulate the input data from an HTTP request.

They provide a convenient way to validate and process user input before using it in your application. Read more

Create command: php artisan make:request StoreUserRequest

1class StoreUserRequest extends FormRequest
2{
3 /**
4 * Determine if the user is authorized to make this request.
5 */
6 public function authorize()
7 {
8 return true;
9 }
10 
11 /**
12 * Get the validation rules that apply to the request.
13 */
14 public function rules()
15 {
16 return [
17 //
18 ];
19 }
20}

Naming

Method name with singular model name and with "Request" suffix (StoreUserRequest, StoreProductRequest, UpdateCategoryRequest...)

Configuration

Configurations are always stored in the config directory.

Warning: You should never access the env() method directly in application. You should use it only in configuration files and access it by config() method.

Best practices

  1. Access config values only via config() method.
  2. Store custom application settings in seprated config file.
  • e.g. project.php
  1. API keys of 3rd party services should be stored in services.php.

Action

Actions are classes responsible for only one single task. Code is cleaner and simpler.

Create command: php artisan make:action VerifyUserAction

1class VerifyUserAction
2{
3 /**
4 * Run the action.
5 */
6 public function run(): void
7 {
8 //
9 }
10}

Tip: This command is not part of Laravel framework, install our package rockero-cz/laravel-starter-kit to get a bit of magics.

Naming

Action purpose name with "Action" suffix (VerifyUserAction, CreateProductAction, ReorderCategoryAction...)

Best practices

  1. Each action should contain only one public method.
  • Use some self-explanatory name such as run() or execute().
  1. Action helper methods should be private or protected.
  • Multiple helper methods may be converted to Support classes.

Support

Support classes are a way to group related functions and logic together in a single class. They allow for easy reuse of code and help to keep application code organized.

They are typically used to provide functionality that is not specific to a single model or controller, but rather is used across multiple parts of an application.

It is simpler alternative than using services.

Create command: php artisan make:class Support/Cart

1class Cart
2{
3 //
4}

Tip: This command is not part of Laravel framework, install our package rockero-cz/laravel-starter-kit to get a bit of magics.

Naming

Support purpose name without "Support" suffix (Cart, OpeningHours, Table...)

Routing

Route Types

  • web - Routes that handle web-based HTTP requests and responses…
  • api - Routes that handle API requests and responses…
  • channels - Routes that handle real-time broadcasting to channels using websockets…
  • console - Routes for custom commands that can be executed via Artisan CLI…

Best practices

  1. URLs should be in plural.
  2. Each route should have name.
  3. Routes should be grouped by entities.
1Route::middleware('auth')->group(function () {
2 Route::name('users.')->group(function () {
3 Route::get('/', UserIndex::class)->name('index');
4 Route::get('/{user}', UserShow::class)->name('show');
5 });
6});

Middleware

Middleware is a way to filter and modify incoming HTTP requests in your application, allowing you to perform various tasks such as authentication, authorization, and session management.

You should create middleware in cases when you need to do some specific logic for a specific group of routes. Read more

Create command: php artisan make:middleware HandleLocale

1class HandleLocale
2{
3 /**
4 * Handle an incoming request.
5 */
6 public function handle(Request $request, Closure $next): Response
7 {
8 return $next($request);
9 }
10}

Usage example

1Route::prefix('/admin')->name('admin.')->middleware(HandleLocale::class)->group(function () {
2 Route::resource('users', UserController::class)->name('users');
3 Route::resource('orders', OrderController::class)->name('orders');
4});

Observer

Observers are used to listen for specific events that occurred by models, such as created, updated, or deleted and more...

By using observers, you can keep your model classes focused on their primary responsibilities and avoid cluttering them with additional logic. Read more

Warning: Eloquent mass update queries do not perform the event and the observer is not triggered. It is caused because models are not actually loaded when doing a mass update but only SQL query is.

Create command: php artisan make:observer UserObserver --model=User

1class UserObserver
2{
3 /**
4 * Handle the User "created" event.
5 */
6 public function created(User $user): void
7 {
8 //
9 }
10}

Naming

Singular model name with "Observer" suffix (UserObserver, ProductObserver, CategoryObserver...)

Usage example

1// Recalculate invoice when the invoice item is saved.
2public function saved(InvoiceItem $invoiceItem): void
3{
4 $invoiceItem->invoice()->recalculate();
5}
6 
7// Set default state when the order is created.
8public function creating(Order $order): void
9{
10 $order->state = OrderState::NEW;
11}
12 
13// Delete relations before the model is deleted.
14public function deleting(Order $order): void
15{
16 $order->products()->delete();
17}

Event

Events are a way to trigger and handle actions that occur during the execution of your application. They are used in combination with listeners.

When an event is dispatched, Laravel will notify all registered listeners for that event, giving them a chance to perform any necessary actions. Read more

We primarily use actions instead of events because they are more simple and understandable. However, we use still events for some notifications or in combination with websockets.

Create command: php artisan make:event OrderCreated

1class OrderCreated
2{
3 use Dispatchable, InteractsWithSockets, SerializesModels;
4 
5 /**
6 * Create a new event instance.
7 */
8 public function __construct()
9 {
10 //
11 }
12 
13 /**
14 * Get the channels the event should broadcast on.
15 */
16 public function broadcastOn(): Channel|array
17 {
18 return new PrivateChannel('channel-name');
19 }
20}

Dispatching events

1OrderCreated::dispatch();
2 
3// or
4 
5event(new OrderCreated());

Listeners

Create command: php artisan make:listener SendOrderCreatedNotification --event=OrderCreated

1class SendOrderCreatedNotification
2{
3 /**
4 * Create the event listener.
5 */
6 public function __construct()
7 {
8 //
9 }
10 
11 /**
12 * Handle the event.
13 */
14 public function handle(OrderCreated $event): void
15 {
16 //
17 }
18}

Command

Commands are a powerful tool for automating some tasks in your application. Laravel also provides a set of built-in commands that you can use out of the box.

With commands, you can easily perform repetitive actions like running tests or executing database migrations, with minimal effort. Read more

Create command: php artisan make:command FetchUsers

1class FetchUsers extends Command
2{
3 protected $signature = 'command:name';
4 protected $description = 'Command description';
5 
6 /**
7 * Execute the console command.
8 */
9 public function handle(): int
10 {
11 return Command::SUCCESS;
12 }
13}

Scheduling commands

You can easily run commands at specified intervals or times using Scheduler.

1// app/Console/Kernel.php
2protected function schedule(Schedule $schedule)
3{
4 $schedule->command('telescope:prune')->daily();
5}
Edit this page

We are hiring!