<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های رضا</title>
        <link>https://virgool.io/feed/@rezarabbbani</link>
        <description>مشغول کُشتن زامبی‌ها</description>
        <language>fa</language>
        <pubDate>2026-06-07 20:33:34</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/24913/avatar/8BHG4o.png?height=120&amp;width=120</url>
            <title>رضا</title>
            <link>https://virgool.io/@rezarabbbani</link>
        </image>

                    <item>
                <title>نکاتی برای آمادگی آزمون آیلتس (رضا یکانی)</title>
                <link>https://virgool.io/@rezarabbbani/%D8%A2%DB%8C%D9%84%D8%AA%D8%B3-%D8%B1%D9%88-%D8%A7%D8%B2-%DA%A9%D8%AC%D8%A7-%D8%B4%D8%B1%D9%88%D8%B9-%DA%A9%D9%86%DB%8C%D9%85-xygjb0e1fwgc</link>
                <description>رضا یکانی مدرس آیلتس آموزشگاه آفرینشاگر در مسیر یادگیری زبان هستین این یادداشت میتونه براتون موثر باشه.چون استفاده از تجربه دیگران میتونه منجر به گرفتن تصمیمات بهتر، درست تر و مناسب تر بشه.حدودا 6 ماه قبل برای آمادگی آیلتس و یادگیری زبان با یکی از مدرس های زبان آموزشگاه سفیر شعبه شریعتی به نام رضا یکانی (اینستاگرام، فیسبوک) جلسات خصوصی برداشتم.رضا یکانی مدرس آیلتس آموزشگاه سفیر شریعتیرضا یکانی مدرس آیلتس آموزشگاه سفیر شریعتیالویتم مهارت تدریس و سوابق آموزشی مدرس بود در صورتیکه الویت اول ام میبایست شخصیت، اخلاق حرفه ای، وجدان کاری و ...می بود.خب متاسفانه اشتباه در شناخت افراد میتونه مضر باشه و منجر به مورد سواستفاده قرار گرفتن و اتلاف زمان و پولتون بشه.کنسلی های پی در پی کلاس و روند کند کلاس بدون فیدبک و بی انگیزگی مدرس از ابتدا و در نهایت نیمه کاره ماندن کلاس ها و ناپدید شدن مدرس خلاصه ی ماجرای ایشون بود. که صد البته چون این روزها فضای آموزش زبان، به بازار مکاره ی برخی ها تبدیل شده، این اتفاق ناآشنا نیست..?توصیه میکنم برای یادگیری زبان خیلی کم، بطور مستقیم سراغ معلم های خصوصی ناآشنا برید. وقتی با یک موسسه طرف باشید نه یک فرد، حتا اگر مدرس خودجوش! ناپدید بشه شما نیاز به زمان گذاشتن و پیگیری و حتا شکایت ندارین.. این برعهده ی موسسه است.?وجدان کاری ، شخصیت پاسخگو و اخلاق حرفه ای به راحتی قابل تشخیص نیست پس اگر جلسات خصوصی برمیدارین پرداخت رو برای تعداد کوتاه-مثلا هر 5 جلسه- قرار بدین.?به روش های سلف استادی و مدرس ها و منابع خارجی نگاه ویژه ای داشته باشین این مورد برای من خیلی خیلی موثر و خوب بود. تقریبا تمام منابع عالی بطور رایگان در دسترسه?? (بجز برای رایتینگ که شما به کمک نیاز دارید)? There isn&#x27;t a secret! Just keep practicing, keep learning.? و در آخر به قول استیو کافمن مردی که 20 زبان رو بلده:Become an Independent Language Learnerپ.ن: با احترام به همه ی مدرسین حرفه ای و با شخصیت که تعدادشون کم نیست ?#رضا_یکانی #آموزشگاه_سفیر #زبان #آیلتسمنبع</description>
                <category>رضا</category>
                <author>رضا</author>
                <pubDate>Mon, 12 Dec 2022 12:23:49 +0330</pubDate>
            </item>
                    <item>
                <title>چند دیتابیس در یک MySQL Container</title>
                <link>https://virgool.io/@rezarabbbani/%DA%86%D9%86%D8%AF-%D8%AF%DB%8C%D8%AA%D8%A7%D8%A8%DB%8C%D8%B3-%D8%AF%D8%B1-%DB%8C%DA%A9-mysql-container-inc0tnx2zyep</link>
                <description>هنگام ساخت یک کانتینر MySQL با مقدار دهی به متغیر MYSQL_DATABASE, به صورت پیشفرض یک دیتابیس با این نام ساخته می شود.برای افزودن دیتابیس های بیشتر باید برای هرکدام یک فایل sql, که شامل کوئری ساخت دیتابیس جدید و دادن دسترسی ها به کاربر پیشفرض کانتینر MySQL است, در فولدر docker-entrypoint-initdb.d داخل کانتینر قرار دهیم و هنگام ساخته شدن کانتینر, داکر هر تعداد فایل sql که داخل این فولدر باشد را به ترتیب حروف الفبا اجرا می کند و دیتابیس های مورد نظر ما ساخته می شود.ابتدا یک Dockerfile می سازیمtouch Dockerfileسپس یک MySQL image با ورژن دلخواه را در آن فراخوانی میکنیم و همه فایل های sql موجود در فولدر کنونی را داخل کانتینر در فولدر docker-entrypoint-initdb.d میریزیم# Using latest version of MySQL
FROM mysql:latest

# Copying all sql files that are in charge of creating new databases
COPY ./*.sql ./docker-entrypoint-initdb.d/برای نمونه فایل 01.sql را با محتویات زیر برای ساخت اولین دیتابیس قرار می دهیم# Create new_db if doesn&#039;t exist
CREATE DATABASE IF NOT EXISTS `new_db`;

# Give all permissions to admin user
GRANT ALL ON `new_db`.* TO &#039;admin&#039;@&#039;%&#039;;حالا یک image از Dockerfile می سازیمdocker build -t multi_database_mysql -f Dockerfileو یک کانتینر با استفاده از آن راه اندازی می کنیمdocker run --name my_multi_database_mysql \
-e MYSQL_ROOT_PASSWORD=root-password \
-e MYSQL_USER=admin \
-e MYSQL_PASSWORD=password \
-e MYSQL_DATABASE=db \
-d multi_database_mysqبا استفاده از دستور زیر وارد کانتینر خود شویدdocker exec -it my_multi_database_mysql bash -lسپس در MySQL لاگین کنیدmysql -uadmin -ppasswordو با اجرای کوئری زیر لیست دیتابیس های ساخت شده را ببینیدSHOW DATABASES;اگر از Docker Compose استفاده میکنید فایل های sql ساخت دیتابیس ها را داخل یک فولدر قرار دهید و در شاخه volumes به کانتینر خود بشناسانید  mysql:
    container_name: multi-db-mysql
    image: mysql:latest
    restart: unless-stopped
    volumes:
      - ./mysql:/var/lib/mysql
      - ./init:/docker-entrypoint-initdb.d
..........</description>
                <category>رضا</category>
                <author>رضا</author>
                <pubDate>Mon, 05 Jul 2021 10:21:57 +0430</pubDate>
            </item>
                    <item>
                <title>روش صحیح آپلود لاراول در هاست اشتراکی</title>
                <link>https://virgool.io/@rezarabbbani/%D8%B1%D9%88%D8%B4-%D8%B5%D8%AD%DB%8C%D8%AD-%D8%A2%D9%BE%D9%84%D9%88%D8%AF-%D9%84%D8%A7%D8%B1%D8%A7%D9%88%D9%84-%D8%AF%D8%B1-%D9%87%D8%A7%D8%B3%D8%AA-%D8%A7%D8%B4%D8%AA%D8%B1%D8%A7%DA%A9%DB%8C-pashfgvqc2zh</link>
                <description>هاست اشتراکی ارزان ترین سرویس برای آپلود یک وبسایت است. در هاست اشتراکی شما هیچگونه دسترسی مستقیم به سرور نخواهید داشت و تنها راه ارتباطی شما با سرور استفاده از پروتکل FTP و یا سیستم مدیریت فایل (Direct Admin, Plesk و ...) نصب شده توسط شرکت هاستینگ است.هاست مناسب برای لاراول یک هاست لینوکسی است که با توجه به ورژن لاراول, ورژن مناسب php و mysql بر روی آن نصب شده باشد. لاراول باید به حالت انتشار (Production) آپلود شود. آپلود پروژه در حالت توسعه به شدت خطرناک است و راه نفوذ برای دیگران را باز میگذارد. در مستندات لاراول توضیحات کاملی در این باره داده شده که در این مقاله قدم به قدم و متناسب شده با هاست اشتراکی توضیح داده میشوند.در هاست شتراکی هیچگونه دسترسی مستقیم به command line امکان پذیر نیست (پروتکل ssh بسته است) و به همین دلیل مجبوریم قسمتی از آماده سازی را بر روی سیستم خود و به صورت local انجام بدهیم.در ابتدا پکیج های مورد نیاز را توسط composer نصب میکنیم. در اینجا باید دقت کرد که فقط باید پکیج هایی که در قسمت require فایل composer.json قرار دارند را نصب کنیم, برای این کار دستور زیر را در فولدر پروژه اجرا میکنیمcomposer install --optimize-autoloader --no-devمرحله بعدی ایجاد جداول در دیتابیس است و همچنین با توجه به مستندات باید متغییر های env, کلیه فایل های view و route ها را برای پرفورمنس بهتر cache کنیم همچنین مقدار متغییر APP_DEBUG را false و APP_ENV را production قرار دهیم.همه ی موارد بالا با استفاده از اجرای دستورات در command line اجرا می شوند و تنها راه برای اجرای آنها در هاست اشتراکی استفاده از یکی از Facade های جالب لاراول به نام Artisan است که با فراخوانی متد call آن می توانیم دستورات مختلف artisan را اجرا کنیم.پیشنهاد من برای این کار افزودن یک route است که هنگام فراخوانی در صورتی که مقدار APP_DEBUG = true باشد دستورات لازم را اجرا میکند و در انتها مقدار APP_DEBUG را false میکند تا در صورت فراخوانی دوباره و ناخواسته خطای ۴۰۴ برگردانده شود.این route را اضافه میکنیمRoute::get(&#039;/deploy&#039;, &#039;DeployController@deploy&#039;);سپس DeployController را به صورت زیر پیاده سازی میکنیم https://gist.github.com/thrashzone13/aaf951cc43c06867f098f213bc430ae0 حالا تمامی فایل های پروژه به همراه پوشه vendor را zip میکنیم در سیستم مدیریت فایل هاست فولدری با نام project (یا هر نام دلخواه دیگری) میسازیم و فایل zip را در آن آپلود و unzip میکنیم, سپس تمامی فایل های درون فولدر public را به فولدر public_html منتقل میکنیم.حال باید مسیر فراخوانی فایل autoload.php را به صورت زیر require __DIR__.&#039;/../project/vendor/autoload.php&#039;;همچنین فراخوانی فایل app.php را به این شکل$app = require_once __DIR__.&#039;/../project/bootstrap/app.php&#039;;در داخل فایل index.php تغییر دهیم و بعد از آن به سراغ فایل server.php در فولدر project رفته و مسیر فراخوانی index.php را نیز به صورت زیر تغییر میدهیمrequire_once __DIR__.&#039;/../public_html/index.php&#039;;وارد phpmyadmin هاست خود شوید و بعد از ساخت کاربر و دیتابیس مورد نظر اطلاعات دیتابیس را در فایل env. وارد کنید. توجه داشته باشید مقدار APP_DEBUG = true و APP_ENV = production باشد.مسیر deploy که پیشتر ساختیم را در مرورگر فراخوانی کنید کار تمام است /m\</description>
                <category>رضا</category>
                <author>رضا</author>
                <pubDate>Tue, 04 May 2021 22:50:45 +0430</pubDate>
            </item>
                    <item>
                <title>رعایت اصل DRY در لاراول</title>
                <link>https://virgool.io/@rezarabbbani/%D8%B1%D8%B9%D8%A7%DB%8C%D8%AA-%D8%A7%D8%B5%D9%84-dry-%D8%AF%D8%B1-%D9%84%D8%A7%D8%B1%D8%A7%D9%88%D9%84-dtghzjssm5d3</link>
                <description>برای توضیح (Don&#x27;t Repeat Yourself) DRY این متن رو از ویکیپدیا قرار میدم:‍‍‍اصلی در برنامه‌نویسی رایانه‌ای است که به‌وسیلهٔ عدم تکرار یک یا چند خط کد در مکان‌های مختلف برنامه رعایت می‌شود. در واقع با این کار، برای اصلاح بخشی از برنامه نیاز به اصلاح قسمت‌های مختلف و جداگانه‌ای از کد نیست. برای رعایت این اصل معمولاً برنامه‌نویسان کد خود را داخل یک تابع یا کلاس قرار داده و در موارد مورد نیاز تابع را فراخوانی کرده یا یک شئ جدید از کلاس می‌سازند.در پروژه های لاراولی عملیات CRUD برای Model ها علاوه بر Controller ها ممکن است در کلاس های Command یا Event یا حتی در کنترلر های دیگری که به طور خاص برای آن Model ساخته نشده اند اتفاق بیافتد. علاوه بر این CRUD برای هر مدل در هر قسمتی که انجام شود عموما یکسان است. یک ذخیره داده ساده در لاراول معمولا مانند مثال زیر نوشته می شود:public function store (Request $request) {
    User::create($request-&gt;all());
    return redirect()-&gt;back();
}و از آنجایی که Model ها در Eloquent تمامی سیستم ORM را به ارث می برند در ظاهر این کد یک خطی تمیز است مشکلی ندارد اما:  لایه Controller مجاز به دانستن این عملیات ها نیست و فقط مجاز به فراخوانی دیگر لایه ها است.در صورت افزوده شدن عملیات های دیگر که باید بعد از ذخیره داده انجام شوند با تکرار کد مواجه می شویم. برای مثال بخواهیم برای بعد از ذخیره هر کاربر یک Blog  هم برای آن ذخیره کنیم.با توجه به اصل لیسکوف در SOLID برای مثال امکان جایگزینی Eloquent با یک ORM دیگر را نداریم.پس نیاز به پیاده سازی لایه ای بالاتر که توسط Controller فراخوانده شود به شدت احساس می شود. لایه بالاتر که به آن Service Layer می گوییم به ازای هر کدام از Model ها ساخته شده و می تواند به هر کدام از حروف CRUD یک Method اختصاص بدهد (از آنجایی که READ در لایه Repository انجام می شود آن را در قرارداد این لایه قرار نمی دهیم):interface ServiceLayerInterface {
    public function create (array $data): Model;
    public function update (int|string $id, array $data): Model;
    public function delete (int|string $id): void;
}اما با توجه به این که هر کدام از این Method ها کار جداگانه ای انجام می دهد پس با توجه به اصل تک مسئولیتی کلاس ها در SOLID می توانیم به هر کدام از عملیات ها یک کلاس اختصاص دهیم.interface CreateServiceInterface {
    public function handle (array $data): Model;
}و طبق قرارداد بالا داشته باشیم:class CreateUser implements CreateServiceInterface {
    public function handle (array $data): Model {
        $user = new User();
        $user-&gt;name = $data[&#039;name];
        $user-&gt;email = $data[&#039;email&#039;];
        $user-&gt;password = Hash::make($data[&#039;password&#039;]);
        $user-&gt;save();
        return $user;
    }
}حالا تنها کاری که باید انجام شود فراخوانی این کلاس در مکان های لازم است:class UserController extends Controller {
    public function store(CreateUser $service, Request $request) {
        $user = $service-&gt;handle($request-&gt;all());
        return view(&#039;profile&#039;, [&#039;user&#039; =&gt; $user]);
    }
}و یا برای مثال اگر قرار باشد توسط یک Command اطلاعات کاربران را از یک فایل بگیریم و در دیتابیس ذخیره کنیم:class ImportUsers extends Command {

    protected $service;

    public function __construct (CreateUser $service) {
        $this-&gt;service = $service;
    }

    public function handle () {
        $users = // Read data from file as array;
        foreach ($users as $user)
           $this-&gt;service($user);
    }
}</description>
                <category>رضا</category>
                <author>رضا</author>
                <pubDate>Mon, 29 Mar 2021 10:44:33 +0430</pubDate>
            </item>
                    <item>
                <title>آپلود پروژه React بر روی هاست</title>
                <link>https://virgool.io/wptips/%D8%A2%D9%BE%D9%84%D9%88%D8%AF-%D9%BE%D8%B1%D9%88%DA%98%D9%87-react-%D8%A8%D8%B1-%D8%B1%D9%88%DB%8C-%D9%87%D8%A7%D8%B3%D8%AA-nweimtpzoc7b</link>
                <description>معمولا برای اولین بار که اپلیکیشنی با استفاده از یک فریم‌ورک می‌نویسیم, این سوال پیش می‌آید که چگونه آن را بر روی یک هاست اشتراکی آپلود کنیم.معمولا فریم‌ورک‌ها شامل دو حالت development (شامل ابزار‌های ویژه برای دیباگینگ) و production (شامل فایل‌های فشرده شده همراه با کَش برخی فایل‌ها) هستند.همواره به این نکته توجه داشته باشید که آپلود پروژه در حالت development خطر نمایش ناخواسته اطلاعات ضروری پروژه شما (مانند اطلاعات احراز هویت دیتابیس) در سَمت client را به دنبال دارد, همچنین به دلیل نبود خروجی کَش و فشرده شده از فایل‌ها سرعت بارگذاری پایین‌تری نسبت به production دارند.قدم اول برای build گرفتن از پروژه اضافه کردن مسیر اصلی دسترسی هاست به فایل package.json است.کلید homepage را به package.json اصافه می‌کنیم و url هاست رو به عنوان مقدار اون قرار می‌دهیم:{
   &amp;quotname&amp;quot: &amp;quotreact-app&amp;quot,
   &amp;quotversion&amp;quot: &amp;quot0.1.0&amp;quot,
   &amp;quothomepage&amp;quot:  آدرس وبسایت,
   &amp;quotprivate&amp;quot: true,
   &amp;quotdependencies&amp;quot: { ... },
    .... 
}سپس دستور زیر را در پوشه پروژه اجرا میکنیم:npm run buildبعد از اینکار پوشه build به پروژه اضافه میشه که شامل فایل‌هایی از جمله دو فایل فشرده شده css و js است.حالا به file manager هاستمون میریم و در پوشه public_html فایلی با نام .htaccess اضافه می‌کنیم که شامل این باشه:&lt;IfModule mod_rewrite.c&gt;
     RewriteEngine On
     RewriteBase /
     RewriteRule ^index\.html$ - [L]
     RewriteCond %{REQUEST_FILENAME} !-f
     RewriteCond %{REQUEST_FILENAME} !-d
     RewriteCond %{REQUEST_FILENAME} !-l
     RewriteRule . /index.html [L]
&lt;/IfModule&gt;این قطعه کد مسیر‌ اصلی پروژه ما رو به سرور معرفی میکنه, حالا فایل های پوشه build رو در public_html آپلود می‌کنیم و کار تمومه.کامل‌تر این نوشته رو می‌تونین اینجا بخونین.</description>
                <category>رضا</category>
                <author>رضا</author>
                <pubDate>Tue, 02 Jun 2020 14:54:50 +0430</pubDate>
            </item>
                    <item>
                <title>درخواست های Http متمرکز در Redux</title>
                <link>https://virgool.io/@rezarabbbani/%D8%AF%D8%B1%D8%AE%D9%88%D8%A7%D8%B3%D8%AA-%D9%87%D8%A7%DB%8C-http-%D9%85%D8%AA%D9%85%D8%B1%DA%A9%D8%B2-%D8%AF%D8%B1-redux-vya3omifhlna</link>
                <description>با استفاده از Thunk middleware می‌توانیم action های Redux رو از object های ساده به متد های هوشمند تبدیل کنیم. یکی از استفاده های معروفی که از این هوشمند سازی میشه, ارسال درخواست‏ های http از طریق action هاست. اگه به نمونه کد زیر نگاه کنیم در کنار مزیت انتقال درخواست ها به این بخش متوجه یه سری معایب هم می‌شویم:اگه در کل پروژه همین یک درخواست رو داشتیم مشکلی نبود, ولی خب اینجوری نیست! در حقیقت تعداد زیادی درخواست داریم که مثلا بخش پردازش خطا‌های بازگشتی از این درخواست‌ها تقریبا مثل هم انجام میشه, پس بهتره یه کد اصلی برای انجام کلیه درخواست هامون داشته باشیم.می‌تونیم دوباره با  middleware ها مشکلمون رو حل کنیم, مثلا هر بار که خواستیم درخواست http داشته باشیم این action رو dispatch کنیم:و یه middleware داشته باشیم که در صورت dispatch شدن &#x27;API_REQUEST&#x27; اطلاعات لازم رو از meta object بگیره و درخواست رو انجام بده:حالا اگه بخواهیم مثلا baseURL رو هم تغییر بدیم فقط همین قسمت از کد نیاز به تغییر داره یا حتی می‌توانیم loading رو به سادگی به همه درخواست هامون اضافه کنیم:به همین تمیزی! برای اضافه کردن middleware به store از اینجا کمک بگیرین.</description>
                <category>رضا</category>
                <author>رضا</author>
                <pubDate>Fri, 29 May 2020 00:00:45 +0430</pubDate>
            </item>
                    <item>
                <title>دیزاین پترن استراتژی در Reducre های Redux</title>
                <link>https://virgool.io/@rezarabbbani/%D8%AF%DB%8C%D8%B2%D8%A7%DB%8C%D9%86-%D9%BE%D8%AA%D8%B1%D9%86-%D8%A7%D8%B3%D8%AA%D8%B1%D8%A7%D8%AA%DA%98%DB%8C-%D8%AF%D8%B1-reducre-%D9%87%D8%A7%DB%8C-redux-f6znrbmilurl</link>
                <description>در اکثر آموزش های Redux برای پیاده سازی Reducer ها همچین شکلی پیشنهاد میشه:استفاده از switch case برای بررسی حالت های مختلف نسبتا منطقیه ولی با بیشتر شدن حالات به مرور تکرار کد زیاد و خوانایی کد کم میشه. شاید اولین راه حلی که به ذهنمون برسه این باشه که برای هر کدوم از شرط ها یه متد جداگانه تعریف کنیم و عملیات هر کدوم رو به متد خودش انتقال بدیم :خب تا حدودی بهتر شد.حالا چطور از شر اون switch case راحت شیم و هوشمندتر عمل کنیم؟ یه object از حالت های مختلف میسازیم که شامل حالت default با مقدار state =&gt; state باشه و Reducer ما بتونه با یه if یه خطی حالت مورد نظر رو از توش پیدا کنه :به همین سادگی و با پیاده سازی دیزاین پترن استراتژی تونستیم کدمون رو خواناتر کنیم!این فقط یه خلاصه از یه نوشته دیگس, اصلش رو اینجا بخونین: https://levelup.gitconnected.com/react-redux-and-the-strategy-pattern-8019c0c5bb54 </description>
                <category>رضا</category>
                <author>رضا</author>
                <pubDate>Wed, 27 May 2020 12:47:58 +0430</pubDate>
            </item>
            </channel>
</rss>