Repositories mangpaat sareng Eloquent?

Minggu kamari kuring nyerat artikel ngeunaan gunana tina template Repository pikeun éntitas Eloquent, kumaha oge, anjeunna jangji baris ngabejaan ka kuring kumaha sabagean ngagunakeun eta pikeun kaunggulan na. Jang ngalampahkeun ieu, kuring bakal nyobian nganalisis kumaha template ieu biasana dianggo dina proyék. Set metodeu minimum anu diperyogikeun pikeun gudang:

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

Nanging, dina proyék-proyék nyata, upami diputuskeun pikeun ngagunakeun repositori, metode pikeun nyandak rékaman sering ditambihan ka aranjeunna:

<?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);
}

Metoda ieu bisa dilaksanakeun ngaliwatan scopes Eloquent, tapi overloading kelas éntitas jeung tanggung jawab dipulut sorangan sanes gagasan pangalusna, sarta mindahkeun tanggung jawab ieu ka kelas gudang sigana logis. Naha kitu? Kuring husus visually dibagi panganteur ieu dua bagian. Bagian kahiji tina métode bakal dipaké dina operasi nulis.

Operasi nulis standar nyaéta:

  • pangwangunan objék anyar jeung tantangan PostRepository:: simpen
  • PostRepository::getById, manipulasi éntitas jeung manggil PostRepository:: simpen
  • tangtangan PostRepository :: ngahapus

Operasi nulis teu make métode dipulut. Dina operasi baca, ngan ukur metode get * anu dianggo. Lamun maca ngeunaan Prinsip Segregation Interface (serat I в SIDID), mangka bakal jadi jelas yén panganteur urang badag teuing jeung ngalakukeun sahenteuna dua tanggung jawab béda. Geus waktuna dibagi dua. Métode getById diperlukeun dina duanana, tapi sakumaha aplikasi nu jadi leuwih kompleks, palaksanaan na bakal béda. Urang bakal ningali ieu saeutik engké. Kuring nulis ngeunaan gunana tina bagian nulis dina artikel saméméhna, jadi dina hiji ieu kuring ngan bakal poho ngeunaan eta.

Bagian Baca sigana mah teu jadi gunana, saprak malah keur Eloquent meureun aya sababaraha palaksanaan dieu. Naon ngaran kelas? Tiasa ReadPostRepository, tapi kana citakan Repository anjeunna geus boga saeutik relevansi. Anjeun ngan bisa PostQueries:

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

Ngalaksanakeunana sareng Eloquent cukup saderhana:

<?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();
    }
}

Antarbeungeut kedah dipatalikeun sareng palaksanaan, contona dina AppServiceProvider:

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

kelas ieu geus mangpaat. Anjeunna sadar tanggung jawabna ku ngaleungitkeun pangendali atanapi kelas éntitas. Dina controller bisa dipaké saperti kieu:

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

Metode PostsController :: lastPosts ngan menta sababaraha palaksanaan PostsQueries sarta gawéna kalayan eta. Dina panyadia kami numbu PostQueries kalawan kelas EloquentPostQueries jeung kelas ieu bakal diganti kana controller nu.

Hayu urang ngabayangkeun yén aplikasi urang geus jadi pohara populér. Rébuan pamaké per menit muka kaca jeung publikasi panganyarna. Publikasi anu pang populerna ogé sering dibaca. Basis data henteu nanganan beban sapertos kitu, janten aranjeunna nganggo solusi standar - cache. Salian database, snapshot data tangtu disimpen dina gudang dioptimalkeun pikeun operasi tangtu - memcached atawa redis.

Logika cache biasana henteu rumit, tapi ngalaksanakeunana dina EloquentPostQueries henteu leres pisan (upami ngan kusabab Prinsip Tanggung Jawab Tunggal). Éta langkung alami ngagunakeun citakan Dekorator sareng nerapkeun cache salaku hiasan pikeun aksi utama:

<?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();
            });
    }

    // другие методы практически такие же
}

Teu malire panganteur Repository dina constructor nu. Kanggo sababaraha alesan anu teu dipikanyaho, aranjeunna mutuskeun pikeun namikeun antarmuka pikeun cache di Laravel ku cara ieu.

kelas CachedPostQueries implements cache wungkul. $this->cache->inget pariksa naha entri ieu aya dina cache sarta lamun henteu, lajeng nelepon callback tur nyerat nilai balik ka cache nu. Sadaya anu tetep nyaéta pikeun nerapkeun kelas ieu kana aplikasi. Urang kudu sagala kelas nu di aplikasi pikeun menta hiji palaksanaan panganteur PostQueries mimiti nampa hiji conto tina kelas CachedPostQueries. Sanajan kitu, manéhna sorangan CachedPostQueries constructor kudu narima kelas salaku parameter a EloquentPostQueriessaprak teu tiasa dianggo tanpa palaksanaan "real". Urang robah 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);
    }
}

Sadayana kahayang kuring dijelaskeun sacara alami dina panyadia. Ku kituna, urang ngalaksanakeun cache pikeun requests urang ngan ku nulis hiji kelas jeung ngarobah konfigurasi wadahna. Sesa kode aplikasi teu robah.

Tangtosna, pikeun ngalaksanakeun caching sapinuhna, anjeun ogé kedah ngalaksanakeun invalidation supados tulisan anu dihapus henteu ngagantung dina situs pikeun sababaraha waktos, tapi langsung dihapus. Tapi ieu hal minor.

Garis handap: kami henteu nganggo hiji, tapi dua témplat. Sampel Command Query Responsibility Segregation (CQRS) proposes pikeun sakabéhna misahkeun operasi maca jeung nulis dina tingkat panganteur. Kuring datang ka anjeunna ngaliwatan Prinsip Segregation Interface, nu nunjukkeun yen kuring skillfully ngamanipulasi pola jeung prinsip sarta diturunkeun hiji ti séjén salaku teorema a :) Tangtu, teu unggal proyék perlu abstraksi misalna pikeun milih entitas, tapi kuring baris babagi trik sareng anjeun Dina tahap awal aplikasi. ngembangkeun, anjeun ngan saukur bisa nyieun kelas PostQueries kalayan palaksanaan biasa via Eloquent:

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

    // другие методы
}

Nalika peryogi caching timbul, kalayan gerakan saderhana anjeun tiasa nyiptakeun antarbeungeut (atanapi kelas abstrak) di tempat kelas ieu. PostQueries, nyalin implementasina ka kelas EloquentPostQueries tur buka skéma I ditétélakeun saméméhna. Sesa kode aplikasi teu perlu dirobah.

Sadaya trik ieu sareng kelas, antarmuka, Suntikan kagumantungan и CQRS dijelaskeun sacara rinci dina buku abdi "Arsitektur Aplikasi Wéb Kompleks". Aya ogé solusi pikeun teka-teki naha sadaya kelas kuring dina conto pikeun tulisan ieu ditandaan salaku final.

sumber: www.habr.com

Tambahkeun komentar