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

Annotated Laravel Package

cycle/annotated

Define Cycle ORM entities and schema using PHP 8 attributes. Annotate columns, primary keys, enums, decimals, and relationships like HasOne, HasMany, and BelongsTo, then let Cycle build the mapping from your code.

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.
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
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