ืžืื’ืจื™ื ืฉื™ืžื•ืฉื™ื™ื ืขื 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, ืื‘ืœ ื”ืขืžืกืช ื™ืชืจ ืฉืœ ืžื—ืœืงื•ืช ื™ืฉื•ื™ื•ืช ื‘ืื—ืจื™ื•ืช ืœื”ื‘ื™ื ืืช ืขืฆืžืŸ ื”ื™ื ืœื ื”ืจืขื™ื•ืŸ ื”ื˜ื•ื‘ ื‘ื™ื•ืชืจ, ื•ื”ืขื‘ืจืช ืื—ืจื™ื•ืช ื–ื• ืœืžื—ืœืงื•ืช ืžืื’ืจ ื ืจืื” ื”ื’ื™ื•ื ื™. ื”ืื ื–ื” ื›ืš? ื‘ืื•ืคืŸ ื•ื™ื–ื•ืืœื™ ื—ื™ืœืงืชื™ ืืช ื”ืžืžืฉืง ื”ื–ื” ืœืฉื ื™ ื—ืœืงื™ื. ื”ื—ืœืง ื”ืจืืฉื•ืŸ ืฉืœ ื”ืฉื™ื˜ื•ืช ื™ืฉืžืฉ ื‘ืคืขื•ืœื•ืช ื›ืชื™ื‘ื”.

ืคืขื•ืœืช ื”ื›ืชื™ื‘ื” ื”ืกื˜ื ื“ืจื˜ื™ืช ื”ื™ื:

  • ื‘ื ื™ื™ื” ืฉืœ ืื•ื‘ื™ื™ืงื˜ ื—ื“ืฉ ื•ืืชื’ืจ PostRepository::ืฉืžื•ืจ
  • PostRepository::getById, ืžื ื™ืคื•ืœืฆื™ื” ืฉืœ ื™ืฉื•ืช ื•ื–ื™ืžื•ืŸ PostRepository::ืฉืžื•ืจ
  • ื”ืืชื’ืจ PostRepository::delete

ืคืขื•ืœื•ืช ื›ืชื™ื‘ื” ืื™ื ืŸ ืžืฉืชืžืฉื•ืช ื‘ืฉื™ื˜ื•ืช ืื—ื–ื•ืจ. ื‘ืคืขื•ืœื•ืช ืงืจื™ืื” ืžืฉืชืžืฉื™ื ืจืง ื‘ืฉื™ื˜ื•ืช get*. ืื ืงืจืืช ืขืœ ืขืงืจื•ืŸ ื”ืคืจื“ืช ืžืžืฉืง (ืžึดื›ึฐืชึธื‘ I ะฒ ืžื•ืฆืง), ืื– ื™ืชื‘ืจืจ ืฉื”ืžืžืฉืง ืฉืœื ื• ื’ื“ื•ืœ ืžื“ื™ ื•ืžื‘ืฆืข ืœืคื—ื•ืช ืฉืชื™ ืชื—ื•ืžื™ ืื—ืจื™ื•ืช ืฉื•ื ื™ื. ื”ื’ื™ืข ื”ื–ืžืŸ ืœื—ืœืง ืื•ืชื• ืœืฉื ื™ื™ื. ืฉื™ื˜ื” getById ื”ื•ื ื”ื›ืจื—ื™ ื‘ืฉื ื™ื”ื, ืืš ื›ื›ืœ ืฉื”ื™ื™ืฉื•ื ื ืขืฉื” ืžื•ืจื›ื‘ ื™ื•ืชืจ, ื”ื”ื˜ืžืขื•ืช ืฉืœื• ื™ื”ื™ื• ืฉื•ื ื•ืช. ื ืจืื” ืืช ื–ื” ืงืฆืช ืžืื•ื—ืจ ื™ื•ืชืจ. ื›ืชื‘ืชื™ ืขืœ ื—ื•ืกืจ ื”ืชื•ืขืœืช ืฉืœ ื—ืœืง ื”ื›ืชื™ื‘ื” ื‘ืžืืžืจ ืงื•ื“ื, ืื– ื‘ืžืืžืจ ื”ื–ื” ืื ื™ ืคืฉื•ื˜ ืืฉื›ื— ืžื–ื”.

ื”ื—ืœืง ืฉืœ 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 ื•ื”ืžื—ืœืงื” ื”ื–ื• ืชื•ื—ืœืฃ ื‘ื‘ืงืจ.

ื‘ื•ืื• ื ื“ืžื™ื™ืŸ ืฉื”ืืคืœื™ืงืฆื™ื” ืฉืœื ื• ื”ืคื›ื” ืคื•ืคื•ืœืจื™ืช ืžืื•ื“. ืืœืคื™ ืžืฉืชืžืฉื™ื ื‘ื“ืงื” ืคื•ืชื—ื™ื ืืช ื”ื“ืฃ ืขื ื”ืคืจืกื•ืžื™ื ื”ืื—ืจื•ื ื™ื. ื’ื ื”ืคืจืกื•ืžื™ื ื”ืคื•ืคื•ืœืจื™ื™ื ื‘ื™ื•ืชืจ ื ืงืจืื™ื ืœืขืชื™ื ืงืจื•ื‘ื•ืช ืžืื•ื“. ืžืกื“ื™ ื ืชื•ื ื™ื ืœื ืžื˜ืคืœื™ื ื‘ืขื•ืžืกื™ื ื›ืืœื” ื‘ืฆื•ืจื” ื˜ื•ื‘ื”, ื•ืœื›ืŸ ื”ื ืžืฉืชืžืฉื™ื ื‘ืคืชืจื•ืŸ ืกื˜ื ื“ืจื˜ื™ - ืžื˜ืžื•ืŸ. ื‘ื ื•ืกืฃ ืœืžืกื“ ื”ื ืชื•ื ื™ื, ืชืžื•ื ืช ืžืฆื‘ ืžืกื•ื™ืžืช ืžืื•ื—ืกื ืช ื‘ืื—ืกื•ืŸ ื”ืžื•ืชืื ืœืคืขื•ืœื•ืช ืžืกื•ื™ืžื•ืช - ื ืฉืœื— ืœืžื—ืฉื‘ ืื• ื—ื•ื–ืจ.

ืœื•ื’ื™ืงื” ืฉืœ ืžื˜ืžื•ืŸ ื”ื™ื ื‘ื“ืจืš ื›ืœืœ ืœื ื›ืœ ื›ืš ืžืกื•ื‘ื›ืช, ืื‘ืœ ื”ื˜ืžืขืชื” ื‘- EloquentPostQueries ื”ื™ื ืœื ืžืื•ื“ ื ื›ื•ื ื” (ื•ืœื• ืจืง ื‘ื’ืœืœ ืขืงืจื•ืŸ ืื—ืจื™ื•ืช ื™ื—ื™ื“ื”). ื–ื” ื”ืจื‘ื” ื™ื•ืชืจ ื˜ื‘ืขื™ ืœื”ืฉืชืžืฉ ื‘ืชื‘ื ื™ืช ืžึฐืขึทืฆึตื‘ ื•ืœื™ื™ืฉื ืžื˜ืžื•ืŸ ื›ืงื™ืฉื•ื˜ ืœืคืขื•ืœื” ื”ืขื™ืงืจื™ืช:

<?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->ื–ื›ื•ืจ ื‘ื•ื“ืง ืื ื”ืขืจืš ื”ื–ื” ื ืžืฆื ื‘ืžื˜ืžื•ืŸ ื•ืื ืœื, ืื– ืงื•ืจื ืœื”ืชืงืฉืจื•ืช ื—ื•ื–ืจืช ื•ื›ื•ืชื‘ ืืช ื”ืขืจืš ื”ืžื•ื—ื–ืจ ืœืžื˜ืžื•ืŸ. ื›ืœ ืžื” ืฉื ื•ืชืจ ื”ื•ื ืœื™ื™ืฉื ืืช ื”ืžื—ืœืงื” ื”ื–ื• ื‘ืืคืœื™ืงืฆื™ื”. ืื ื—ื ื• ืฆืจื™ื›ื™ื ืืช ื›ืœ ื”ืžื—ืœืงื•ืช ื‘ืืคืœื™ืงืฆื™ื” ื›ื“ื™ ืœื‘ืงืฉ ื™ื™ืฉื•ื ืฉืœ ื”ืžืžืฉืง 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);
    }
}

ื›ืœ ื”ืžืฉืืœื•ืช ืฉืœื™ ืžืชื•ืืจื•ืช ื‘ืื•ืคืŸ ื˜ื‘ืขื™ ื‘ืกืคืง. ืœืคื™ื›ืš, ื”ื˜ืžืขื ื• ืžื˜ืžื•ืŸ ืขื‘ื•ืจ ื”ื‘ืงืฉื•ืช ืฉืœื ื• ืจืง ืขืœ ื™ื“ื™ ื›ืชื™ื‘ืช ืžื—ืœืงื” ืื—ืช ื•ืฉื™ื ื•ื™ ืชืฆื•ืจืช ื”ืงื•ื ื˜ื™ื™ื ืจ. ืฉืืจ ืงื•ื“ ื”ืืคืœื™ืงืฆื™ื” ืœื ื”ืฉืชื ื”.

ื›ืžื•ื‘ืŸ, ื›ื“ื™ ืœื™ื™ืฉื ืžืœื ืฉืœ ืžื˜ืžื•ืŸ, ื™ืฉ ืฆื•ืจืš ื’ื ืœื™ื™ืฉื ื‘ื™ื˜ื•ืœ ืชื•ืงืฃ ื›ื“ื™ ืฉื”ืžืืžืจ ืฉื ืžื—ืง ืœื ื™ืชืงืข ื‘ืืชืจ ื‘ืžืฉืš ื–ืžืŸ ืžื”, ืืœื ื™ื™ืžื—ืง ืžื™ื“. ืื‘ืœ ืืœื• ื“ื‘ืจื™ื ืžื™ื ื•ืจื™ื™ื.

