Naming Conventions
Overview
Consistent naming conventions improve code readability, maintainability, and team collaboration. This document defines the naming standards for the Laravel backend.
General Principles
Be Descriptive and Clear
php
// Bad - Unclear abbreviations
$u = User::find(1);
$dt = now();
$arr = [];
// Good - Clear and descriptive
$user = User::find(1);
$createdDate = now();
$activeUsers = [];Use Pronounceable Names
php
// Bad
$usrCrtDt = now();
$prdCatMgr = new ProductCategoryManager();
// Good
$userCreatedDate = now();
$productCategoryManager = new ProductCategoryManager();Avoid Mental Mapping
php
// Bad - What does 'i' represent?
for ($i = 0; $i < count($users); $i++) {
// ...
}
// Good - Clear iteration
foreach ($users as $user) {
// ...
}File Names
Controllers
Format: [Singular]Controller.php
Examples:
UserController.php
PostController.php
OrderController.php
ProductCategoryController.phpModels
Format: [Singular].php
Examples:
User.php
Post.php
Order.php
OrderItem.php
ProductCategory.phpMigrations
Format: yyyy_mm_dd_hhiiss_[action]_[table]_table.php
Examples:
2024_01_01_000000_create_users_table.php
2024_01_02_120000_add_phone_to_users_table.php
2024_01_03_153000_create_posts_table.php
2024_01_04_090000_add_indexes_to_posts_table.phpSeeders
Format: [Table]Seeder.php or [Purpose]Seeder.php
Examples:
DatabaseSeeder.php
UserSeeder.php
PostSeeder.php
RolePermissionSeeder.phpRequests
Format: [Action][Model]Request.php
Examples:
StoreUserRequest.php
UpdateUserRequest.php
DeletePostRequest.php
PublishPostRequest.phpResources
Format: [Model]Resource.php or [Model]Collection.php
Examples:
UserResource.php
UserCollection.php
PostResource.php
OrderResource.phpServices
Format: [Model]Service.php or [Purpose]Service.php
Examples:
UserService.php
OrderService.php
PaymentService.php
NotificationService.phpRepositories
Format: [Model]Repository.php
Examples:
UserRepository.php
PostRepository.php
OrderRepository.phpJobs
Format: [VerbPhrase].php
Examples:
ProcessPayment.php
SendWelcomeEmail.php
GenerateReport.php
SyncUserData.php
ExportOrdersToCSV.phpEvents
Format: [ModelOrSubject][PastTense].php
Examples:
UserRegistered.php
OrderPlaced.php
PaymentProcessed.php
PostPublished.php
EmailSent.phpListeners
Format: [VerbPhrase].php
Examples:
SendWelcomeEmail.php
UpdateUserStatistics.php
NotifyAdminOfNewOrder.php
LogUserActivity.phpMiddleware
Format: [PurposeOrAction].php
Examples:
EnsureEmailIsVerified.php
CheckUserRole.php
LogApiRequests.php
CheckSubscription.php
ValidateApiKey.phpTraits
Format: [Descriptive][Trait optional].php
Examples:
HasUuid.php
Searchable.php
Sluggable.php
Taggable.php
HasAvatar.phpPolicies
Format: [Model]Policy.php
Examples:
UserPolicy.php
PostPolicy.php
OrderPolicy.phpExceptions
Format: [Description]Exception.php
Examples:
UserNotFoundException.php
PaymentFailedException.php
InvalidCredentialsException.php
ResourceNotFoundException.phpClass Names
General Rule: PascalCase (UpperCamelCase)
php
class UserController extends Controller { }
class PaymentService { }
class OrderRepository { }
class ProcessPayment implements ShouldQueue { }Models
php
// Singular, descriptive nouns
class User extends Model { }
class Post extends Model { }
class Order extends Model { }
class OrderItem extends Model { }
class ProductCategory extends Model { }
class BlogPost extends Model { }
// Pivot models (optional)
class PostTag extends Model { }
class UserRole extends Model { }Controllers
php
// Singular noun + "Controller"
class UserController extends Controller { }
class PostController extends Controller { }
class OrderController extends Controller { }
// Resource controllers
class Api\V1\UserController extends Controller { }
class Admin\DashboardController extends Controller { }
// Specific purpose controllers
class Auth\LoginController extends Controller { }
class Auth\RegisterController extends Controller { }Services
php
// Purpose + "Service"
class UserService { }
class OrderService { }
class PaymentService { }
class NotificationService { }
class EmailService { }
class ReportService { }Repositories
php
// Model + "Repository"
class UserRepository { }
class PostRepository { }
class OrderRepository { }
class ProductRepository { }Resources (API Transformers)
php
// Model + "Resource"
class UserResource extends JsonResource { }
class PostResource extends JsonResource { }
class OrderResource extends JsonResource { }
// Collections
class UserCollection extends ResourceCollection { }Method Names
General Rule: camelCase
php
public function getUserById(int $id): User { }
public function createNewPost(array $data): Post { }
public function updateOrderStatus(Order $order, string $status): void { }CRUD Operations
php
// Create
public function create(array $data): Model
public function store(Request $request): Response
public function insert(array $data): bool
// Read/Retrieve
public function find(int $id): ?Model
public function get(): Collection
public function all(): Collection
public function show(Model $model): Response
public function index(): Response
// Update
public function update(Model $model, array $data): Model
public function save(Model $model): bool
public function patch(Model $model, array $data): Model
// Delete
public function delete(Model $model): bool
public function destroy(Model $model): Response
public function remove(int $id): bool
public function forceDelete(Model $model): boolBoolean Methods
Use prefixes: is, has, can, should, will
php
// is - State check
public function isActive(): bool
public function isPublished(): bool
public function isAdmin(): bool
public function isEmpty(): bool
// has - Possession/existence
public function hasPermission(string $permission): bool
public function hasRole(string $role): bool
public function hasPosts(): bool
public function hasActiveSubscription(): bool
// can - Capability/permission
public function canEdit(): bool
public function canDelete(): bool
public function canPublish(): bool
public function canAccessResource(): bool
// should - Conditional logic
public function shouldNotify(): bool
public function shouldSendEmail(): bool
public function shouldRefresh(): bool
// will - Future action
public function willExpire(): bool
public function willAutoRenew(): boolAction Methods
Use clear action verbs:
php
// Process/Handle
public function processPayment(array $data): PaymentResult
public function handleWebhook(Request $request): void
public function execute(): void
// Send/Notify
public function sendEmail(User $user): void
public function sendNotification(string $message): void
public function notifyUsers(Collection $users): void
// Generate/Build
public function generateReport(): Report
public function generateInvoice(Order $order): Invoice
public function buildQuery(): Builder
// Calculate/Compute
public function calculateTotal(Order $order): float
public function calculateDiscount(User $user): float
public function computeStatistics(): array
// Validate/Verify/Check
public function validateInput(array $data): bool
public function verifyEmail(string $token): bool
public function checkAvailability(): bool
// Transform/Convert
public function transformData(array $data): array
public function convertToArray(): array
public function toJson(): string
// Activate/Deactivate
public function activate(): void
public function deactivate(): void
public function enable(): void
public function disable(): void
// Approve/Reject
public function approve(): void
public function reject(string $reason): void
// Publish/Unpublish
public function publish(): void
public function unpublish(): void
// Archive/Restore
public function archive(): void
public function restore(): voidController Actions
php
// Standard resource methods
public function index(): Response // List all
public function create(): Response // Show create form
public function store(Request $request): Response // Save new
public function show(Model $model): Response // Display one
public function edit(Model $model): Response // Show edit form
public function update(Request $request, Model $model): Response // Update
public function destroy(Model $model): Response // DeleteScopes (Model)
php
// Prefix with "scope", use camelCase after
public function scopeActive($query)
public function scopePublished($query)
public function scopeRecent($query)
public function scopeByAuthor($query, User $author)
public function scopeWithComments($query)
public function scopePopular($query)Variable Names
General Rule: camelCase
php
$userName = 'John Doe';
$userEmail = 'john@example.com';
$isActive = true;
$createdAt = now();
$totalAmount = 100.50;Collections and Arrays
Use plural form:
php
// Collections
$users = User::all();
$posts = Post::where('status', 'published')->get();
$activeOrders = Order::active()->get();
// Arrays
$roles = ['admin', 'user', 'moderator'];
$permissions = ['create', 'read', 'update', 'delete'];
$errors = [];Single Items
Use singular form:
php
$user = User::find(1);
$post = Post::first();
$order = Order::latest()->first();
$product = Product::findOrFail($id);Boolean Variables
Use descriptive names with prefixes:
php
// is - State
$isActive = true;
$isPublished = false;
$isAdmin = $user->role === 'admin';
$isEmpty = count($items) === 0;
// has - Possession
$hasPermission = true;
$hasErrors = !empty($errors);
$hasPosts = $user->posts()->exists();
// can - Capability
$canEdit = $user->can('edit', $post);
$canDelete = false;
// should - Conditional
$shouldNotify = true;
$shouldSendEmail = $user->email_notifications;Temporary Variables
php
// Use descriptive names even for temp variables
foreach ($users as $user) {
foreach ($user->posts as $post) {
// Good
$publishedDate = $post->published_at;
// Avoid
$temp = $post->published_at;
}
}Constants
General Rule: UPPER_SNAKE_CASE
php
// Class constants
class Order
{
const STATUS_PENDING = 'pending';
const STATUS_PROCESSING = 'processing';
const STATUS_COMPLETED = 'completed';
const STATUS_CANCELLED = 'cancelled';
const PAYMENT_METHOD_CARD = 'card';
const PAYMENT_METHOD_CASH = 'cash';
const PAYMENT_METHOD_TRANSFER = 'transfer';
const MAX_ITEMS = 100;
const DEFAULT_TAX_RATE = 0.15;
}
// Global constants (avoid if possible, use config instead)
define('APP_VERSION', '1.0.0');
define('MAX_UPLOAD_SIZE', 10240);Configuration Keys
Use snake_case:
php
// config/app.php
return [
'name' => env('APP_NAME', 'Laravel'),
'env' => env('APP_ENV', 'production'),
'debug' => env('APP_DEBUG', false),
'url' => env('APP_URL', 'http://localhost'),
'asset_url' => env('ASSET_URL', null),
'timezone' => 'UTC',
'locale' => 'en',
'fallback_locale' => 'en',
'max_upload_size' => 10240,
'allowed_file_types' => ['jpg', 'png', 'pdf'],
];Database Names
Tables
Use snake_case, plural:
users
posts
orders
order_items
product_categories
user_roles (pivot table)
post_tags (pivot table)Columns
Use snake_case:
sql
id
name
email
email_verified_at
password
remember_token
created_at
updated_at
deleted_at
-- Multi-word columns
first_name
last_name
phone_number
birth_date
is_active
is_verifiedForeign Keys
Format: [singular_table]_id
sql
user_id
post_id
order_id
category_id
parent_id
author_idPivot Tables
Alphabetical order, singular, snake_case:
sql
post_tag (not tags_posts or posts_tags)
role_user (not users_roles)
category_productIndexes
Format: [table]_[columns]_[type]
sql
-- Standard index
users_email_index
posts_created_at_index
-- Unique index
users_email_unique
-- Foreign key
posts_user_id_foreign
-- Composite
posts_user_id_created_at_indexRoutes
Route Names
Use dot notation, snake_case:
php
// routes/api.php
Route::get('/users', [UserController::class, 'index'])->name('users.index');
Route::post('/users', [UserController::class, 'store'])->name('users.store');
Route::get('/users/{user}', [UserController::class, 'show'])->name('users.show');
Route::put('/users/{user}', [UserController::class, 'update'])->name('users.update');
Route::delete('/users/{user}', [UserController::class, 'destroy'])->name('users.destroy');
// Custom routes
Route::post('/users/{user}/activate', [UserController::class, 'activate'])
->name('users.activate');
Route::get('/posts/published', [PostController::class, 'published'])
->name('posts.published');URL Paths
Use kebab-case, plural for resources:
php
/api/v1/users
/api/v1/posts
/api/v1/product-categories
/api/v1/order-items
// Actions
/api/v1/users/{user}/activate
/api/v1/posts/{post}/publish
/api/v1/orders/{order}/cancelView/Blade Files
File Names
Use kebab-case:
user-profile.blade.php
post-list.blade.php
order-details.blade.php
email-verification.blade.phpDirectories
resources/views/
auth/
login.blade.php
register.blade.php
users/
index.blade.php
show.blade.php
edit.blade.php
posts/
index.blade.php
show.blade.php
emails/
welcome.blade.php
order-confirmation.blade.phpNamespaces
Format: Pascal Case with backslashes
php
namespace App\Http\Controllers;
namespace App\Http\Controllers\Api\V1;
namespace App\Services\User;
namespace App\Repositories;
namespace App\Models;
namespace App\Events;
namespace App\Listeners;
namespace App\Jobs;
namespace App\Mail;
namespace App\Exceptions;
namespace App\Exceptions\Domain;Environment Variables
Format: UPPER_SNAKE_CASE
env
APP_NAME=Laravel
APP_ENV=production
APP_KEY=base64:...
APP_DEBUG=false
APP_URL=https://api.example.com
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=myapp
DB_USERNAME=root
DB_PASSWORD=secret
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@example.com
MAIL_FROM_NAME="${APP_NAME}"
SENTRY_LARAVEL_DSN=
STRIPE_KEY=
STRIPE_SECRET=Enums (PHP 8.1+)
Enum Names: PascalCase
php
// app/Enums/OrderStatus.php
namespace App\Enums;
enum OrderStatus: string
{
case PENDING = 'pending';
case PROCESSING = 'processing';
case SHIPPED = 'shipped';
case DELIVERED = 'delivered';
case CANCELLED = 'cancelled';
}
// app/Enums/UserRole.php
enum UserRole: string
{
case ADMIN = 'admin';
case USER = 'user';
case MODERATOR = 'moderator';
}
// app/Enums/PaymentMethod.php
enum PaymentMethod: string
{
case CARD = 'card';
case CASH = 'cash';
case BANK_TRANSFER = 'bank_transfer';
}Test Names
Test Classes
Format: [ClassName]Test.php
php
// tests/Unit/UserServiceTest.php
class UserServiceTest extends TestCase { }
// tests/Feature/UserControllerTest.php
class UserControllerTest extends TestCase { }
// tests/Feature/Api/V1/PostTest.php
class PostTest extends TestCase { }Test Methods
Format: test_[what_it_does]
php
public function test_user_can_be_created()
public function test_user_email_must_be_unique()
public function test_user_can_update_profile()
public function test_user_cannot_delete_other_users()
public function test_returns_404_when_user_not_found()
public function test_validates_required_fields()Summary Table
| Element | Convention | Example |
|---|---|---|
| Classes | PascalCase | UserController, OrderService |
| Methods | camelCase | getUserById, createOrder |
| Variables | camelCase | $userName, $isActive |
| Constants | UPPER_SNAKE_CASE | MAX_ATTEMPTS, STATUS_ACTIVE |
| Tables | snake_case, plural | users, order_items |
| Columns | snake_case | created_at, first_name |
| Routes (names) | dot.snake_case | users.index, posts.show |
| URLs | kebab-case | /product-categories, /order-items |
| Files | PascalCase.php | UserController.php, User.php |
| Blade files | kebab-case | user-profile.blade.php |
| Env variables | UPPER_SNAKE_CASE | APP_NAME, DB_HOST |
| Config keys | snake_case | app.name, database.default |
| Namespaces | PascalCase\With\Backslash | App\Http\Controllers |