Skip to content

💡 Scope Classes for Relation Attributes #493

@butschster

Description

@butschster

I have an idea!

Add support for scope classes in relation attributes to allow for more complex and reusable query conditions in entity relationships.

Problem

Currently, CycleORM allows defining relationships for an entity using attributes, but there's no built-in way to add additional conditions or complex queries using these attributes. This limitation makes it difficult to handle scenarios where more specific criteria are needed for relationship resolution, such as selecting the latest record or applying custom filtering.

Proposed Solution

Introduce a new scope parameter in relation attributes that accepts a class implementing a scope interface. This class would allow developers to define complex query conditions that can be reused across different relations.

Example Usage

#[Entity(table: 'posts')]
#[Scope(NotDeletedScope::class)]
#[Scope(PublishedScope::class)]
class Post
{
    #[Column(type: 'primary')]
    public int $id;
    
    #[Column(type: 'string')]
    public string $title;
    
    #[Column(type: 'string')]
    public string $status;  // draft, published, archived
    
    #[BelongsTo(target: User::class)]
    #[Scope(ActiveUserScope::class)]  // Don't show posts from deactivated authors
    public User $author;
    
    #[HasMany(target: Comment::class)]
    #[Scope(ApprovedCommentsScope::class)]
    #[Scope(NotSpamScope::class)]
    public array $comments;
    
    #[ManyToMany(target: Tag::class, through: PostTag::class)]
    #[Scope(ActiveTagScope::class)]  // Only active tags
    public array $tags;
    
    #[HasMany(target: Image::class)]
    // No scope - show all images (admin might need drafts)
    public array $images;
}

#[Entity(table: 'comments')]
#[Scope(NotDeletedScope::class)]
#[Scope(ApprovedCommentsScope::class)]
class Comment
{
    #[Column(type: 'primary')]
    public int $id;
    
    #[Column(type: 'text')]
    public string $content;
    
    #[Column(type: 'string')]
    public string $status;  // pending, approved, rejected
    
    #[Column(type: 'bool')]
    public bool $is_spam;
    
    #[BelongsTo(target: Post::class)]
    public Post $post;
    
    #[BelongsTo(target: User::class)]
    public User $author;
}

Scope Class Example

use Cycle\ORM\Select;

class LatestAddressScope implements Select\ScopeInterface
{  
    public function apply(Select\QueryBuilder $query): void
    { 
        $query->where('address', '!=', '')->orderBy('created_at', 'DESC'); 
    }
}

Benefits

  • Allows for more flexible and powerful relationship definitions
  • Improves code reusability by separating query logic into dedicated classes
  • Enhances readability and maintainability of entity definitions
  • Provides a consistent way to apply complex conditions across different types of relationships

Supported Relations

This feature would be applicable to the following relation types:

  • HasOne
  • HasMany
  • ManyToMany
  • Morphed

I believe this feature would greatly enhance the flexibility and power of CycleORM's relationship handling, making it easier for developers to implement complex data models and queries.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions