Depoyên kêrhatî yên bi Eloquent?

Hefteya borî min nivîsî gotara li ser bêkêrbûna şablonê Repository ji bo hebûnên Eloquent, lebê, wî soz da ku ji min re bêje ka ez çawa bi qismî wê ji bo berjewendiya xwe bikar bînim. Ji bo vê yekê, ez ê hewl bidim ku analîz bikim ka ev şablon bi gelemperî di projeyan de çawa tê bikar anîn. Rêbazên herî kêm ên pêdivî ji bo depoyek:

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

Lêbelê, di projeyên rastîn de, heke biryar hat dayîn ku depoyan bikar bînin, rêbazên ji bo wergirtina tomaran bi gelemperî li wan têne zêdekirin:

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

Van rêbazan dikaribû bi navgînên Eloquent ve were bicîh kirin, lê barkirina çînên sazûmanan bi berpirsiyariya girtina xwe ne ramana çêtirîn e, û veguheztina vê berpirsiyariyê berbi dersên depoyê mentiqî xuya dike. Ma wisa ye? Min bi taybetî bi dîtbarî vê navberê li du beşan dabeş kir. Beşa yekem a rêbazan dê di operasyonên nivîsandinê de were bikar anîn.

Operasyona nivîsandina standard ev e:

  • avakirina objeyek nû û dijwar PostRepository:: hilanînê
  • PostRepository::getById, manîpulasyon û gazîkirina saziyan PostRepository:: hilanînê
  • derekek PostRepository:: jêbirin

Operasyonên nivîsandinê rêbazên hilanînê bikar nayînin. Di operasyonên xwendinê de, tenê rêbazên bidestxistin * têne bikar anîn. Ger hûn li ser bixwînin Prensîba Veqetandina Navberê (name I в LISERXWE), wê hingê dê diyar bibe ku pêwendiya me pir mezin e û bi kêmî ve du berpirsiyariyên cûda pêk tîne. Wext e ku meriv wê li ser du dabeş bike. Awa getById di herduyan de jî pêwîst e, lê her ku serîlêdan tevlihevtir dibe, dê pêkanînên wê cûda bibin. Em ê vê hinekî paşê bibînin. Min di gotarek berê de li ser bêkêrbûna beşa nivîsandinê nivîsî, ji ber vê yekê di vê yekê de ez ê tenê wê ji bîr bikim.

Beşa Read ji min re ne ewqas bêkêr xuya dike, ji ber ku ji bo Eloquent jî dibe ku li vir çend pêkanîn hebin. Navê polê çi bikin? Kanîn ReadPostRepository, lê ji bo şablonê Daxistin eleqeya wî jixwe hindik e. Hûn dikarin tenê PostQueries:

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

Pêkanîna wê bi Eloquent re pir hêsan e:

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

Pêdivî ye ku navber bi pêkanînê re têkildar be, mînakî di AppServiceProvider:

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

Ev dersa jixwe kêrhatî ye. Ew berpirsiyariya xwe bi xilaskirina kontrolkeran an jî çîna sazûman dizane. Di kontrolkerek de ew dikare bi vî rengî were bikar anîn:

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

Rêbaz PostsController :: posts dawî tenê hinek pêkanînê dipirse PostsQueries û pê re dixebite. Di pêşkêşkara ku me ve girêdayî ye PostQueries bi polê EloquentPostQueries û ev çîn dê di kontrolkerê de were veguheztin.

Ka em bifikirin ku serîlêdana me pir populer bûye. Bi hezaran bikarhêner her deqê rûpelê bi weşanên herî dawî vedikin. Weşanên herî populer jî pir caran têne xwendin. Database barên weha pir baş nagirin, ji ber vê yekê ew çareseriyek standard bikar tînin - cache. Ji bilî databasê, hin wêneyek daneyê di hilanînê de ku ji bo hin operasyonan xweşbînkirî tê hilanîn - bîranîn an redis.

Mantiqa caching bi gelemperî ne ew çend tevlihev e, lê pêkanîna wê di EloquentPostQueries de ne pir rast e (heke tenê ji ber ku Prensîba Berpirsyariya Yekane). Bikaranîna şablonê pir xwezayîtir e Decorator û caching-ê wekî xemilandina çalakiya sereke bicîh bikin:

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

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

Navberê paşguh bikin Daxistin di avaker de. Ji ber hin sedemên nenas, wan biryar da ku bi vî rengî navbeynkariyê ji bo cachkirina Laravel bi nav bikin.

Çar CachedPostQueries tenê cachkirinê pêk tîne. $this->cache-> bi bîr bîne kontrol dike ka ev têketin di cacheyê de ye yan na, wê hingê bangî paşvegerê dike û nirxa vegerî li kaşê dinivîse. Tiştê ku dimîne ev e ku meriv vê polê di serîlêdanê de bicîh bike. Em hewce ne ku hemî çînên ku di serîlêdanê de daxwaza pêkanîna navbeynkariyê bikin PostQueries dest bi wergirtina mînakek polê kir CachedPostQueries. Lêbelê, ew bi xwe CachedPostQueries çêker divê çînek wekî parametre werbigire EloquentPostQueriesji ber ku ew bêyî pêkanîna "rast" nikare bixebite. Em diguherin 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);
    }
}

Hemî daxwazên min bi xwezayî di pêşkêşker de têne vegotin. Bi vî rengî, me caching ji bo daxwazên xwe tenê bi nivîsandina yek polê û guheztina veavakirina konteynerê pêk anî. Koda serîlêdanê ya mayî nehatiye guhertin.

Bê guman, ji bo bi tevahî bicîhkirina cachkirinê, pêdivî ye ku meriv betalkirinê jî bicîh bîne da ku gotara jêbirin ji bo demekê li ser malperê nemîne, lê tavilê were jêbirin. Lê ev tiştên piçûk in.

Rêza jêrîn: me ne yek, lê du şablon bikar anîn. Mînak Veqetandina Berpirsiyariya Fermandariyê (CQRS) pêşniyar dike ku bi tevahî karûbarên xwendin û nivîsandinê di asta navberê de ji hev veqetîne. Ez bi wî awayî hatim cem wî Prensîba Veqetandina Navberê, ku pêşnîyar dike ku ez bi hostayî qalib û prensîban manîpule bikim û yekî ji yê din wek teorem derxim :) Helbet her projeyek ji bo bijartina sazîyan ne hewceyî abstrakasyonek wusa ye, lê ez ê hîleyê bi we re parve bikim. Di qonaxa destpêkê ya serîlêdanê de pêşkeftinê, hûn dikarin bi tenê çînek biafirînin PostQueries bi pêkanîna asayî bi rêya Eloquent:

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

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

Gava ku hewcedariya cachkirinê çêbibe, bi tevgerek hêsan hûn dikarin li şûna vê polê navgînek (an çîna razber) biafirînin. PostQueries, pêkanîna wê li polê kopî bikin EloquentPostQueries û herin pilana ku min berê diyar kir. Koda serîlêdanê ya mayî ne hewce ye ku were guheztin.

Hemî van hîleyên bi çîn, navber, Injection Dependency и CQRS bi berfirehî têne vegotin pirtûka min "Architecture of Complex Applications Web". Di heman demê de çareyek heye ku çima hemî dersên min di mînakên vê gotarê de wekî dawî têne nîşankirin.

Source: www.habr.com

Add a comment