ΠŸΠΎΠ»Π΅Π·Π½Ρ‹Π΅ Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΈ с Eloquent?

На ΠΏΡ€ΠΎΡˆΠ»ΠΎΠΉ Π½Π΅Π΄Π΅Π»Π΅ я написал ΡΡ‚Π°Ρ‚ΡŒΡŽ ΠΎ бСсполСзности шаблона Π Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΉ для Eloquent сущностСй, ΠΎΠ΄Π½Π°ΠΊΠΎ ΠΏΠΎΠΎΠ±Π΅Ρ‰Π°Π» Ρ€Π°ΡΡΠΊΠ°Π·Π°Ρ‚ΡŒ ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ частично Π΅Π³ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ с пользой. Для этого ΠΏΠΎΠΏΡ€ΠΎΠ±ΡƒΡŽ ΠΏΡ€ΠΎΠ°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠ°ΠΊ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ этот шаблон Π² ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°Ρ…. Минимально Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹ΠΉ Π½Π°Π±ΠΎΡ€ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² для рСпозитория:

<?php
interface PostRepository
{
    public function getById($id): Post;
    public function save(Post $post);
    public function delete($id);
}

Однако, Π² Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹Ρ… ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°Ρ…, Ссли Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΈ Ρ‚Π°ΠΊΠΈ Π±Ρ‹Π»ΠΎ Ρ€Π΅ΡˆΠ΅Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ, Π² Π½ΠΈΡ… часто Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ΡΡ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ для Π²Ρ‹Π±ΠΎΡ€ΠΎΠΊ записСй:

<?php
interface PostRepository
{
    public function getById($id): Post;
    public function save(Post $post);
    public function delete($id);

    public function getLastPosts();
    public function getTopPosts();
    public function getUserPosts($userId);
}

Π­Ρ‚ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ ΠΌΠΎΠΆΠ½ΠΎ Π±Ρ‹Π»ΠΎ Π±Ρ‹ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· Eloquent scopes, Π½ΠΎ ΠΏΠ΅Ρ€Π΅Π³Ρ€ΡƒΠΆΠ°Ρ‚ΡŒ классы сущностСй обязанностями ΠΏΠΎ Π²Ρ‹Π±ΠΎΡ€ΠΊΠ΅ самих сСбя β€” Π½Π΅ самая Π»ΡƒΡ‡ΡˆΠ°Ρ затСя ΠΈ вынос этой обязанности Π² классы Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠ΅Π² выглядит Π»ΠΎΠ³ΠΈΡ‡Π½Ρ‹ΠΌ. Π’Π°ΠΊ Π»ΠΈ это? Π― ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎ Π²ΠΈΠ·ΡƒΠ°Π»ΡŒΠ½ΠΎ Ρ€Π°Π·Π΄Π΅Π»ΠΈΠ» этот интСрфСйс Π½Π° Π΄Π²Π΅ части. ΠŸΠ΅Ρ€Π²Π°Ρ Ρ‡Π°ΡΡ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² Π±ΡƒΠ΄Π΅Ρ‚ использована Π² опСрациях записи.

Бтандартная ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ записи это:

  • конструированиС Π½ΠΎΠ²ΠΎΠ³ΠΎ ΠΎΠ±ΡŒΠ΅ΠΊΡ‚Π° ΠΈ Π²Ρ‹Π·ΠΎΠ² PostRepository::save
  • PostRepository::getById, манипуляции с ΡΡƒΡ‰Π½ΠΎΡΡ‚ΡŒΡŽ ΠΈ Π²Ρ‹Π·ΠΎΠ² PostRepository::save
  • Π²Ρ‹Π·ΠΎΠ² PostRepository::delete

Π’ опСрациях записи Π½Π΅Ρ‚ использования ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² Π²Ρ‹Π±ΠΎΡ€ΠΊΠΈ. Π’ опСрациях чтСния ΠΆΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ get*. Если ΠΏΠΎΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ ΠΏΡ€ΠΎ Interface Segregation Principle (Π±ΡƒΠΊΠ²Π° I Π² SOLID), Ρ‚ΠΎ станСт понятно, Ρ‡Ρ‚ΠΎ наш интСрфСйс получился слишком большим ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‰ΠΈΠΌ ΠΊΠ°ΠΊ ΠΌΠΈΠ½ΠΈΠΌΡƒΠΌ Π΄Π²Π΅ Ρ€Π°Π·Π½Ρ‹Π΅ обязанности. ΠŸΠΎΡ€Π° Π΄Π΅Π»ΠΈΡ‚ΡŒ Π΅Π³ΠΎ Π½Π° Π΄Π²Π°. ΠœΠ΅Ρ‚ΠΎΠ΄ getById Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌ Π² ΠΎΠ±ΠΎΠΈΡ…, ΠΎΠ΄Π½Π°ΠΊΠΎ ΠΏΡ€ΠΈ услоТнСнии прилоТСния Π΅Π³ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Ρ€Π°Π·Π½Ρ‹ΠΌΠΈ. Π­Ρ‚ΠΎ ΠΌΡ‹ ΡƒΠ²ΠΈΠ΄ΠΈΠΌ Ρ‡ΡƒΡ‚ΡŒ ΠΏΠΎΠ·Π΄Π½Π΅Π΅. ΠŸΡ€ΠΎ Π±Π΅ΡΠΏΠΎΠ»Π΅Π·Π½ΠΎΡΡ‚ΡŒ write-части я писал Π² ΠΏΡ€ΠΎΡˆΠ»ΠΎΠΉ ΡΡ‚Π°Ρ‚ΡŒΠ΅, поэтому Π² этой я ΠΏΡ€ΠΎ Π½Π΅Π΅ просто Π·Π°Π±ΡƒΠ΄Ρƒ.

Read ΠΆΠ΅ Ρ‡Π°ΡΡ‚ΡŒ ΠΌΠ½Π΅ каТСтся Π½Π΅ Ρ‚Π°ΠΊΠΎΠΉ ΡƒΠΆ ΠΈ бСсполСзной, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π΄Π°ΠΆΠ΅ для Eloquent здСсь ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ нСсколько Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΉ. Как Π½Π°Π·Π²Π°Ρ‚ΡŒ класс? МоТно ReadPostRepository, Π½ΠΎ ΠΊ ΡˆΠ°Π±Π»ΠΎΠ½Ρƒ Repository ΠΎΠ½ ΡƒΠΆΠ΅ ΠΈΠΌΠ΅Π΅Ρ‚ ΠΌΠ°Π»ΠΎΠ΅ ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΠ΅. МоТно просто PostQueries:

<?php
interface PostQueries
{
    public function getById($id): Post;
    public function getLastPosts();
    public function getTopPosts();
    public function getUserPosts($userId);
}

Π•Π³ΠΎ рСализация с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Eloquent довольно проста:

<?php
final class EloquentPostQueries implements PostQueries
{
    public function getById($id): Post
    {
        return Post::findOrFail($id);
    }

    /**
    * @return Post[] | Collection
    */
    public function getLastPosts()
    {
        return Post::orderBy('created_at', 'desc')
            ->limit(/*some limit*/)
            ->get();
    }
    /**
    * @return Post[] | Collection
    */
    public function getTopPosts()
    {
        return Post::orderBy('rating', 'desc')
            ->limit(/*some limit*/)
            ->get();
    }

    /**
    * @param int $userId
    * @return Post[] | Collection
    */
    public function getUserPosts($userId)
    {
        return Post::whereUserId($userId)
            ->orderBy('created_at', 'desc')
            ->get();
    }
}

Π˜Π½Ρ‚Π΅Ρ€Ρ„Π΅ΠΉΡ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ связан с Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π² AppServiceProvider:

