Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Core Laravel Package

atk4/core

Agile Core is a set of reusable PHP traits for building object-oriented frameworks. Provides containers (parent/child), hooks with priorities, automatic init, dynamic methods, factory by class string, app scope injection, and improved exceptions.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require atk4/core
    

    Add to composer.json if using Laravel:

    "require": {
        "atk4/core": "^6.0"
    }
    
  2. First Use Case: Use HookTrait to add event-driven behavior to a Laravel service or model:

    use Atk4\Core\HookTrait;
    
    class UserService
    {
        use HookTrait;
    
        public function __construct()
        {
            $this->addHook('beforeSave', function($user) {
                // Pre-save logic
            });
        }
    }
    
  3. Key Entry Points:

    • Documentation (focus on HookTrait, ContainerTrait, FactoryTrait).
    • src/Atk4/Core/ for trait implementations.
    • Laravel integration: Use traits in Service Providers, Models, or Controllers.

Implementation Patterns

1. Hook-Driven Workflows

  • Pattern: Centralize cross-cutting logic (e.g., logging, validation) via hooks.
class OrderProcessor
{
    use HookTrait;

    public function process(Order $order)
    {
        $this->callHook('validate', [$order]);
        $this->callHook('preSave', [$order]);
        $order->save();
    }
}
  • Laravel Integration: Attach hooks in boot() methods of service providers:
public function boot()
{
    $this->app->make(OrderProcessor::class)
        ->addHook('validate', function($order) {
            if ($order->isInvalid()) {
                throw new \Exception("Invalid order");
            }
        });
}

2. Dependency Injection with DiContainerTrait

  • Pattern: Replace Laravel’s container for lightweight DI in services:
class UserRepository
{
    use DiContainerTrait;

    public function __construct()
    {
        $this->setDefault('db', \DB::connection('mysql'));
    }
}
  • Tip: Use assertInstanceOf() to enforce type safety:
$this->assertInstanceOf(\Illuminate\Database\Connection::class, $this->get('db'));

3. Dynamic Method Generation

  • Pattern: Add runtime methods to models/services:
class User extends \Illuminate\Database\Eloquent\Model
{
    use DynamicMethodTrait;

    public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);
        $this->addDynamicMethod('getFullName', function() {
            return "{$this->first_name} {$this->last_name}";
        });
    }
}
  • Use Case: Avoid bloating models with trivial getters/setters.

4. Container Hierarchies

  • Pattern: Model parent-child relationships (e.g., OrderOrderItem):
class Order
{
    use ContainerTrait;

    protected $items = [];

    public function addItem(OrderItem $item)
    {
        $this->addChild($item);
    }
}
  • Laravel Tip: Use addChild() in afterCreate() hooks:
public static function afterCreate(Order $order)
{
    $order->addChild(new OrderItem(['product_id' => 1]));
}

5. Factory Pattern for Instantiation

  • Pattern: Decouple object creation from usage:
class UserFactory
{
    use FactoryTrait;

    protected $seeds = [
        'admin' => ['role' => 'admin'],
        'guest' => ['role' => 'guest']
    ];
}
  • Laravel Integration: Bind factories to the container:
$this->app->singleton(UserFactory::class, function() {
    return new UserFactory();
});

6. Exception Handling

  • Pattern: Replace Laravel’s exceptions with Atk4\Core\Exception for richer debugging:
try {
    $user->save();
} catch (\Atk4\Core\Exception $e) {
    report($e->getTraceAsString()); // HTML-friendly trace
}
  • Tip: Use Exception::render() in Laravel’s App\Exceptions\Handler:
public function render($request, Throwable $exception)
{
    if ($exception instanceof \Atk4\Core\Exception) {
        return response($exception->render(), 500);
    }
    return parent::render($request, $exception);
}

Gotchas and Tips

Pitfalls

  1. Hook Priorities Collisions:

    • Hooks with the same priority execute in arbitrary order. Use unique priorities (e.g., 100, 200).
    • Fix: Explicitly set priorities:
    $this->addHook('beforeSave', $callback, 100);
    
  2. Circular Dependencies in Containers:

    • ContainerTrait throws CircularDependencyException if parent-child cycles exist.
    • Fix: Validate hierarchy early:
    $order->assertNoCircularDependencies();
    
  3. Dynamic Methods Overwriting:

    • Dynamically added methods can shadow existing ones. Use hasMethod() to check:
    if (!$this->hasMethod('getFullName')) {
        $this->addDynamicMethod('getFullName', ...);
    }
    
  4. Factory Seed Conflicts:

    • Merging seeds with duplicate keys throws an exception (since v4.0.0).
    • Fix: Use unique keys or merge manually:
    $factory->mergeSeeds(['user' => ['id' => 1]], true); // Force overwrite
    
  5. PHP 8.2+ Strict Typing:

    • Some traits (e.g., NameTrait) enforce strict types for properties like $name.
    • Fix: Annotate properties:
    #[Assert\Type('string')]
    protected string $name;
    
  6. Exception Rendering in CLI:

    • HTML-based exception rendering may fail in CLI. Use Exception::render('text'):
    echo $e->render('text');
    

Debugging Tips

  1. Hook Debugging:

    • Enable hook logging:
    $this->setHookDebug(true);
    
    • Check active hooks:
    print_r($this->getHooks('beforeSave'));
    
  2. Container Inspection:

    • List all children:
    print_r($this->getChildren());
    
    • Check parent:
    var_dump($this->getParent());
    
  3. Dynamic Method Introspection:

    • List all dynamic methods:
    print_r($this->getDynamicMethods());
    
  4. Factory Seed Inspection:

    • Dump seeds:
    print_r($this->getSeeds());
    

Extension Points

  1. Custom Exception Renderers:

    • Extend ExceptionRenderer to add Laravel-specific formatting:
    class LaravelExceptionRenderer extends \Atk4\Core\ExceptionRenderer
    {
        public function render(Throwable $e, string $format = 'html')
        {
            if ($format === 'laravel') {
                return view('errors.atk4', ['exception' => $e]);
            }
            return parent::render($e, $format);
        }
    }
    
  2. Hook Middleware:

    • Create a Laravel middleware to wrap hook calls:
    class HookMiddleware
    {
        public function handle($request, Closure $next)
        {
            $response = $next($request);
            $this->app->make(OrderProcessor::class)->callHook('postRequest');
            return $response;
        }
    }
    
  3. Trait Composition:

    • Combine traits for complex behaviors (e.g., HookTrait + DiContainerTrait):
    class EventDispatcher
    {
        use HookTrait, DiContainerTrait;
    
        public function __construct()
        {
            $this->setDefault('logger', \Log::getMonolog());
        }
    }
    
  4. Laravel Service Provider Integration:

    • Register traits as Laravel bindings:
    public function register()
    {
        $this->app->bind('hookable', function() {
            return new class {
                use HookTrait;
            };
        });
    }
    

Performance Considerations

  1. Hook Overhead:

    • Hooks add minimal overhead (~1-2ms per call). Benchmark critical paths.
    • Optimization: Use callHookSilent() to bypass priority sorting for non-critical hooks.
  2. Dynamic Methods:

    • Avoid adding thousands of dynamic methods to a single object (memory overhead).
    • Alternative: Use Laravel’s __call() or HandleDynamicProperties.

3

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky