php-patterns
PHP development principles and decision-making. Modern PHP 8.3, Laravel 11, Symfony 7, PSR standards.
ソース情報
- リポジトリ
- skeletorflet/opencode-kit
- ソースの最終更新活動
- 2026年3月31日 19:12
- 検出された SKILL.md の言語
- 英語
- スター
- 9
- フォーク
- 1
インストール方法
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
ソースファイルを確認
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
SKILL.md を表示中
SKILL.md
ソースの指示 · 読み取り専用プレビュー- name
- php-patterns
- description
- PHP development principles and decision-making. Modern PHP 8.3, Laravel 11, Symfony 7, PSR standards.
# PHP Patterns - Modern PHP 8.3
> PHP development principles and decision-making.
> **Learn to THINK, not copy-paste patterns.**
---
## ⚠️ How to Use This Skill
This skill teaches **decision-making principles** for PHP development.
- ASK user for framework preference
- Use PHP 8.x features (attributes, readonly, etc.)
- Don't write PHP 5/7 style code
---
## 1. Framework Selection
### Decision Tree
```
What are you building?
│
├── REST API
│ ├── Laravel (full-featured, most popular)
│ └── Symfony (enterprise, components)
│
├── CMS / Dashboard
│ ├── Laravel + Filament (fast admin)
│ ├── Laravel + Livewire (interactive)
│ └── Symfony (Symfony UX)
│
├── Simple API / Microservice
│ ├── Laravel (if you need full features)
│ ├── Slim (minimalist)
│ ├── Lumen (lightweight Laravel)
│ └── Flight (very simple)
│
├── CLI Tools
│ ├── Laravel Artisan
│ └── Symfony Console
│
└── Real-time / WebSocket
├── Laravel + Reverb (Pusher alternative)
└── Symfony + Mercure
```
### Comparison Table
| Factor | Laravel | Symfony | Slim |
|--------|---------|---------|------|
| **Ecosystem** | Largest | Very large | Small |
| **Learning Curve** | Low-Medium | Medium | Very Low |
| **Admin Tools** | Filament/Panel | EasyAdmin | None |
| **Flexibility** | Opinionated | Modular | Minimal |
| **Best For** | Full-stack, rapid dev | Enterprise, K8s | Simple APIs |
---
## 2. PHP 8.3 Features
### Attributes (New in PHP 8)
```php
// OLD: Doctrine annotations
/**
* @Entity
* @Table(name="users")
*/
class User
{
/**
* @Id
* @GeneratedValue
*/
private int $id;
}
// NEW: PHP 8 Attributes
#[ORM\Entity]
#[ORM\Table(name: 'users')]
class User
{
#[ORM\Id]
#[ORM\GeneratedValue]
private int $id;
}
```
### Readonly Properties
```php
// Readonly (cannot be changed after construction)
class User
{
public function __construct(
public readonly int $id,
public readonly string $name,
public readonly string $email
) {}
}
// Cannot do this (will error):
$user->name = "Other"; // ❌ Error!
```
### constructor Property Promotion
```php
// Before PHP 8
class User
{
private int $id;
private string $name;
private string $email;
public function __construct(int $id, string $name, string $email)
{
$this->id = $id;
$this->name = $name;
$this->email = $email;
}
}
// PHP 8: Constructor property promotion
class User
{
public function __construct(
public int $id,
public string $name,
public string $email
) {}
}
```
### Match Expression
```php
// OLD: switch
$status = match ($statusCode) {
200 => 'success',
404 => 'not_found',
500 => 'error',
default => 'unknown',
};
// With full expression
$result = match ($input) {
$a => 'a',
$b => 'b',
default => 'other',
};
```
---
## 3. Laravel Patterns
### Service Container
```php
// Binding interfaces to implementations
$this->app->bind(
UserRepositoryInterface::class,
UserRepository::class
);
// Singleton (one instance)
$this->app->singleton(
ConfigService::class,
fn() => new ConfigService(config('app.config'))
);
// Facade pattern (static-like access)
User::find(1); // Actually: UserRepository::class->find(1)
```
### Eloquent ORM
```php
// Model with relationships
class User extends Model
{
protected $fillable = ['name', 'email'];
// Relationship
public function posts(): HasMany
{
return $this->hasMany(Post::class);
}
// Accessor
public function getFullNameAttribute(): string
{
return "{$this->name} (ID: {$this->id})";
}
}
// Query scopes
class User extends Model
{
public function scopeActive($query)
{
return $query->where('is_active', true);
}
}
// Usage
User::active()->where('role', 'admin')->get();
```
### Controller Patterns
```php
// REST controller
class UserController extends Controller
{
public function index(): JsonResponse
{
$users = User::with('posts')->paginate(10);
return response()->json($users);
}
public function store(Request $request): JsonResponse
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users'
]);
$user = User::create($validated);
return response()->json($user, 201);
}
}
```
---
## 4. Symfony Patterns
### Dependency Injection
```php
// Services.yaml
services:
App\Service\UserService:
arguments:
$repository: '@App\Repository\UserRepository'
// Service class
class UserService
{
public function __construct(
private UserRepository $repository,
private MailerInterface $mailer
) {}
}
```
### Symfony Validation
```php
use Symfony\Component\Validator\Constraints as Assert;
class CreateUserCommand
{
#[Assert\NotBlank]
#[Assert\Email]
public string $email;
#[Assert\NotBlank]
#[Assert\Length(min: 8)]
public string $password;
}
```
---
## 5. PSR Standards
### PSR-12: PHP Coding Style
```php
<?php
namespace App;
use App\Other\Example;
// Braces on new line, 4 spaces indent
class UserService
{
private int $id;
private string $name;
public function __construct(
int $id,
string $name
) {
$this->id = $id;
$this->name = $name;
}
}
```
### PSR-7: HTTP Messages
```php
use Psr\Http\Message\ServerRequestInterface;
// PSR-7 compatible handlers
function handleRequest(ServerRequestInterface $request)
{
$method = $request->getMethod();
$uri = $request->getUri()->getPath();
return new JsonResponse(['method' => $method]);
}
```
---
## 6. Testing Patterns
### PHPUnit with Coverage
```php
// Unit test
class UserServiceTest extends TestCase
{
public function test_creates_user(): void
{
$service = new UserService(new InMemoryUserRepository());
$user = $service->create('test@example.com');
$this->assertNotNull($user->id);
$this->assertEquals('test@example.com', $user->email);
}
}
// Feature test with HTTP client
class UserApiTest extends TestCase
{
public function test_get_users_returns_json(): void
{
$response = $this->getJson('/api/users');
$response->assertStatus(200);
$response->assertJsonStructure([
'data' => [
'*' => ['id', 'name', 'email']
]
]);
}
}
```
### Testing Tools
| Tool | Purpose |
|------|---------|
| **PHPUnit** | Core testing |
| **Pest** | Cleaner syntax, built on PHPUnit |
| **Mockery** | Mocking |
| **Laravel Dusk** | Browser testing |
| **PHPStan** | Static analysis |
| **PHP-CS-Fixer** | Code style |
---
## 7. Error Handling
### Exception Strategy
```php
// Custom exceptions
class UserNotFoundException extends Exception
{
public function __construct(int $id)
{
parent::__construct("User with ID {$id} not found", 404);
}
}
// Handler in Laravel
class ExceptionHandler extends IlluminateExceptionHandler
{
public function register(): void
{
$this->reportable(function (UserNotFoundException $e) {
Log::warning("User not found: " . $e->getId());
});
}
}
// Using Result/Either pattern
class UserService
{
public function findUser(int $id): User|UserNotFoundException
{
$user = User::find($id);
if (!$user) {
return new UserNotFoundException($id);
}
return $user;
}
}
```
---
## 8. Decision Checklist
Before implementing:
- [ ] **Chosen framework for this project?**
- [ ] **PSR standards applied (PSR-12)?**
- [ ] **PHP 8.x features used (attributes, readonly)?**
- [ ] **Validation strategy chosen?**
- [ ] **Testing with PHPUnit/Pest?**
- [ ] **Static analysis with PHPStan?**
- [ ] **DI container used properly?**
---
## ❌ Anti-Patterns to Avoid
### ❌ DON'T:
- Use old PHP 5/7 style (no attributes, manual getters)
- Skip PSR standards (causes conflicts in teams)
- Use $_GET/$_POST directly (use Request)
- Store passwords as plain text (use bcrypt)
- Write procedural code in classes
- Skip static analysis (PHPStan)
### ✅ DO:
- Use PHP 8 attributes (not Doctrine annotations)
- Use readonly properties
- Use constructor property promotion
- Use Laravel/Symfony best practices
- Add types everywhere (strict)
- Run tests on CI
- Use Pest for cleaner tests
---
> **Remember:** PHP has evolved significantly.
> Use PHP 8+ features and PSR standards.
> **Think in modern PHP.**
GitHubで見る