<?php
final class AppServiceProvider extends ServiceProvider 
{
    public function register()
    {
        $this->app->bind(PostQueries::class, 
            EloquentPostQueries::class);
    }
}

Π”Π°Π½Π½Ρ‹ΠΉ класс ΡƒΠΆΠ΅ ΠΏΠΎΠ»Π΅Π·Π΅Π½. Он Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅Ρ‚ свою ΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²Π΅Π½Π½ΠΎΡΡ‚ΡŒ, Ρ€Π°Π·Π³Ρ€ΡƒΠ·ΠΈΠ² этим Π»ΠΈΠ±ΠΎ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Ρ‹, Π»ΠΈΠ±ΠΎ класс сущности. Π’ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π΅ ΠΎΠ½ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использован Ρ‚Π°ΠΊ:

<?php
final class PostsController extends Controller
{
    public function lastPosts(PostQueries $postQueries)
    {
        return view('posts.last', [
            'posts' => $postQueries->getLastPosts(),
        ]);
    }
} 

ΠœΠ΅Ρ‚ΠΎΠ΄ PostsController::lastPosts просто просит сСбС ΠΊΠ°ΠΊΡƒΡŽ-Π½ΠΈΠ±ΡƒΠ΄ΡŒ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ PostsQueries ΠΈ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ с Π½Π΅ΠΉ. Π’ ΠΏΡ€ΠΎΠ²Π°ΠΉΠ΄Π΅Ρ€Π΅ ΠΌΡ‹ связали PostQueries с классом EloquentPostQueries ΠΈ Π² ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€ Π±ΡƒΠ΄Π΅Ρ‚ подставлСн этот класс.

Π”Π°Π²Π°ΠΉΡ‚Π΅ прСдставим, Ρ‡Ρ‚ΠΎ нашС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ стало ΠΎΡ‡Π΅Π½ΡŒ популярным. Высячи ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ Π² ΠΌΠΈΠ½ΡƒΡ‚Ρƒ ΠΎΡ‚ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‚ страницу с послСдними публикациями. НаиболСС популярныС ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ Ρ‚ΠΎΠΆΠ΅ Ρ‡ΠΈΡ‚Π°ΡŽΡ‚ΡΡ ΠΎΡ‡Π΅Π½ΡŒ часто. Π‘Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… Π½Π΅ ΠΎΡ‡Π΅Π½ΡŒ Ρ…ΠΎΡ€ΠΎΡˆΠΎ ΡΠΏΡ€Π°Π²Π»ΡΡŽΡ‚ΡΡ с Ρ‚Π°ΠΊΠΈΠΌΠΈ Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠ°ΠΌΠΈ, поэтому ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ стандартноС Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ β€” кСш. ΠšΡ€ΠΎΠΌΠ΅ Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ…, Π½Π΅ΠΊΠΈΠΉ слСпок Π΄Π°Π½Π½Ρ‹Ρ… хранится Π² Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠΌ ΠΊ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΌ опСрациям β€” memcached ΠΈΠ»ΠΈ redis.

Π›ΠΎΠ³ΠΈΠΊΠ° ΠΊΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ Π½Π΅ такая слоТная, Π½ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ Π΅Π΅ Π² EloquentPostQueries Π½Π΅ ΠΎΡ‡Π΅Π½ΡŒ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ (хотя Π±Ρ‹ ΠΈΠ·-Π·Π° Single Responsibility Principle). Намного Π±ΠΎΠ»Π΅Π΅ СстСствСнно ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ шаблон Π”Π΅ΠΊΠΎΡ€Π°Ρ‚ΠΎΡ€ ΠΈ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΊΠ°ΠΊ Π΄Π΅ΠΊΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π³Π»Π°Π²Π½ΠΎΠ³ΠΎ дСйствия:

<?php
use IlluminateContractsCacheRepository;

final class CachedPostQueries implements PostQueries
{
    const LASTS_DURATION = 10;

    /** @var PostQueries */
    private $base;

    /** @var Repository */
    private $cache;

