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

Cycle Bridge Laravel Package

spiral/cycle-bridge

Bridge package integrating Cycle ORM v2 with Spiral Framework 3+. Provides ORM configuration and runtime wiring for Spiral apps using PDO database drivers on PHP 8.1+.

View on GitHub
Deep Wiki
Context7

Getting Started

First Steps

  1. Installation Add the package via Composer:

    composer require spiral/cycle-bridge
    

    Register the bridge in your config/app.php under providers:

    Spiral\CycleBridge\CycleBridgeProvider::class,
    
  2. Basic Setup Configure Cycle ORM in config/cycle.php (if not already present):

    return [
        'dsn' => env('DATABASE_DSN', 'mysql://user:pass@localhost/db'),
        'orm' => [
            'default' => [
                'entityManager' => \Cycle\ORM\EntityManager::class,
                'connection' => \Cycle\Database\Connection\Connection::class,
            ],
        ],
    ];
    
  3. First Use Case: Querying Entities with Relations Define entities with relations and leverage the new Relations Bulk Loader binding:

    use Spiral\CycleBridge\CycleBridge;
    use Cycle\Annotated\Annotation\Column;
    use Cycle\Annotated\Annotation\Entity;
    use Cycle\Annotated\Annotation\Relation;
    
    #[Entity]
    class User
    {
        #[Column(type: 'primary')]
        public int $id;
    
        #[Column(type: 'string')]
        public string $name;
    
        #[Relation(target: Post::class, type: 'one-to-many')]
        public array $posts;
    }
    
    #[Entity]
    class Post
    {
        #[Column(type: 'primary')]
        public int $id;
    
        #[Column(type: 'string')]
        public string $title;
    }
    
    // In a Spiral controller:
    public function index(CycleBridge $cycle)
    {
        // Fetch users with eagerly loaded posts using Relations Bulk Loader
        $users = $cycle->getEntityManager()
            ->getRepository(User::class)
            ->findAll()
            ->with('posts') // Bulk loads relations
            ->fetchAll();
    
        return $users;
    }
    

Implementation Patterns

Common Workflows

  1. Dependency Injection Inject CycleBridge into Spiral handlers (controllers, commands) to access the ORM:

    public function __construct(private CycleBridge $cycle) {}
    
  2. Repository Pattern with Relations Use Cycle’s repositories for CRUD operations, now optimized for bulk relation loading:

    // Fetch a user with all related posts in a single query
    $user = $this->cycle->getRepository(User::class)
        ->find(1)
        ->with('posts')
        ->fetch();
    
  3. Transactions Wrap operations in transactions for atomicity:

    $this->cycle->getEntityManager()->transactional(function () {
        $user = new User();
        $user->name = 'John';
        $this->cycle->getRepository(User::class)->persist($user);
    });
    
  4. Query Building with Relations Leverage Cycle’s query builder for complex queries, including relation filtering:

    $query = $this->cycle->getEntityManager()
        ->getRepository(User::class)
        ->createQueryBuilder()
        ->where('name', '=', 'John')
        ->with('posts') // Bulk loads posts for all matching users
        ->fetchAll();
    
  5. Event Handling Use Cycle’s lifecycle events (e.g., prePersist, postLoad) via Spiral’s event system:

    $this->cycle->getEntityManager()->addListener(
        new YourEventListener()
    );
    

Integration Tips

  • Migrations: Use Cycle’s migration system alongside Laravel’s (if hybrid):
    vendor:publish --provider="Cycle\Migrations\MigrationsProvider"
    
  • Testing: Mock CycleBridge in unit tests, including relation loading:
    $this->bean->provide(CycleBridge::class, function () {
        $mock = $this->mock(CycleBridge::class);
        $mock->getEntityManager()
             ->getRepository(User::class)
             ->find(1)
             ->with('posts')
             ->willReturn($this->mock(User::class));
        return $mock;
    });
    
  • Caching: Configure Cycle’s cache layer (e.g., Redis) in config/cycle.php for performance, especially with bulk-loaded relations.

Gotchas and Tips

Pitfalls

  1. Connection Configuration

    • Ensure config/cycle.php matches your database DSN. Test with:
      php artisan cycle:migrate
      
    • Debugging: Use cycle:debug command to inspect connections.
  2. Entity Mapping

    • Cycle requires explicit annotations (#[Entity], #[Column], #[Relation]). Forgetting them causes Cycle\ORM\Exception\MappingException.
    • Fix: Run cycle:generate to auto-generate mappings (if using cycle-orm/annotations).
  3. Transaction Isolation

    • Spiral’s default transaction isolation may conflict with Cycle’s. Explicitly set in config/cycle.php:
      'orm' => [
          'default' => [
              'transaction' => [
                  'isolation' => \PDO::TRANSACTION_READ_COMMITTED,
              ],
          ],
      ],
      
  4. Relations Bulk Loader

    • N+1 Queries: Ensure you use .with('relation') to trigger bulk loading. Without it, relations are loaded lazily.
    • Performance: Bulk loading adds overhead. Use sparingly for deep or wide relations.
  5. Schema Changes

    • Cycle does not auto-migrate. Always run migrations manually:
      php artisan cycle:migrate
      

Debugging Tips

  • Enable Logging: Add to config/cycle.php:
    'debug' => env('APP_DEBUG', false),
    
  • Query Logging: Use Cycle\Database\Connection\Logger to log SQL, including bulk-loaded relations:
    $this->cycle->getConnection()->addLogger(new \Cycle\Database\Connection\Logger\FileLogger('/tmp/cycle.log'));
    
  • Common Errors:
    • PDOException: Check DSN format (e.g., mysql://user:pass@host/db).
    • InvalidArgumentException: Validate entity annotations with cycle:validate.
    • Bulk Loader Issues: Ensure relations are properly annotated with #[Relation].

Extension Points

  1. Custom Repositories with Relations Extend Cycle’s repositories for domain-specific logic, including optimized relation loading:

    class UserRepository extends \Cycle\ORM\Select\Repository
    {
        public function findByNameWithPosts(string $name): ?User
        {
            return $this->getConnection()
                ->select()
                ->from(User::class)
                ->where('name', '=', $name)
                ->with('posts')
                ->fetchOne();
        }
    }
    
  2. Middleware for ORM and Relations Use Spiral’s middleware to wrap requests in transactions and bulk-load relations:

    public function handle(HandlerInterface $handler): ResponseInterface
    {
        return $this->cycle->getEntityManager()->transactional(
            fn() => $handler->handle($request, $response)
        )->with('posts'); // Bulk load relations for all entities
    }
    
  3. Hybrid with Eloquent If using both Cycle and Laravel’s Eloquent, alias the bridge:

    $this->bean->alias(CycleBridge::class, 'db.cycle');
    

    Then inject via:

    public function __construct(private \DB\CycleBridge $cycle) {}
    
  4. Dynamic Relation Loading Dynamically load relations based on runtime conditions:

    $query = $this->cycle->getEntityManager()
        ->getRepository(User::class)
        ->createQueryBuilder();
    
    if ($includePosts) {
        $query->with('posts');
    }
    
    return $query->fetchAll();
    
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