Laravel
| What |
How |
Good |
Bad |
| Blade |
kebab-case |
partials.top-header |
@include('top_header') |
| Collections |
Plural, camelCase |
activeUsers |
active_users |
| Commands |
kebab-case |
send-email |
SendEmail |
| Config |
snake_case |
google_calendar.php |
google-calendar.php |
| Controllers |
Singular |
UserController |
UsersController |
| Functions |
snake_case |
get_user |
getUser |
| Methods |
camelCase |
getUsers |
get_users |
| Models |
Singular |
User |
Users |
| Route Names |
dot notation |
tickets.show |
tickets-show |
| Routes |
Plural |
articles/1 |
article/1 |
| Tables |
Plural |
users |
user |
| URLs |
kebab-case |
/about-us |
/about_us |
| Variables |
camelCase |
userName |
$user_name |
| Views |
kebab-case |
show-user.blade.php |
show_user.blade.php |
Classes
Models
- PascalCase, singular form
- Prefix related models with parent name
// Good
class User extends Model
class Ticket extends Model
class MashCategory extends Model
class MashItem extends Model
class ExerciseVideo extends Model
// Bad
class Users extends Model // Plural
class mash_category extends Model // snake_case
Actions
- PascalCase, verb-first naming
- Describe the action being performed
// Good
class CreateTicket
class UpdateItem
class DeleteUser
class ConvertKilogramsToPounds
class GetAllActiveRepeatingReminders
class BuildUserSettingDefaults
// Bad
class TicketCreator // Noun instead of verb
class HandleTicket // Too vague
Data Transfer Objects (DTOs)
- PascalCase, suffixed with
Data
// Good
class TicketData extends Data
class StoreData extends Data
class PlanData extends Data
// Bad
class TicketDTO extends Data // Use Data suffix
class Ticket extends Data // Conflicts with model
Enums
- PascalCase, singular
- Values in PascalCase or UPPER_SNAKE_CASE
// Good
enum Status: int
{
case Pending = 0;
case Active = 1;
case Completed = 2;
}
enum WeightTypes: string
{
case Kilograms = 'kg';
case Pounds = 'lbs';
}
Traits
- PascalCase, prefixed with
Has or descriptive verb
// Good
trait HasHashIds
trait HasActiveInactive
trait HasSlug
trait HasTags
// Bad
trait HashIdsTrait // Suffix instead of prefix
trait Active // Not descriptive
Livewire Components
- PascalCase, descriptive of the view/feature
// Good
class Dashboard extends Component
class Login extends Component
class TicketList extends Component
class LoginForm extends Form
// Bad
class DashboardComponent // Redundant suffix
Methods
General Methods
- camelCase
- Verb-first for actions
// Good
public function execute(TicketData $data): Ticket
public function authenticate(): void
public function generateSlug(): string
// Bad
public function Execute() // PascalCase
public function ticket_create() // snake_case
Query Scopes
- camelCase, prefixed with
scope
- Descriptive of the filter
// Good
public function scopeActive(Builder $query): Builder
public function scopeDueThisWeek(Builder $query): Builder
public function scopeForUser(Builder $query, User $user): Builder
// Bad
public function scopeGetActive() // Redundant "Get"
public function active() // Missing scope prefix
Relationship Methods
- camelCase
- Singular for belongsTo/hasOne, plural for hasMany
// Good
public function user(): BelongsTo
public function category(): BelongsTo
public function items(): HasMany
public function tickets(): HasMany
// Bad
public function getUser() // Redundant prefix
public function item(): HasMany // Singular for hasMany
Protected/Private Helpers
- camelCase, descriptive names
// Good
protected function ensureIsNotRateLimited(): void
protected function throttleKey(): string
private function calculateTotal(): float
// Bad
protected function helper() // Not descriptive
private function _doSomething() // Underscore prefix
Properties
Class Properties
- camelCase for PHP properties
- Type hints always present
// Good
public string $email = '';
public bool $rememberMe = false;
private int $maxAttempts = 5;
// Bad
public $email; // Missing type hint
public string $Email; // PascalCase
Database Properties
- snake_case for database-related
// Good
protected $guarded = ['id'];
protected $casts = [
'is_active' => 'boolean',
'due_at' => 'datetime',
];
// Bad
protected $Guarded = ['id']; // PascalCase
Database
Tables
// Good
users
tickets
mash_items
mash_categories
exercise_videos
// Bad
User // PascalCase, singular
MashItems // PascalCase
Columns
- snake_case
- Boolean: prefix with
is_ or has_
- Foreign keys:
{model}_id
- Timestamps:
_at suffix
// Good
id
hash_id
user_id
category_id
is_active
has_subscription
created_at
due_at
next_reminder_at
// Bad
userId // camelCase
isActive // camelCase
active // Missing is_ prefix
createdAt // camelCase
Indexes
// Good
$table->index(['user_id', 'is_active']);
$table->unique(['name', 'user_id']);
// Bad
$table->index(['user_id', 'is_active'], 'idx1'); // Non-descriptive name
Files
PHP Files
- Match class name exactly
- One class per file
// Good
CreateTicket.php → class CreateTicket
TicketData.php → class TicketData
HasHashIds.php → trait HasHashIds
// Bad
create-ticket.php // kebab-case
ticketData.php // camelCase
Blade Views
// Good
resources/views/dashboard.blade.php
resources/views/components/primary-button.blade.php
resources/views/livewire/ticket-list.blade.php
// Bad
resources/views/Dashboard.blade.php
resources/views/components/primaryButton.blade.php
Migration Files
- Laravel default format:
{timestamp}_create_{table}_table.php
// Good
2024_01_15_000000_create_users_table.php
2024_01_15_000001_create_tickets_table.php
2024_01_16_000000_add_status_to_tickets_table.php
Routes
Route Names
- snake_case or dot notation for resources
// Good
Route::get('/dashboard')->name('dashboard');
Route::get('/tickets')->name('tickets.index');
Route::post('/tickets')->name('tickets.store');
// Bad
Route::get('/dashboard')->name('Dashboard');
Route::get('/tickets')->name('ticketsList');
Translations
Translation Parameters
- camelCase for parameter names
// Good
{{ __('orders.total', ['itemCount' => $count, 'totalPrice' => $total]) }}
{{ __('users.greeting', ['userName' => $user->name]) }}
// Bad
{{ __('orders.total', ['item_count' => $count, 'total_price' => $total]) }}