    public function __construct(
        PostQueries $base, Repository $cache) 
    {
        $this->base = $base;
        $this->cache = $cache;
    }

    /**
    * @return Post[] | Collection
    */
    public function getLastPosts()
    {
        return $this->cache->remember('last_posts', 
            self::LASTS_DURATION, 
            function(){
                return $this->base->getLastPosts();
            });
    }

    // Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ практичСски Ρ‚Π°ΠΊΠΈΠ΅ ΠΆΠ΅
}

НС ΠΎΠ±Ρ€Π°Ρ‰Π°ΠΉΡ‚Π΅ внимания Π½Π° интСрфСйс Repository Π² конструкторС. По нСпонятной ΠΏΡ€ΠΈΡ‡ΠΈΠ½Π΅ Ρ‚Π°ΠΊ Ρ€Π΅ΡˆΠΈΠ»ΠΈ Π½Π°Π·Π²Π°Ρ‚ΡŒ интСрфСйс для ΠΊΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡ Π² Laravel.

Класс CachedPostQueries Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅. $this->cache->remember провСряСт Π½Π΅Ρ‚ Π»ΠΈ Π΄Π°Π½Π½ΠΎΠΉ записи Π² кСшС ΠΈ Ссли Π½Π΅Ρ‚, Ρ‚ΠΎ Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ callback ΠΈ записываСт Π² кСш Π²Π΅Ρ€Π½ΡƒΠ²ΡˆΠ΅Π΅ΡΡ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅. ΠžΡΡ‚Π°Π»ΠΎΡΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π²Π½Π΅Π΄Ρ€ΠΈΡ‚ΡŒ Π΄Π°Π½Π½Ρ‹ΠΉ класс Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅. Нам Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ всС классы, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π² ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ просят Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ интСрфСйса PostQueries стали ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ экзСмпляр класса CachedPostQueries. Однако сам CachedPostQueries Π² качСствС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π° Π² конструктор Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ класс EloquentPostQueries, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ½ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π±Π΅Π· «Π½Π°ΡΡ‚оящСй» Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ. МСняСм AppServiceProvider:

<?php
final class AppServiceProvider extends ServiceProvider 
{
    public function register()
    {
        $this->app->bind(PostQueries::class, 
            CachedPostQueries::class);

        $this->app->when(CachedPostQueries::class)
            ->needs(PostQueries::class)
            ->give(EloquentPostQueries::class);
    }
}

ВсС ΠΌΠΎΠΈ поТСлания довольно СстСствСнно ΠΎΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‚ΡΡ Π² ΠΏΡ€ΠΎΠ²Π°ΠΉΠ΄Π΅Ρ€Π΅. Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, ΠΌΡ‹ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π»ΠΈ ΠΊΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ для Π½Π°ΡˆΠΈΡ… запросов Ρ‚ΠΎΠ»ΡŒΠΊΠΎ написав ΠΎΠ΄ΠΈΠ½ класс ΠΈ помСняв ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡŽ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π°. Код ΠΎΡΡ‚Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ прилоТСния Π½Π΅ помСнялся.

РазумССтся, для ΠΏΠΎΠ»Π½ΠΎΡ†Π΅Π½Π½ΠΎΠΉ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΊΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΅Ρ‰Π΅ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΠ½Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΡŽ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ удалСнная ΡΡ‚Π°Ρ‚ΡŒΡ Π½Π΅ висСла Π½Π° сайтС Π΅Ρ‰Π΅ ΠΊΠ°ΠΊΠΎΠ΅-Ρ‚ΠΎ врСмя Π° ΡƒΠ΄Π°Π»ΠΈΠ»Π°ΡΡŒ сразу. Но это ΡƒΠΆΠ΅ ΠΌΠ΅Π»ΠΎΡ‡ΠΈ.

