Eloquent සමඟ ප්‍රයෝජනවත් ගබඩා?

ගිය සතියේ මම ලිව්වා Eloquent entities සඳහා Repository සැකිල්ලේ නිෂ්ඵලභාවය පිළිබඳ ලිපිය, කෙසේ වෙතත්, එය ඔහුගේ වාසියට අර්ධ වශයෙන් භාවිතා කරන්නේ කෙසේදැයි මට කියන්නට ඔහු පොරොන්දු විය. මෙය සිදු කිරීම සඳහා, මෙම අච්චුව සාමාන්යයෙන් ව්යාපෘතිවල භාවිතා කරන ආකාරය විශ්ලේෂණය කිරීමට මම උත්සාහ කරමි. ගබඩාවක් සඳහා අවශ්‍ය අවම ක්‍රම කට්ටලය:

<?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::සුරකින්න
  • PostRepository::getById, ආයතන හැසිරවීම සහ කැඳවීම PostRepository::සුරකින්න
  • අභියෝගයක් PostRepository::මකන්න

ලිවීමේ මෙහෙයුම් ලබා ගැනීමේ ක්‍රම භාවිතා නොකරයි. කියවීමේ මෙහෙයුම් වලදී, get* ක්‍රම පමණක් භාවිතා වේ. ගැන කියෙව්වොත් අතුරුමුහුණත වෙන් කිරීමේ මූලධර්මය (ලිපිය I в ඝණ), එවිට අපගේ අතුරු මුහුණත ඉතා විශාල වන අතර අවම වශයෙන් විවිධ වගකීම් දෙකක් ඉටු කරන බව පැහැදිලි වනු ඇත. එය දෙකකින් බෙදීමට කාලයයි. ක්රමය getById දෙකම අවශ්ය වේ, නමුත් යෙදුම වඩාත් සංකීර්ණ වන විට, එහි ක්රියාත්මක කිරීම් වෙනස් වනු ඇත. අපි මෙය ටිකක් පසුව බලමු. මම කලින් ලිපියක ලියන කොටසේ නිෂ්ඵලකම ගැන ලිව්වා, ඒ නිසා මේකෙන් මම ඒක සරලව අමතක කරන්නම්.

Eloquent සඳහා පවා මෙහි ක්‍රියාත්මක කිරීම් කිහිපයක් තිබිය හැකි බැවින්, කියවීමේ කොටස එතරම් නිෂ්ඵල නොවන බව මට පෙනේ. පන්තිය නම් කළ යුත්තේ කුමක්ද? පුළුවන් ReadPostRepository, නමුත් සැකිල්ලට ගබඩාව ඔහුට දැනටමත් කුඩා අදාළත්වයක් ඇත. ඔබට නිකම්ම පුළුවන් 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();
    }
}

අතුරු මුහුණත ක්රියාත්මක කිරීම සමඟ සම්බන්ධ විය යුතුය, උදාහරණයක් ලෙස in 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 හි ක්‍රියාත්මක කිරීම එතරම් නිවැරදි නොවේ (එසේ නම් පමණක් නම් තනි වගකීම් මූලධර්මය) අච්චුවක් භාවිතා කිරීම වඩාත් ස්වාභාවිකය සැරසිලි කරු සහ ප්‍රධාන ක්‍රියාව සඳහා සැරසිලි ලෙස හැඹිලිගත කිරීම ක්‍රියාත්මක කරන්න:

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

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

අතුරු මුහුණත නොසලකා හරින්න ගබඩාව ඉදිකිරීම්කරු තුළ. කිසියම් නොදන්නා හේතුවක් නිසා, ඔවුන් 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

අදහස් එක් කරන්න