Extract Eloquent models scopes #226
              
                
                  
                  
                    Answered
                  
                  by
                    antonkomarev
                  
              
          
                  
                    
                      antonkomarev
                    
                  
                
                  asked this question in
                Choose solution
              
            -
| 
         This discussion created after the #224 Right now Eloquent model local scopes are located in Reactable & Reacterable traits and you cannot exclude them. To not add magical optional methods to models but let people easily use them we move them to the specific traits. There are 2 options: 
  | 
  
Beta Was this translation helpful? Give feedback.
      
      
          Answered by
          
            antonkomarev
          
      
      
        Jan 6, 2023 
      
    
    Replies: 2 comments 6 replies
-
        Solution 1: Magical local scope methods in models traitsPros
 Cons
 Usage$usersReactedByMe = User::query()->whereReactedBy($myUser)->get();Implementation<?php
declare(strict_types=1);
namespace App\Models;
use Cog\Laravel\Love\Reactable\Models\Traits\Reactable;
use Cog\Laravel\Love\Reactable\ReactableScopesTrait;
use Cog\Laravel\Love\Reacterable\Models\Traits\Reacterable;
use Cog\Laravel\Love\Reacterable\ReacterableScopesTrait;
use Illuminate\Database\Eloquent\Model;
final class User extends Model
{
    use Reactable;
    use ReactableScopesTrait;
    use Reacterable;
    use ReacterableScopesTrait;
}<?php
declare(strict_types=1);
namespace Cog\Laravel\Love\Reactable;
use Cog\Contracts\Love\Reacterable\Models\Reacterable as ReacterableInterface;
use Cog\Laravel\Love\ReactionType\Models\ReactionType;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
/**
 * @mixin Model
 */
trait ReactableScopesTrait
{
    public function scopeWhereReactedBy(
        Builder $query,
        ReacterableInterface $reacterable,
        ?string $reactionTypeName = null,
    ): Builder {
        return $query->whereHas(
            'loveReactant.reactions',
            function (Builder $reactionsQuery) use ($reacterable, $reactionTypeName) {
                $reactionsQuery->where('reacter_id', $reacterable->getLoveReacter()->getId());
                if ($reactionTypeName !== null) {
                    $reactionsQuery->where('reaction_type_id', ReactionType::fromName($reactionTypeName)->getId());
                }
            }
        );
    }
    public function scopeWhereNotReactedBy(
        Builder $query,
        ReacterableInterface $reacterable,
        ?string $reactionTypeName = null,
    ): Builder {
        return $query->whereDoesntHave(
            'loveReactant.reactions',
            function (Builder $reactionsQuery) use ($reacterable, $reactionTypeName) {
                $reactionsQuery->where('reacter_id', $reacterable->getLoveReacter()->getId());
                if ($reactionTypeName !== null) {
                    $reactionsQuery->where('reaction_type_id', ReactionType::fromName($reactionTypeName)->getId());
                }
            }
        );
    }
}<?php
declare(strict_types=1);
namespace Cog\Laravel\Love\Reacterable;
use Cog\Contracts\Love\Reactable\Models\Reactable as ReactableInterface;
use Cog\Laravel\Love\ReactionType\Models\ReactionType;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
/**
 * @mixin Model
 */
trait ReacterableScopesTrait
{
    public function scopeWhereReactedTo(
        Builder $query,
        ReactableInterface $reactable,
        ?string $reactionTypeName = null,
    ): Builder {
        return $query->whereHas(
            'loveReacter.reactions',
            function (Builder $reactionsQuery) use ($reactable, $reactionTypeName) {
                $reactionsQuery->where('reactant_id', $reactable->getLoveReactant()->getId());
                if ($reactionTypeName !== null) {
                    $reactionsQuery->where('reaction_type_id', ReactionType::fromName($reactionTypeName)->getId());
                }
            }
        );
    }
    public function scopeWhereNotReactedTo(
        Builder $query,
        ReactableInterface $reactable,
        ?string $reactionTypeName = null,
    ): Builder {
        return $query->whereDoesntHave(
            'loveReacter.reactions',
            function (Builder $reactionsQuery) use ($reactable, $reactionTypeName) {
                $reactionsQuery->where('reactant_id', $reactable->getLoveReactant()->getId());
                if ($reactionTypeName !== null) {
                    $reactionsQuery->where('reaction_type_id', ReactionType::fromName($reactionTypeName)->getId());
                }
            }
        );
    }
} | 
  
Beta Was this translation helpful? Give feedback.
                  
                    5 replies
                  
                
            -
        Solution 2: Custom Eloquent Builder methods traitsPros
 Cons
 Usage$usersReactedByMe = User::query()->whereReactedBy($myUser)->get();Implementation<?php
declare(strict_types=1);
namespace App\Models;
use Cog\Laravel\Love\Reactable\Models\Traits\Reactable;
use Cog\Laravel\Love\Reacterable\Models\Traits\Reacterable;
use Illuminate\Database\Eloquent\Model;
/**
 * @method static UserEloquentBuilder query()
 */
final class User extends Model
{
    use Reactable;
    use Reacterable;
    public function newEloquentBuilder($query)
    {
        return new UserEloquentBuilder($query);
    }
}<?php
declare(strict_types=1);
namespace App\Models;
use Cog\Laravel\Love\Reactable\ReactableScopesTrait;
use Cog\Laravel\Love\Reacterable\ReacterableScopesTrait;
use Illuminate\Database\Eloquent\Builder;
final class UserEloquentBuilder extends Builder
{
    use ReactableScopesTrait;
    use ReacterableScopesTrait;
    // Your other custom scopes
}<?php
declare(strict_types=1);
namespace Cog\Laravel\Love\Reactable;
use Cog\Contracts\Love\Reacterable\Models\Reacterable as ReacterableInterface;
use Cog\Laravel\Love\ReactionType\Models\ReactionType;
use Illuminate\Database\Eloquent\Builder;
/**
 * @mixin Builder
 */
trait ReactableEloquentBuilderTrait
{
    public function whereReactedBy(
        ReacterableInterface $reacterable,
        ?string $reactionTypeName = null,
    ): Builder {
        return $this->whereHas(
            'loveReactant.reactions',
            function (Builder $reactionsQuery) use ($reacterable, $reactionTypeName) {
                $reactionsQuery->where('reacter_id', $reacterable->getLoveReacter()->getId());
                if ($reactionTypeName !== null) {
                    $reactionsQuery->where('reaction_type_id', ReactionType::fromName($reactionTypeName)->getId());
                }
            }
        );
    }
    public function whereNotReactedBy(
        ReacterableInterface $reacterable,
        ?string $reactionTypeName = null,
    ): Builder {
        return $this->whereDoesntHave(
            'loveReactant.reactions',
            function (Builder $reactionsQuery) use ($reacterable, $reactionTypeName) {
                $reactionsQuery->where('reacter_id', $reacterable->getLoveReacter()->getId());
                if ($reactionTypeName !== null) {
                    $reactionsQuery->where('reaction_type_id', ReactionType::fromName($reactionTypeName)->getId());
                }
            }
        );
    }
}<?php
declare(strict_types=1);
namespace Cog\Laravel\Love\Reacterable;
use Cog\Contracts\Love\Reactable\Models\Reactable as ReactableInterface;
use Cog\Laravel\Love\ReactionType\Models\ReactionType;
use Illuminate\Database\Eloquent\Builder;
/**
 * @mixin Builder
 */
trait ReacterableEloquentBuilderTrait
{
    public function whereReactedTo(
        ReactableInterface $reactable,
        ?string $reactionTypeName = null,
    ): Builder {
        return $this->whereHas(
            'loveReacter.reactions',
            function (Builder $reactionsQuery) use ($reactable, $reactionTypeName) {
                $reactionsQuery->where('reactant_id', $reactable->getLoveReactant()->getId());
                if ($reactionTypeName !== null) {
                    $reactionsQuery->where('reaction_type_id', ReactionType::fromName($reactionTypeName)->getId());
                }
            }
        );
    }
    public function whereNotReactedTo(
        ReactableInterface $reactable,
        ?string $reactionTypeName = null,
    ): self {
        return $this->whereDoesntHave(
            'loveReacter.reactions',
            function (Builder $reactionsQuery) use ($reactable, $reactionTypeName) {
                $reactionsQuery->where('reactant_id', $reactable->getLoveReactant()->getId());
                if ($reactionTypeName !== null) {
                    $reactionsQuery->where('reaction_type_id', ReactionType::fromName($reactionTypeName)->getId());
                }
            }
        );
    }
} | 
  
Beta Was this translation helpful? Give feedback.
                  
                    1 reply
                  
                
            
      Answer selected by
        antonkomarev
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment
  
        
    
Solution 2: Custom Eloquent Builder methods traits
Pros
Cons
Usage
Implementation