Weave 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

Annotated Laravel Package

cycle/annotated

Define Cycle ORM entity schemas using PHP attributes instead of annotations or config. Map columns, primary keys, and HasOne, HasMany, and BelongsTo relations directly in your entity classes.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require cycle/annotated
    

    Ensure cycle/orm is also installed (required dependency).

  2. Basic Entity Definition Create a PHP class with #[Entity] and #[Column] attributes:

    use Cycle\Annotated\Annotation\{Entity, Column};
    
    #[Entity]
    class User {
        #[Column(type: 'primary')]
        public int $id;
    
        #[Column(type: 'string(255)')]
        public string $name;
    }
    
  3. Register the Schema Compiler In your Laravel service provider (e.g., AppServiceProvider):

    use Cycle\Annotated\Processor;
    use Cycle\ORM\Factory;
    
    public function boot(): void {
        $factory = new Factory();
        $factory->getPool()->registerCompiler(new Processor());
    }
    
  4. First Use Case Define a repository and fetch entities:

    use Cycle\ORM\Select;
    
    $users = $factory->getRepository(User::class)
        ->select(Select::all())
        ->fetchAll();
    

Where to Look First


Implementation Patterns

1. Entity Design Patterns

Active Record vs. Data Mapper

  • Data Mapper Preferred: Decouple entities from persistence logic. Use repositories for CRUD operations.
    // Repository pattern (recommended)
    $user = $factory->getRepository(User::class)->create([
        'name' => 'John Doe',
    ]);
    

Type Safety with Enums

  • Leverage PHP 8.1+ enums for constrained columns:
    enum UserStatus {
        case Active;
        case Inactive;
    }
    
    #[Column(type: 'enum', values: [UserStatus::Active, UserStatus::Inactive])]
    public UserStatus $status;
    

2. Relation Workflows

Lazy Loading

  • Use #[HasOne]/#[BelongsTo] with fetchMode: 'lazy' to defer loading:
    #[HasOne(target: Address::class, fetchMode: 'lazy')]
    public ?Address $address;
    

Polymorphic Relations

  • Morphed Relations for dynamic targets:
    interface Imageable {
        public function getImageableId(): int;
    }
    
    #[BelongsToMorphed(target: Imageable::class)]
    public Imageable $imageable;
    

Embedded Entities

  • Group related fields into reusable components:
    #[Embeddable]
    class ContactInfo {
        #[Column(type: 'string(100)')]
        public string $email;
    
        #[Column(type: 'string(20)')]
        public string $phone;
    }
    
    #[Entity]
    class User {
        #[Embedded(target: ContactInfo::class)]
        public ContactInfo $contact;
    }
    

3. Performance Patterns

Generated Fields

  • Auto-compute columns (e.g., timestamps, hashes):
    #[Column(type: 'timestamp', generated: 'insert')]
    public ?string $createdAt;
    

Indexing

  • Optimize queries with #[Index]:
    #[Column(type: 'string(255)')]
    #[Index]
    public string $email;
    

Batch Operations

  • Use Cycle\ORM\Select for bulk queries:
    $factory->getRepository(User::class)
        ->select(Select::all())
        ->where('status', '=', 'active')
        ->update(['balance' => fn($balance) => $balance + 100]);
    

4. Integration with Laravel

Service Container Binding

  • Bind the ORM factory to Laravel’s container:
    $this->app->singleton(Factory::class, fn($app) => new Factory());
    

Eloquent-like Facades

  • Create a facade for convenience:
    // app/Facades/CycleORM.php
    namespace App\Facades;
    
    use Illuminate\Support\Facades\Facade;
    
    class CycleORM extends Facade {
        protected static function getFacadeAccessor() {
            return \Cycle\ORM\Factory::class;
        }
    }
    
    Usage:
    $users = CycleORM::getRepository(User::class)->fetchAll();
    

Migrations

  • Generate migrations from annotated entities using cycle/orm:
    vendor/bin/cycle-make:migration User
    

Gotchas and Tips

1. Common Pitfalls

Attribute Parsing Issues

  • Problem: Attributes ignored or misconfigured.
    • Fix: Ensure PHP 8.1+ and AttributeReader is the default reader (set in cycle/orm config).
    • Debug: Use #[Attribute\Target("CLASS")] or #[Attribute\Target("PROPERTY")] explicitly if needed.

Circular Dependencies in Relations

  • Problem: #[HasMany]/#[BelongsTo] loops cause infinite recursion.
    • Fix: Use fetchMode: 'lazy' or break cycles with #[RefersTo]:
      #[RefersTo(target: Comment::class)]
      public ?Comment $lastComment;
      

Inheritance Quirks

  • Single Table Inheritance (STI):
    • Ensure #[DiscriminatorColumn] is defined on the base class.
    • Child classes must extend the base and use #[InheritanceSingleTable].
  • Joined Table Inheritance (JTI):
    • Parent class must include the outerKey column (e.g., fooId).
    • Child classes use #[InheritanceJoinedTable(outerKey: 'fooId')].

Foreign Key Conflicts

  • Problem: Duplicate foreign keys or mismatched innerKey/outerKey.
    • Fix: Explicitly define #[ForeignKey] with innerKey/outerKey:
      #[ForeignKey(
          target: User::class,
          innerKey: 'user_id',
          outerKey: 'id',
          action: 'CASCADE'
      )]
      public int $userId;
      

2. Debugging Tips

Schema Validation

  • Validate schema before runtime:
    $factory->getSchemaCompiler()->compile();
    // Throws exceptions for invalid configurations.
    

Logging SQL

  • Enable ORM logging in config/cycle.php:
    'debug' => env('APP_DEBUG', false),
    'logger' => [
        'class' => \Monolog\Logger::class,
        'level' => \Monolog\Logger::DEBUG,
    ],
    

Attribute Introspection

  • Dump entity metadata for debugging:
    $metadata = $factory->getSchemaCompiler()->getMetadata(User::class);
    dd($metadata->getTable(), $metadata->getColumns());
    

3. Configuration Quirks

Custom Column Types

  • Extend supported types via cycle/orm's TypeSystem:
    use Cycle\ORM\Type\TypeSystem;
    
    $typeSystem = new TypeSystem();
    $typeSystem->register('ulid', new ULIDType());
    

Naming Strategies

  • Override default naming (e.g., snake_case to camelCase):
    'naming' => [
        'strategy' => \Cycle\ORM\Naming\SnakeCaseStrategy::class,
    ],
    

Embeddable Typecasting

  • Customize typecasting for embedded entities:
    #[Embeddable(typecast: [
        'email' => 'string',
        'age' => 'int',
    ])]
    class ContactInfo { ... }
    

4. Extension Points

Custom Attributes

  • Create reusable attributes by extending Cycle\Annotated\Annotation\Annotation:
    #[Attribute(Attribute::TARGET_PROPERTY)]
    class SoftDelete extends Annotation {
        public function __construct(
            public string $column = 'deleted_at',
            public string $default = '0000-00-00 00:00:00'
        ) {}
    }
    

Event Listeners

  • Hook into lifecycle events (e.g., beforeInsert):
    use Cycle\ORM\Event\EventInterface;
    
    $factory->getEventManager()->addListener(
        EventInterface::BEFORE_INSERT,
        fn($event) => $event->getEntity()->setCreatedAt(now())
    );
    

Custom Processors

  • Extend Cycle\Annotated\Processor for custom logic:
    class CustomProcessor extends Processor {
    
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.
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast