<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>نوشته های زهیر مظاهری</title><link>https://virgool.ir/feed/@zoheirmaz.zm</link><description></description><language>fa</language><pubDate>2026-11-11 14:19:38</pubDate><image><url>https://files.virgool.ir/upload/users/140058/avatar/6oiqkZ.jpg</url><title>زهیر مظاهری</title><link>https://virgool.ir/@zoheirmaz.zm</link></image><item><title>قفل‌های پایگاه داده در لاراول</title><link>https://virgool.ir/@zoheirmaz.zm/پست-جدید-hmj3e5iuyeas</link><description>مدیریت قفل‌های پایگاه داده در لاراول: lockForUpdate و sharedLockگاهی اوقات برای مدیریت داده‌های حساس و جلوگیری از مشکلاتی مانند تناقض‌های احتمالی، نیاز به استفاده از قفل‌های پایگاه داده دارید. در این مقاله به بررسی دو قابلیت مهم لاراول، lockForUpdate و sharedLock، می‌پردازیم که به شما کمک می‌کنند تا این چالش‌ها را به شکلی بهینه مدیریت کنید.مشکل: به‌روزرسانی‌های ناسازگار در پایگاه دادهتصور کنید یک سیستم بانکی داریم که مشتریان می‌توانند به‌راحتی بین حساب‌ها تراکنش انجام دهند. بدون قفل‌های مناسب، ممکن است مشکلاتی مانند دوبار خرج کردن (Double Spending) رخ دهد.برای مثال، اگر چندین درخواست همزمان ارسال شوند و هر دو تراکنش وضعیت موجودی یکسانی را بخوانند، ممکن است سیستم بیش از موجودی واقعی، پول جابه‌جا کند.پیاده‌سازی اولیه: بدون قفلمدل کاربر و تابع انتقال وجه بین حساب‌ها به‌صورت زیر تعریف شده است:namespace App\Models;&#xA;&#xA;use Illuminate\Database\Eloquent\Model;&#xA;&#xA;class User extends Model&#xA;{&#xA;    protected $fillable = [&#xA;        &#39;name&#39;,&#xA;        &#39;balance&#39;,&#xA;    ];&#xA;    protected $casts = [&#xA;        &#39;balance&#39; =&gt; &#39;float&#39;,&#xA;    ];&#xA;}&#xA;&#xA;&#xA;class Bank&#xA;{&#xA;    public static function sendMoney(User $from, User $to, float $amount)&#xA;    {&#xA;        if ($from-&gt;balance &lt; $amount) {&#xA;            return false;&#xA;        }&#xA;&#xA;        $from-&gt;update([&#39;balance&#39; =&gt; $from-&gt;balance - $amount]);&#xA;        $to-&gt;update([&#39;balance&#39; =&gt; $to-&gt;balance + $amount]);&#xA;        return true;&#xA;    }&#xA;}در ابتدا، ارسال پول بین حساب‌ها به‌سادگی انجام می‌شود:$alice = User::find(1); // &#39;balance&#39; =&gt; 100&#xA;$bob = User::find(2); // &#39;balance&#39; =&gt; 0&#xA;&#xA;Bank::sendMoney($alice, $bob, 100); // trueاین کد ممکن است در شرایط عادی به‌درستی عمل کند، اما در مواردی که درخواست‌های همزمان دریافت می‌شود، ممکن است مشکلاتی ایجاد شود.راه‌حل اول: تراکنش‌های اتمی (Atomic Transactions)برای اطمینان از اجرای کامل یا بازگشت تمام مراحل یک عملیات، باید از تراکنش‌ها استفاده کنید:use Illuminate\Support\Facades\DB;&#xA;class Bank&#xA;{&#xA;    public static function sendMoney(User $from, User $to, float $amount)&#xA;    {&#xA;        if ($from-&gt;balance &lt; $amount) {&#xA;            return false;&#xA;        }&#xA;        return DB::transaction(function () use ($from, $to, $amount) {&#xA;            $from-&gt;update([&#39;balance&#39; =&gt; $from-&gt;balance - $amount]);&#xA;            $to-&gt;update([&#39;balance&#39; =&gt; $to-&gt;balance + $amount]);&#xA;            return true;&#xA;        });&#xA;    }&#xA;}در صورت بروز هرگونه خطا، تراکنش به‌طور کامل بازگشت داده می‌شود و هیچ تغییری اعمال نمی‌شود.راه‌حل دوم: قفل‌های بدبینانه (Pessimistic Locking)تراکنش‌ها ممکن است مشکل خواندن داده‌های قدیمی را حل نکنند. برای حل این مشکل، باید از قفل‌های بدبینانه استفاده کنید. در لاراول، می‌توانید از lockForUpdate برای جلوگیری از دسترسی همزمان به رکوردها استفاده کنید:DB::transaction(function () {&#xA;    $alice = User::lockForUpdate()-&gt;find(1); // &#39;balance&#39; =&gt; 100&#xA;    $bob = User::lockForUpdate()-&gt;find(2); // &#39;balance&#39; =&gt; 0&#xA;    Bank::sendMoney($alice, $bob, 100); // true&#xA;});&#xA;&#xA;DB::transaction(function () {&#xA;    $alice = User::lockForUpdate()-&gt;find(1); // &#39;balance&#39; =&gt; 0&#xA;    $charlie = User::lockForUpdate()-&gt;find(3); // &#39;balance&#39; =&gt; 0&#xA;    Bank::sendMoney($alice, $charlie, 100); // false&#xA;});تفاوت lockForUpdate و sharedLockمتد lockForUpdate: مانع از تغییر یا خوانده شدن رکورد توسط سایر تراکنش‌ها تا زمان اتمام تراکنش جاری می‌شود.متد sharedLock: فقط مانع از تغییر رکورد می‌شود، اما سایر تراکنش‌ها می‌توانند آن را بخوانند.برای جلوگیری از مشکلاتی مانند Double Spending، استفاده از lockForUpdate کافی است، زیرا این قفل مانع از خواندن یا تغییر همزمان رکوردها می‌شود.نتیجه‌گیریاستفاده از قفل‌های مناسب در لاراول، مانند lockForUpdate و sharedLock، به شما کمک می‌کند تا تراکنش‌های ایمن و بدون تناقض را پیاده‌سازی کنید. با این حال، برای سیستم‌های بزرگ‌تر مانند بانکداری، استفاده از روش‌های پیشرفته‌تر مانند Event Sourcing توصیه می‌شود.این ابزارها به شما کمک می‌کنند تا از مشکلاتی مانند دوبرابر شدن یا از دست رفتن داده‌ها جلوگیری کنید و سیستم‌هایی قابل اعتمادتر بسازید.</description><category>زهیر مظاهری</category><author>زهیر مظاهری</author><pubDate>Sat, 14 Dec 2024 11:10:17 +0330</pubDate></item><item><title>استفاده از swagger در laravel</title><link>https://virgool.ir/@zoheirmaz.zm/how-use-swagger-in-laravel-gib4xtzlm6c4</link><description>مقدمهاگر توسعه دهنده backend باشید قطعا تا به حال براتون پیش اومده که خواستید api سرویسی که توسعه دادید رو به مدیر ارشد تیمتون و یا توسعه دهنده های frontend تحویل بدید. هرکدوممون از یه راهی استفاده کردیم، یا شفاهی براشون توضیح دادیم و یا توی تلگرام آدرس و اطلاعات api رو براشون فرستادیم و یا نهایت از Postman استفاده می ­کنیم ولی خب مشکلی که داره اینه که نمیشه محیط‌های ایجاد شده رو در حالت رایگان با بقیه توسعه دهنده ها به اشتراک گذاشت و به محض کوچکترین تغییر باید همه دوباره ایمپورتش کنند.اما خوشبختانه دوست عزیزمون، شرکت SmartBear به کمکمون اومده و swagger رو برامون توسعه داده.اما swagger چیست؟یک ابزار open-source برای توضیح، مستندسازی و تست سرویس های REST API است که کتابخانه های آن برای اکثر زبان­ ها و فریمورک ­های رایج توسعه وب موجود می­ باشد. از طریق اون میتونید انواع اطلاعات مربوط به سرویس های توسعه داده شده، از جمله ورودی ها و خروجی ها و انواع هرکدوم رو مستند کنید و همچنین میشه توی همون محیط اون ها را تست کرد.اولین تجربه کامل با Swaggerچند وقت پیش بود که برای پروژه ای که به تازگی گرفته بودم، برای مستند سازی apiهای سیستم، تصمیم گرفتم که از swagger استفاده کنم. با swagger از قبل و توی پروژه ای که حدود 6ماه قبل مشغولش بودم آشنا بودم اما خودم از صفر اجراش نکرده بودم و قبل از ورود من به پروژه، برنامه نویس ارشد تیم روی پروژه سوارش کرده بود و من صرفا مستنداتم رو بهش اضافه می­کردم.اما حالا بنا بود که خودم از صفر اجراش کنم. اما نکته ای که توجهم رو جلب کرد این بود منبع فارسی برای آموزش swagger بسیار کم بود و برای laravel که اصلا نبود! پس تصمیم گرفتم که یک توضیح مختصر فارسی برای پیاده سازی swagger در laravel آمده کنم.اولین حرکتدست به کار شدم و در اولین حرکت طبق عادت همیشگی خیلی هامون گوگل کردم “swagger Laravel” و به یک ریپوزیتوری github یک کتابخونه برخوردم که swagger رو روی laravel پیاده سازی کرده بود.این نکته رو اضافه کنم که توی این مقاله از لاراول 5.8 استفاده میکنم و قراره کتابخونه DarkaOnLine/L5-Swagger رو معرفی کنم و ازش استفاده کنم.نصباین کتابخانه نسخه های مختلفی داره که با مراجعه به ریپوزیتوری github میتونید با توجه به نسخه لاراولی که دارید استفاده میکنید نسخه مناسبتون رو انتخاب کنید https://github.com/DarkaOnLine/L5-Swagger  اما من چون از laravel 5.8 استفاده میکردم ورژن 5.8 این کتابخونه رو نصب کردم:composer require &#34;darkaonline/l5-swagger:5.8.*&#34;اگر از نسخه های &gt;= 5.5 لاراول استفاده میکنید نیازی به افزودن L5SwaggerServiceProvider به تنظیمات لاراول نیست اما اگر اینطوری نیست فایل AppServiceProvider را در مسیرconfig/app.php باز کنید و این خط رو به بخش providersاضافه کنید:L5Swagger\L5SwaggerServiceProvider::class,سپس دستور زیر رو اجرا کنید تا فایل های تنظیمات و view صفحه swagger برای شما ایجاد شود:php artisan vendor:publish --provider &#34;L5Swagger\L5SwaggerServiceProvider&#34;بعد از اجرای این دستور فایل های زیر ایجاد خواهند شد:Copied File [\vendor\darkaonline\l5-swagger\config\l5-swagger.php] To [\config\l5-swagger.php]&#xA;Copied Directory [\vendor\darkaonline\l5-swagger\resources\views] To [\resources\views\vendor\l5-swagger]&#xA;Publishing complete.برای ایجاد مستندات، swagger یک مجموعه annotation برای مشخص کردن و دستکاری ورودی ها و خروجی ها پیشنهاد داده است که می توان آنها را به controller و یا modelها اضافه کرد و یا آنها را در یک فایل جداگانه قرار داد که می توانید نمونه هایی از آن را در اینجا، اینجا و اینجا مشاهده بفرمایید (آموزش annotation ها را در بخش های بعدی به طور جداگانه توضیح خواهم داد).حالا اگر annotation ها رو درست و کامل نوشته باشید با دستور زیر میتونید مستندات خودتون رو ایجاد کنید:php artisan l5-swagger:generateو یا در فایل env. میتونید مقدار L5_SWAGGER_GENERATE_ALWAYS را برابر true قرار بدید تا مستنداتتون به طور خودکار ایجاد بشن.حالا میتونید از طریق yourdomain.com/api/documentation به مستندات خود دسترسی داشته باشید.صفحه مستندات swaggerآخر نوشتبه قول یک دوستی که میگفت: کاش کد نویسایی که داکیومنت نمی نویسن برن زیر تریلی! پس خواهشا داکیومنت بنویسید :)</description><category>زهیر مظاهری</category><author>زهیر مظاهری</author><pubDate>Fri, 20 Mar 2020 04:18:44 +0330</pubDate></item></channel></rss>