ื‘ืฉื•ืจื” ื”ืชื—ืชื•ื ื”: ืœื ื”ืฉืชืžืฉื ื• ื‘ืื—ืช, ืืœื ื‘ืฉืชื™ ืชื‘ื ื™ื•ืช. ืœึดื˜ืขื•ึนื ื”ืคืจื“ืช ืื—ืจื™ื•ืช ืฉืื™ืœืชืช ืคืงื•ื“ื” (CQRS) ืžืฆื™ืข ืœื”ืคืจื™ื“ ืœื—ืœื•ื˜ื™ืŸ ื‘ื™ืŸ ืคืขื•ืœื•ืช ืงืจื™ืื” ื•ื›ืชื™ื‘ื” ื‘ืจืžืช ื”ืžืžืฉืง. ื”ื’ืขืชื™ ืืœื™ื• ื“ืจืš ืขืงืจื•ืŸ ื”ืคืจื“ืช ืžืžืฉืง, ืžื” ืฉืžืจืžื– ืฉืืขืฉื” ืžื ื™ืคื•ืœืฆื™ื•ืช ืžื™ื•ืžื ื•ืช ืฉืœ ื“ืคื•ืกื™ื ื•ืขืงืจื•ื ื•ืช ื•ืืคื™ืง ืื—ื“ ืžื”ืฉื ื™ ื›ืžืฉืคื˜ :) ื›ืžื•ื‘ืŸ ืฉืœื ื›ืœ ืคืจื•ื™ืงื˜ ืฆืจื™ืš ื”ืคืฉื˜ื” ื›ื–ื• ืœื‘ื—ื™ืจืช ื™ืฉื•ื™ื•ืช, ืื‘ืœ ืื ื™ ืื—ืœื•ืง ืื™ืชืš ืืช ื”ื˜ืจื™ืง. ื‘ืฉืœื‘ ื”ืจืืฉื•ื ื™ ืฉืœ ื”ื™ื™ืฉื•ื ืคื™ืชื•ื—, ืืชื” ื™ื›ื•ืœ ืคืฉื•ื˜ ืœื™ืฆื•ืจ ื›ื™ืชื” PostQueries ืขื ื”ื™ื™ืฉื•ื ื”ืจื’ื™ืœ ื‘ืืžืฆืขื•ืช Eloquent:

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

    // ะดั€ัƒะณะธะต ะผะตั‚ะพะดั‹
}

ื›ืืฉืจ ืžืชืขื•ืจืจ ื”ืฆื•ืจืš ื‘ืžื˜ืžื•ืŸ, ื‘ืขื–ืจืช ืžื”ืœืš ืคืฉื•ื˜ ื ื™ืชืŸ ืœื™ืฆื•ืจ ืžืžืฉืง (ืื• ืžื—ืœืงื” ืื‘ืกื˜ืจืงื˜ื™ืช) ื‘ืžืงื•ื ื”ืžื—ืœืงื” ื”ื–ื• PostQueries, ื”ืขืชืง ืืช ื”ื™ื™ืฉื•ื ืฉืœื• ืœื›ื™ืชื” EloquentPostQueries ื•ืขื‘ื•ืจ ืœืชื›ื ื™ืช ืฉืชื™ืืจืชื™ ืงื•ื“ื. ืื™ืŸ ืฆื•ืจืš ืœืฉื ื•ืช ืืช ืฉืืจ ืงื•ื“ ื”ืืคืœื™ืงืฆื™ื”.

ื›ืœ ื”ื˜ืจื™ืงื™ื ื”ืืœื” ืขื ืฉื™ืขื•ืจื™ื, ืžืžืฉืงื™ื, ื”ื–ืจืงืช ืชืœื•ืช ะธ CQRS ืžืชื•ืืจ ื‘ืคื™ืจื•ื˜ ื‘ ื”ืกืคืจ ืฉืœื™ "ืืจื›ื™ื˜ืงื˜ื•ืจื” ืฉืœ ื™ื™ืฉื•ืžื™ ืื™ื ื˜ืจื ื˜ ืžื•ืจื›ื‘ื™ื". ื™ืฉ ื’ื ืคืชืจื•ืŸ ืœื—ื™ื“ื” ืžื“ื•ืข ื›ืœ ื”ื›ื™ืชื•ืช ืฉืœื™ ื‘ื“ื•ื’ืžืื•ืช ืœืžืืžืจ ื–ื” ืžืกื•ืžื ื•ืช ื›ืกื•ืคื™ื•ืช.

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”