Π˜Ρ‚ΠΎΠ³: ΠΌΡ‹ использовали Π½Π΅ ΠΎΠ΄ΠΈΠ½, Π° Ρ†Π΅Π»Ρ‹Ρ… Π΄Π²Π° шаблона. Π¨Π°Π±Π»ΠΎΠ½ Command Query Responsibility Segregation (CQRS) ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅Ρ‚ ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ Ρ€Π°Π·Π΄Π΅Π»ΠΈΡ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ чтСния ΠΈ записи Π½Π° ΡƒΡ€ΠΎΠ²Π½Π΅ интСрфСйсов. Π― ΠΏΡ€ΠΈΡˆΠ΅Π» ΠΊ Π½Π΅ΠΌΡƒ Ρ‡Π΅Ρ€Π΅Π· Interface Segregation Principle, Ρ‡Ρ‚ΠΎ Π³ΠΎΠ²ΠΎΡ€ΠΈΡ‚ ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ я ΡƒΠΌΠ΅Π»ΠΎ ΠΌΠ°Π½ΠΈΠΏΡƒΠ»ΠΈΡ€ΡƒΡŽ шаблонами ΠΈ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠ°ΠΌΠΈ ΠΈ Π²Ρ‹Π²ΠΎΠΆΡƒ ΠΎΠ΄ΠΈΠ½ ΠΈΠ· Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ ΠΊΠ°ΠΊ Ρ‚Π΅ΠΎΡ€Π΅ΠΌΡƒ πŸ™‚ РазумССтся, Π½Π΅ ΠΊΠ°ΠΆΠ΄ΠΎΠΌΡƒ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Ρƒ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠ° такая абстракция Π½Π° Π²Ρ‹Π±ΠΎΡ€ΠΊΠΈ сущностСй, Π½ΠΎ я подСлюсь с Π²Π°ΠΌΠΈ фокусом.На Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠΌ этапС Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ прилоТСния ΠΌΠΎΠΆΠ½ΠΎ просто ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ класс PostQueries с ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠΉ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ Ρ‡Π΅Ρ€Π΅Π· Eloquent:

<?php
final class PostQueries
{
    public function getById($id): Post
    {
        return Post::findOrFail($id);
    }

    // Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹
}

Когда Π²ΠΎΠ·Π½ΠΈΠΊΠ½Π΅Ρ‚ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΡΡ‚ΡŒ Π² ΠΊΠ΅ΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠΈ, Π»Π΅Π³ΠΊΠΈΠΌ Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅ΠΌ ΠΌΠΎΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ интСрфСйс (ΠΈΠ»ΠΈ абстрактный класс) Π½Π° мСстС этого класса PostQueries, Π΅Π³ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ ΡΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π² класс EloquentPostQueries ΠΈ ΠΏΠ΅Ρ€Π΅ΠΉΡ‚ΠΈ ΠΊ схСмС, описанной мною Ρ€Π°Π½Π΅Π΅. ΠžΡΡ‚Π°Π»ΡŒΠ½ΠΎΠΉ ΠΊΠΎΠ΄ прилоТСния ΠΌΠ΅Π½ΡΡ‚ΡŒ Π½Π΅ Π½Π°Π΄ΠΎ.

ВсС эти фокусы с классами, интСрфСйсами, Dependency Injection ΠΈ CQRS ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ описаны Π² ΠΌΠΎΠ΅ΠΉ ΠΊΠ½ΠΈΠ³Π΅ «ΠΡ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° слоТных Π²Π΅Π± ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ». Π’Π°ΠΌ ΠΆΠ΅ Ρ€Π°Π·Π³Π°Π΄ΠΊΠ° Π·Π°Π³Π°Π΄ΠΊΠΈ ΠΏΠΎΡ‡Π΅ΠΌΡƒ всС ΠΌΠΎΠΈ классы Π² ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ… ΠΊ этой ΡΡ‚Π°Ρ‚ΡŒΠ΅ ΠΏΠΎΠΌΠ΅Ρ‡Π΅Π½Ρ‹ ΠΊΠ°ΠΊ final.

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com