php-guidelines-from-spatie
40
总安装量
40
周安装量
#5224
全站排名
安装命令
npx skills add https://github.com/freekmurze/dotfiles --skill php-guidelines-from-spatie
Agent 安装分布
claude-code
33
opencode
30
codex
22
gemini-cli
21
github-copilot
21
antigravity
19
Skill 文档
Core Laravel Principle
Follow Laravel conventions first. If Laravel has a documented way to do something, use it. Only deviate when you have a clear justification.
PHP Standards
- Follow PSR-1, PSR-2, and PSR-12
- Use camelCase for non-public-facing strings
- Use short nullable notation:
?stringnotstring|null - Always specify
voidreturn types when methods return nothing
Class Structure
- Use typed properties, not docblocks:
- Constructor property promotion when all properties can be promoted:
- One trait per line:
Type Declarations & Docblocks
- Use typed properties over docblocks
- Specify return types including
void - Use short nullable syntax:
?TypenotType|null - Document iterables with generics:
/** @return Collection<int, User> */ public function getUsers(): Collection
Docblock Rules
- Don’t use docblocks for fully type-hinted methods (unless description needed)
- Always import classnames in docblocks – never use fully qualified names:
use \Spatie\Url\Url; /** @return Url */ - Use one-line docblocks when possible:
/** @var string */ - Most common type should be first in multi-type docblocks:
/** @var Collection|SomeWeirdVendor\Collection */ - If one parameter needs docblock, add docblocks for all parameters
- For iterables, always specify key and value types:
/** * @param array<int, MyObject> $myArray * @param int $typedArgument */ function someFunction(array $myArray, int $typedArgument) {} - Use array shape notation for fixed keys, put each key on it’s own line:
/** @return array{ first: SomeClass, second: SomeClass } */
Control Flow
- Happy path last: Handle error conditions first, success case last
- Avoid else: Use early returns instead of nested conditions
- Separate conditions: Split compound
ifstatements that use&&into nestedifstatements for better readability - Always use curly brackets even for single statements
- Ternary operators: Each part on own line unless very short
// Happy path last
if (! $user) {
return null;
}
if (! $user->isActive()) {
return null;
}
// Process active user...
// Short ternary
$name = $isFoo ? 'foo' : 'bar';
// Multi-line ternary
$result = $object instanceof Model ?
$object->name :
'A default value';
// Ternary instead of else
$condition
? $this->doSomething()
: $this->doSomethingElse();
// Bad: compound condition with &&
if ($user->isActive() && $user->hasPermission('edit')) {
$user->edit();
}
// Good: nested ifs
if ($user->isActive()) {
if ($user->hasPermission('edit')) {
$user->edit();
}
}
Laravel Conventions
Routes
- URLs: kebab-case (
/open-source) - Route names: camelCase (
->name('openSource')) - Parameters: camelCase (
{userId}) - Use tuple notation:
[Controller::class, 'method']
Controllers
- Plural resource names (
PostsController) - Stick to CRUD methods (
index,create,store,show,edit,update,destroy) - Extract new controllers for non-CRUD actions
Configuration
- Files: kebab-case (
pdf-generator.php) - Keys: snake_case (
chrome_path) - Add service configs to
config/services.php, don’t create new files - Use
config()helper, avoidenv()outside config files
Artisan Commands
- Names: kebab-case (
delete-old-records) - Always provide feedback (
$this->comment('All ok!')) - Show progress for loops, summary at end
- Put output BEFORE processing item (easier debugging):
$items->each(function(Item $item) { $this->info("Processing item id `{$item->id}`..."); $this->processItem($item); }); $this->comment("Processed {$items->count()} items.");
Strings & Formatting
- String interpolation over concatenation:
Enums
- Use PascalCase for enum values:
Comments
Be very critical about adding comments as they often become outdated and can mislead over time. Code should be self-documenting through descriptive variable and function names.
Adding comments should never be the first tactic to make code readable.
Instead of this:
// Get the failed checks for this site
$checks = $site->checks()->where('status', 'failed')->get();
Do this:
$failedChecks = $site->checks()->where('status', 'failed')->get();
Guidelines:
- Don’t add comments that describe what the code does – make the code describe itself
- Short, readable code doesn’t need comments explaining it
- Use descriptive variable names instead of generic names + comments
- Only add comments when explaining why something non-obvious is done, not what is being done
- Never add comments to tests – test names should be descriptive enough
Whitespace
- Add blank lines between statements for readability
- Exception: sequences of equivalent single-line operations
- No extra empty lines between
{}brackets - Let code “breathe” – avoid cramped formatting
Validation
- Use array notation for multiple rules (easier for custom rule classes):
public function rules() { return [ 'email' => ['required', 'email'], ]; } - Custom validation rules use snake_case:
Validator::extend('organisation_type', function ($attribute, $value) { return OrganisationType::isValid($value); });
Blade Templates
- Indent with 4 spaces
- No spaces after control structures:
@if($condition) Something @endif
Authorization
- Policies use camelCase:
Gate::define('editPost', ...) - Use CRUD words, but
viewinstead ofshow
Translations
- Use
__()function over@lang:
API Routing
- Use plural resource names:
/errors - Use kebab-case:
/error-occurrences - Limit deep nesting for simplicity:
/error-occurrences/1 /errors/1/occurrences
Testing
- Keep test classes in same file when possible
- Use descriptive test method names
- Follow the arrange-act-assert pattern
Quick Reference
Naming Conventions
- Classes: PascalCase (
UserController,OrderStatus) - Methods/Variables: camelCase (
getUserName,$firstName) - Routes: kebab-case (
/open-source,/user-profile) - Config files: kebab-case (
pdf-generator.php) - Config keys: snake_case (
chrome_path) - Artisan commands: kebab-case (
php artisan delete-old-records)
File Structure
- Controllers: plural resource name +
Controller(PostsController) - Views: camelCase (
openSource.blade.php) - Jobs: action-based (
CreateUser,SendEmailNotification) - Events: tense-based (
UserRegistering,UserRegistered) - Listeners: action +
Listenersuffix (SendInvitationMailListener) - Commands: action +
Commandsuffix (PublishScheduledPostsCommand) - Mailables: purpose +
Mailsuffix (AccountActivatedMail) - Resources/Transformers: plural +
Resource/Transformer(UsersResource) - Enums: descriptive name, no prefix (
OrderStatus,BookingType)
Migrations
- do not write down methods in migrations, only up methods
Code Quality Reminders
PHP
- Use typed properties over docblocks
- Prefer early returns over nested if/else
- Use constructor property promotion when all properties can be promoted
- Avoid
elsestatements when possible - Split compound
ifconditions using&&into nestedifstatements - Use string interpolation over concatenation
- Always use curly braces for control structures
- Always import namespaces with
usestatements â never use inline fully qualified class names (e.g.\Exception,\Illuminate\Support\Facades\Http) - Never use single-letter variable names â use descriptive names (e.g.
$exceptionnot$e,$requestnot$r)