Architecture & Design: MVC and Beyond
MVC (Model-View-Controller)
In Laravel, MVC is a common architectural pattern:
Model: Interacts with the database (e.g., Eloquent models).
View: Renders the data to the user (Blade templates).
Controller: Handles user requests and ties the model and view together.
Example:
// Controller - Handles the request
class UserController extends Controller {
public function show($id) {
$user = User::find($id); // Model logic
return view('user.profile', ['user' => $user]); // View logic
}
}
// View (Blade template)
<h1>{{ $user->name }}</h1>
Beyond MVC: Microservices, CQRS, and Event-Driven Architecture
Microservices Architecture
A system where services are broken down into small, independent services that communicate via HTTP or messaging systems. Each service handles a specific business capability.
Example Scenario: If you're building a large e-commerce application, you could break it down into:
A user service for authentication and user profiles.
A payment service for handling transactions.
An inventory service for managing product stock.
Example using Guzzle in Laravel for HTTP communication between services:
use GuzzleHttp\Client;
$client = new Client();
$response = $client->request('GET', 'http://inventory-service/api/product/stock/1');
$body = $response->getBody();
$stock = json_decode($body);
CQRS (Command Query Responsibility Segregation)
CQRS splits write and read operations into separate models. The idea is to have different logic paths for queries (reads) and commands (writes).
Example:
Commands (write operations) could trigger events that change the system state.
Queries (read operations) are optimized for fetching data.
In Laravel, you can implement CQRS using commands and query objects.
// Command to create a user
class CreateUserCommand {
public function __construct(public $name, public $email) {}
}
// Handler for the command
class CreateUserHandler {
public function handle(CreateUserCommand $command) {
$user = User::create([
'name' => $command->name,
'email' => $command->email
]);
event(new UserCreated($user)); // Event-driven architecture
}
}
// Query to fetch a user
class GetUserQuery {
public function __construct(public $id) {}
}
// Handler for the query
class GetUserHandler {
public function handle(GetUserQuery $query) {
return User::find($query->id);
}
}
Event-Driven Architecture
In this architecture, actions within the system trigger events, and other parts of the system respond to these events.
Example:
// Event - UserCreated
class UserCreated {
public function __construct(public $user) {}
}
// Listener - SendWelcomeEmail
class SendWelcomeEmail {
public function handle(UserCreated $event) {
Mail::to($event->user->email)->send(new WelcomeEmail($event->user));
}
}
// EventServiceProvider - Register event and listener
protected $listen = [
UserCreated::class => [SendWelcomeEmail::class],
];
RESTful APIs & GraphQL
RESTful APIs
REST APIs follow standard HTTP methods like GET, POST, PUT, and DELETE.
Example using Laravel:
// Routes (routes/api.php)
Route::get('users', [UserController::class, 'index']);
Route::post('users', [UserController::class, 'store']);
Route::get('users/{id}', [UserController::class, 'show']);
Route::put('users/{id}', [UserController::class, 'update']);
Route::delete('users/{id}', [UserController::class, 'destroy']);
// Controller
class UserController extends Controller {
public function index() {
return User::all(); // Return all users
}
public function store(Request $request) {
return User::create($request->all()); // Create a new user
}
public function show($id) {
return User::findOrFail($id); // Return specific user
}
public function update(Request $request, $id) {
$user = User::findOrFail($id);
$user->update($request->all());
return $user; // Update user
}
public function destroy($id) {
User::findOrFail($id)->delete();
return response(null, 204); // Delete user
}
}
JWT Authentication in Laravel
To secure the API using JWT, install and configure the tymon/jwt-auth
package.
Example:
// Controller for user authentication
class AuthController extends Controller {
public function login(Request $request) {
$credentials = $request->only('email', 'password');
if (!$token = auth()->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return response()->json(['token' => $token]);
}
}
GraphQL with Laravel
GraphQL allows more flexible querying compared to REST. For Laravel, rebing/graphql-laravel
is a popular package.
Example:
// GraphQL Query Definition
class UserQuery extends Query {
protected $attributes = ['name' => 'user'];
public function type(): Type {
return GraphQL::type('User');
}
public function args(): array {
return ['id' => ['type' => Type::int()]];
}
public function resolve($root, $args) {
return User::find($args['id']);
}
}
Scalability & Performance
Caching Strategies: Redis & Memcached
Laravel supports Redis and Memcached out of the box. For example, using Redis for caching:
// Store data in cache
Cache::put('key', 'value', 600); // Store for 600 seconds (10 minutes)
// Retrieve data from cache
$value = Cache::get('key');
Performance Tuning
Profiling: Use tools like Xdebug or Blackfire to profile your PHP application.
Memory Usage Optimization: Avoid loading large datasets into memory. Use pagination instead.
Example:
// Use chunking to process large datasets
User::chunk(100, function($users) {
foreach ($users as $user) {
// Process each user
}
});
Queues & Workers
Laravel Queues
Queues allow you to defer time-consuming tasks (e.g., sending emails) to background workers.
Example:
// Dispatch a job
SendEmailJob::dispatch($user);
// Job class
class SendEmailJob implements ShouldQueue {
public function __construct(public $user) {}
public function handle() {
Mail::to($this->user->email)->send(new WelcomeEmail($this->user));
}
}
Task Scheduling
Laravel’s task scheduling system allows you to schedule jobs easily using a fluent API.
Example:
// Schedule a job to run daily
$schedule->job(new CleanupJob)->daily();
RabbitMQ/Beanstalkd
For advanced use cases, you can integrate RabbitMQ or Beanstalkd for managing complex queueing systems. Laravel supports these through drivers or external packages.
These examples cover practical applications of architectural principles, API design, scalability, and queues, giving you a solid understanding of how to implement these in PHP or Laravel projects.
Subscribe to my newsletter
Read articles from Dale Lanto directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Dale Lanto
Dale Lanto
A passionate Full Stack and Backend Web Developer with 7+ years of experience, specializing in PHP, Laravel, and a range of modern web technologies. I enjoy solving complex problems, optimizing systems, and delivering efficient, maintainable code. Check out some of my work at dalelanto.netlify.app or explore my GitHub at github.com/dalelantowork.