-
Ensure no redundant code blocks or logic duplications.
Example
: Refactor repetitive code into a reusable function or service.// Old implementation public function index() { $users = User::all(); return view('users.index', compact('users')); } // Refactored implementation public function index() { $users = $this->service->getAllUsers(); return view('users.index', compact('users')); }
Regularly refactor code to eliminate redundancy and improve maintainability.
-
Verify all code and features are fully implemented and thoroughly tested.
Example
: Ensure all endpoints have corresponding tests.public function testIndex() { $response = $this->get('/users'); $response->assertStatus(200); }
Conduct code reviews and use checklists to ensure completeness.
-
Use the Prettier package for code formatting.
Example
: Configure Prettier in your project.npm install --save-dev prettier echo {}> .prettierrc.json
Format code every time changes are made to ensure consistency.
-
Use 4 spaces for indentation across all files.
-
Limit lines to 120 characters. Wrap lines that exceed this limit to maintain readability.
public function exampleFunction() { $longVariableName = "This is a very long string that exceeds the line length limit and needs to be wrapped."; }
Follow the standard Laravel directory structure. Group related classes, traits, and interfaces into appropriate subdirectories under the app directory.
-
Use PascalCase and suffix with Controller.
Example:
UserController
-
Use singular PascalCase.
Example:
User
,Order
-
Suffix with Factory.
Example:
UserFactory
-
Use PascalCase for migration files matching the model name for easy identification. Example:
CreateUserTable
Use camelCase for method names.
Use descriptive names for methods that convey their purpose.
Example: getActiveUsers
, calculateTotalAmount
Use camelCase for variable names.
Use meaningful and descriptive names for variables.
Example: $userEmail
, $totalAmount
Use Enums for listing constant variables to avoid mistakes.
enum UserTypeEnum: string {
case ADMIN = 'admin';
case RESTAURANT_OWNER = 'restaurant_owner';
// More cases...
}
// Accessing:
UserTypeEnum::ADMIN->value
-
Keep controllers thin by delegating logic to service classes and traits for repetitive methods.
// OrderController public function store(OrderRequest $request) { $data = CreateOrderData::from($request->validated()); $result = $this->service->createOrder($data); return $this->successfulResponse($result, __('Order created successfully')); }
-
Use resource controllers for CRUD operations.
Route::resource('users', UserController::class);
-
Follow the order:
constructor
,middleware
,public methods
, andprivate methods
. -
Inject service classes into controllers.
// OrderController public function __construct(private OrderService $service) {}
-
Use Eloquent models for database interactions.
$user = User::find(1); // Find user by ID $users = User::where('email', '[email protected]')->get(); // Find users by email
-
Define
$fillable
properties instead of$guarded
.protected $fillable = ['name', 'email', 'password'];
-
Define relationships using appropriate methods.
public function posts() { return $this->hasMany(Post::class); }
-
Use descriptive names for migration files.
2024_06_27_154523_add_email_column_to_users_table.php
2024_06_27_183012_update_posts_table_add_status_column.php
-
Use up and down methods to define schema changes clearly and revert changes if necessary.
public function up() { Schema::create('users', function (Blueprint $table) { $table->id(); $table->string('name'); $table->timestamps(); }); } public function down() { Schema::dropIfExists('users'); }
-
Use singular PascalCase for table names.
Example:
User
,Order
-
Use snake_case for column names.
Example:
first_name
,created_at
-
Define indexes where necessary to optimise query performance.
$table->index('email');
-
Use RESTful routes for resource controllers.
Route::resource('users', UserController::class);
-
Use kebab-case for route names.
Example:
/user-profile
,/order-items
-
Use
/orders/{id}
instead oforders?id={id}
.
-
Encapsulate business logic in service classes.
class OrderService { public function createOrder(CreateOrderData $data) { // Business logic here } }
-
Use repositories for database interactions beyond basic CRUD operations.
-
Inject services into controllers.
// OrderController public function \_\_construct(private OrderService $service) {} ```3
-
Use Form Request classes for validating incoming data for every
POST
andPUT
API.class CreateUserRequest extends FormRequest { public function rules() { return [ 'name' => 'required|string', 'email' => 'required|email', // More rules... ]; } }
-
Use the Spatie Data package to convert FormRequest data into listed attributes.
use Spatie\LaravelData\Data; class CreateUserData extends Data { public string $name; public string $email; }
-
Create custom validation rules where needed.
<?php namespace App\Rules; use Illuminate\Contracts\Validation\Rule; class PhoneNumber implements Rule { public function passes($attribute, $value, $arguments = []) { $pattern = '/^\d{3}-\d{3}-\d{4}$/'; return preg_match($pattern, $value); } public function message($attribute, $parameters) { return 'The :attribute must be a valid phone number'; } }
-
Use try-catch blocks to handle exceptions gracefully and log errors.
try { // Code that may throw an exception } catch (Exception $e) { Log::error([ "message" => $e->getMessage(), "line" => $e->getLine(), "trace" => $e->getTrace(), "timestamp" => now() ]); }
-
Create custom exceptions for domain-specific errors.
class CustomException extends Exception { // Custom exception logic }
-
Use Pest for testing.
-
Use descriptive names for test methods.
-
Ensure high test coverage for critical parts of the application.
-
Organise tests into appropriate directories.
-
Sanitise and validate all input data.
-
Use Blade’s {{ }} to escape output.
-
Ensure all forms include CSRF tokens.
<form method="POST" action="{{ route('user.store') }}"> @csrf // your codes </form>
-
Use PHPDoc for methods and classes.
class User { /** * Get the user's full name. * @return string The user's full name. */ public function getFullName(): string { return $this->firstName . ' ' . $this->lastName; } }
-
Maintain a README.md with setup instructions and usage examples.
-
Use tools like Swagger or Postman to document APIs.
-
Use a branching strategy (e.g., Git Flow).
Use meaningful commit messages.
-
Use .env for configuration.
-
Store environment-specific settings in config files in the config folder.
Use common naming conventions for input parameters.
-
Follow eager loading in queries.
$users = User::with('posts')->get();
Separate business logic from the controller.
-
Manage validation at the client-side before sending data.
$("#myForm").validate({
rules: { name: "required", email: { required: true, email: true } },
messages: {
name: "Please enter a name.",
email: "Please enter a valid email address.",
},
});
Use traits for methods instead of applying queries directly in controllers.
Add softdeletes trait in models to prevent permanent deletes
class ModelName extends Model
{
use SoftDeletes;
}
Add deleted_at column in migrations to support soft deletes
Schema::create(‘table_name’, function (Blueprint $table) {
// table columns
$table->softDeletes();
});
Standardise API responses using methods from app/Http/Controllers/Controller.php
like:
return response()->json([
'success' => false,
'message' => $message,
'errors' => $errors,
'timestamp' => now()->format('Y-m-d, H:i:s'),
'execution_time' => (microtime(true) - START_EXECUTION_TIME) * 1000 . ' ms',
'cached' => PROCESS_CACHED
], Response::HTTP_UNPROCESSABLE_ENTITY);
-
Use
Route::resource
methods for all resource routes.Example:
Route::resource(‘users', UserController::class);
-
Use kebab casing for URLs.
Example:
/user-profile
,/order-items
-
Use the name method for all URLs.
Route::get('/users/{id}', [UserController::class, ‘show’])->name('user.show');
-
Log each request to the controller.
-
Create activity logs for each endpoint/action.
-
Log errors with the method name.
Use the Lang facade to support multiple languages.
$welcomeMessage = Lang::get('welcome'); //or
$welcomeMessage = trans('welcome');
- Implement additional security measures for API requests.
- Implement login attempt limits and account suspension.
Add comments and descriptions before creating any new function.
/**
* This function retrieves all active users from the database.
**/
function getActiveUsers()
{
// ... function logic
}
Every GET endpoint returning a list should be paginated.
Use helper methods for consistent responses created in app/Http/Controllers/Controller.php
. Like:
function jsonResponseWithPagination($data, $total)
{
return response()->json([
'data' => $data,
'total' => $total,
'timestamp' => now()->format('Y-m-d, H:i:s'),
'execution_time' => (microtime(true) - START_EXECUTION_TIME) * 1000 . ' ms'
]);
}
Every list endpoint should include search capabilities and status check.
Implement search capabilities with necessary columns and add a status column to check the status of the model (the status column should be nullable)