Skip to content
Skillv1.0.0

php-expert

Expert-level PHP development with PHP 8+, Laravel, Composer, and modern best practices. Use when the user mentions Laravel, Composer, Symfony, PHPUnit, or PSR standards, or when the task involves PHP

by personamanagmentlayer(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from personamanagmentlayer/pcl (stdlib/languages/php-expert/SKILL.md). Install upstream with npx skills add personamanagmentlayer/pcl --skill php-expert. Copyright stays with the author.

PHP Expert

Expert guidance for modern PHP development including PHP 8+ features, Laravel framework, Composer dependency management, and PHP best practices.

Core Concepts

PHP 8+ Features

  • Union types and mixed type
  • Named arguments
  • Attributes (annotations)
  • Constructor property promotion
  • Match expressions
  • Nullsafe operator
  • JIT compiler
  • Fibers (PHP 8.1+)
  • Readonly properties and classes

Object-Oriented PHP

  • Classes and objects
  • Interfaces and abstract classes
  • Traits
  • Namespaces
  • Autoloading (PSR-4)
  • Type declarations
  • Visibility modifiers

Modern PHP

  • Strict types
  • Return type declarations
  • Property type declarations
  • Enums (PHP 8.1+)
  • First-class callable syntax

Testing with PHPUnit

Feature Tests

<?php

namespace Tests\Feature;

use App\Models\User;
use App\Models\Post;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class PostControllerTest extends TestCase
{
    use RefreshDatabase;

    public function test_can_list_posts(): void
    {
        Post::factory()->count(3)->create(['published' => true]);
        Post::factory()->create(['published' => false]);

        $response = $this->getJson('/api/posts');

        $response->assertOk()
            ->assertJsonCount(3, 'data');
    }

    public function test_can_create_post_when_authenticated(): void
    {
        $user = User::factory()->create();

        $response = $this->actingAs($user, 'api')
            ->postJson('/api/posts', [
                'title' => 'Test Post',
                'content' => 'Test content with enough characters to pass validation.',
            ]);

        $response->assertCreated()
            ->assertJsonPath('data.title', 'Test Post');

        $this->assertDatabaseHas('posts', [
            'title' => 'Test Post',
            'user_id' => $user->id,
        ]);
    }

    public function test_cannot_create_post_when_not_authenticated(): void
    {
        $response = $this->postJson('/api/posts', [
            'title' => 'Test Post',
            'content' => 'Test content',
        ]);

        $response->assertUnauthorized();
    }

    public function test_validates_post_creation(): void
    {
        $user = User::factory()->create();

        $response = $this->actingAs($user, 'api')
            ->postJson('/api/posts', [
                'title' => '', // Invalid
                'content' => 'Short', // Too short
            ]);

        $response->assertUnprocessable()
            ->assertJsonValidationErrors(['title', 'content']);
    }

    public function test_can_update_own_post(): void
    {
        $user = User::factory()->create();
        $post = Post::factory()->create(['user_id' => $user->id]);

        $response = $this->actingAs($user, 'api')
            ->putJson("/api/posts/{$post->id}", [
                'title' => 'Updated Title',
                'content' => 'Updated content with enough characters.',
            ]);

        $response->assertOk();
        $this->assertDatabaseHas('posts', [
            'id' => $post->id,
            'title' => 'Updated Title',
        ]);
    }

    public function test_cannot_update_other_user_post(): void
    {
        $user = User::factory()->create();
        $otherUser = User::factory()->create();
        $post = Post::factory()->create(['user_id' => $otherUser->id]);

        $response = $this->actingAs($user, 'api')
            ->putJson("/api/posts/{$post->id}", [
                'title' => 'Updated Title',
            ]);

        $response->assertForbidden();
    }
}

Unit Tests

<?php

namespace Tests\Unit;

use App\Models\User;
use App\Models\Post;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class UserTest extends TestCase
{
    use RefreshDatabase;

    public function test_user_has_posts(): void
    {
        $user = User::factory()->create();
        $posts = Post::factory()->count(3)->create(['user_id' => $user->id]);

        $this->assertCount(3, $user->posts);
        $this->assertTrue($user->posts->contains($posts->first()));
    }

    public function test_is_admin_returns_true_for_admin_users(): void
    {
        $admin = User::factory()->create(['is_admin' => true]);
        $user = User::factory()->create(['is_admin' => false]);

        $this->assertTrue($admin->isAdmin());
        $this->assertFalse($user->isAdmin());
    }
}

Factories

<?php

namespace Database\Factories;

use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;

class PostFactory extends Factory
{
    public function definition(): array
    {
        return [
            'user_id' => User::factory(),
            'title' => fake()->sentence(),
            'slug' => fake()->slug(),
            'content' => fake()->paragraphs(5, true),
            'excerpt' => fake()->paragraph(),
            'published' => false,
            'published_at' => null,
            'tags' => fake()->words(3),
        ];
    }

    public function published(): static
    {
        return $this->state(fn (array $attributes) => [
            'published' => true,
            'published_at' => now(),
        ]);
    }

    public function withUser(User $user): static
    {
        return $this->state(fn (array $attributes) => [
            'user_id' => $user->id,
        ]);
    }
}

Best Practices

Type Safety

<?php
declare(strict_types=1);

// Always use strict types
// Use type declarations for parameters and return types
// Use property types where possible

Dependency Injection

<?php

// Use constructor injection
class UserService
{
    public function __construct(
        private UserRepository $repository,
        private EventDispatcher $dispatcher,
    ) {}

    public function createUser(array $data): User
    {
        $user = $this->repository->create($data);
        $this->dispatcher->dispatch(new UserCreated($user));
        return $user;
    }
}

PSR Standards

  • PSR-1: Basic Coding Standard
  • PSR-4: Autoloading Standard
  • PSR-12: Extended Coding Style
  • PSR-7: HTTP Message Interface

Anti-Patterns to Avoid

Not using strict types: Always declare(strict_types=1) ❌ Fat controllers: Extract logic to services ❌ N+1 queries: Use eager loading ❌ No type declarations: Use types everywhere ❌ Ignoring PSR standards: Follow PSR-4, PSR-12 ❌ Direct DB queries in controllers: Use repositories ❌ Missing validation: Always validate input ❌ No tests: Write tests for critical code

Reference Documentation

Detailed material lives alongside this skill and is read on demand:

  • Laravel Framework — Models, Controllers, Form Requests, API Resources, Eloquent Queries, Migrations, Jobs (Queues), Events and Listeners
  • Modern PHP 8+ Syntax — Constructor Property Promotion, Named Arguments, Union Types and Mixed, Match Expression, Nullsafe Operator, Attributes (Annotations), Enums (PHP 8.1+), Readonly Properties and Classes

Resources

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/personamanagmentlayer-pcl-php-expert/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

personamanagmentlayer-pcl-php-expert.ocm.jsonjson
{
  "ocm": "1",
  "id": "personamanagmentlayer-pcl-php-expert",
  "kind": "skill",
  "name": "php-expert",
  "description": "Expert-level PHP development with PHP 8+, Laravel, Composer, and modern best practices. Use when the user mentions Laravel, Composer, Symfony, PHPUnit, or PSR standards, or when the task involves PHP 8+ Features, Object-Oriented PHP, Modern PHP, or Constructor Property Promotion.",
  "publisher": "personamanagmentlayer",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "math"
    ],
    "tags": [
      "skill-md",
      "php",
      "laravel",
      "composer",
      "symfony",
      "phpunit",
      "psr",
      "skills-sh"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Expert-level PHP development with PHP 8+, Laravel, Composer, and modern best practices. Use when the user mentions Laravel, Composer, Symfony, PHPUnit, or PSR standards, or when the task involves PHP 8+ Features, Object-Oriented PHP, Modern PHP, or Constructor Property Promotion."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "skills.sh",
      "repository": "https://github.com/personamanagmentlayer/pcl",
      "path": "stdlib/languages/php-expert/SKILL.md",
      "ref": "HEAD",
      "url": "https://github.com/personamanagmentlayer/pcl/blob/HEAD/stdlib/languages/php-expert/SKILL.md",
      "key": "personamanagmentlayer/pcl/stdlib/languages/php-expert/SKILL.md"
    },
    "allowed_tools": [
      "Read",
      "Write",
      "Edit",
      "Bash(php:*, composer:*, artisan:*)"
    ]
  },
  "instructions": "# PHP Expert\n\nExpert guidance for modern PHP development including PHP 8+ features, Laravel framework, Composer dependency management, and PHP best practices.\n\n## Core Concepts\n\n### PHP 8+ Features\n\n- Union types and mixed type\n- Named arguments\n- Attributes (annotations)\n- Constructor property promotion\n- Match expressions\n- Nullsafe operator\n- JIT compiler\n- Fibers (PHP 8.1+)\n- Readonly properties and classes\n\n### Object-Oriented PHP\n\n- Classes and objects\n- Interfaces and abstract classes\n- Traits\n- Namespaces\n- Autoloading (PSR-4)\n- Type declarations\n- Visibility modifiers\n\n### Modern PHP\n",
  "cost": {
    "context_tokens": 1825
  }
}

Fetch it by URL: GET /api/v1/registry/personamanagmentlayer-pcl-php-expert/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.