<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های Soheil Rahmat</title>
        <link>https://virgool.io/feed/@soheilrt314</link>
        <description>ما در مقابل پیشرفت و افزایش علم در جامعه خودمون مسئولیم.</description>
        <language>fa</language>
        <pubDate>2026-06-29 09:13:00</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/70611/avatar/amG2hv.png?height=120&amp;width=120</url>
            <title>Soheil Rahmat</title>
            <link>https://virgool.io/@soheilrt314</link>
        </image>

                    <item>
                <title>راه‌حل ذخیره وابستگی ها مدل‌های جدید - لاراول</title>
                <link>https://virgool.io/laravel-community/%D8%B1%D8%A7%D9%87%D8%AD%D9%84-%D8%B0%D8%AE%DB%8C%D8%B1%D9%87-%D9%88%D8%A7%D8%A8%D8%B3%D8%AA%DA%AF%DB%8C-%D9%87%D8%A7-%D9%85%D8%AF%D9%84%D9%87%D8%A7%DB%8C-%D8%AC%D8%AF%DB%8C%D8%AF-%D9%84%D8%A7%D8%B1%D8%A7%D9%88%D9%84-raxibujeweet</link>
                <description>معمولا بیشتر اوقات به سورس کدهای نوشته شده لاراول که نگاه میکنیم میبینیم که معمولا وابستگی های یک مدل بعد از این که مدل ذخیره میشه به صورت جدا درون دیتابیس ذخیره میشه مثل زیر:public function store(Request $request)
{
    /** @var User $user*/
    $user  = User::query()-&gt;create($request-&gt;except(&#039;phones&#039;));
    $user-&gt;Phones()-&gt;createMany($request-&gt;get(&#039;phones&#039;));
    
    //
    // Other Model&#039;s relations store operation will come here
    //
    
    return redirect()-&gt;route(&#039;user.edit&#039;, $user-&gt;getKey() );
}توی مثال بالا ما در هر مرحله یک کار رو انجام دادیم. ابتدا کاربر رو ساختیم و  بعدش در هر مرحله وایستگی ها رو ایجاد کردیم.اما یک مسله‌ای که وجود داره اینه که اگر ما بخوایم مقادیر رو قبل از ذخیره نرمال سازی کنیم و تمام مقادیر رو به یک فرمت خاص درون دیتابیس ذخیره کنیم کارهایی که باید توی کنترلر انجام بدیم زیاد میشه و تمیزی کد رو مقداری کم میکنه. برای حل این مشکل ما معمولا از ویژگی توی لاراول استفاده میکنیم که به نام Mutator شناخته میشن. که با استفاده از mutatorها کد ما به صورت زیر درمیاد.class User extends Authenticatable
{
    ...

    public function Phones()
    {
        return $this-&gt;hasMany(Phone::class);
    }


    /**
     * mutator for user phones
     *
     * @param array|mixed $value
     * @return void
     */
    public function setPhonesAttribute($value)
    {
        $normalized_phones = $this-&gt;normalizePhones($value);
        $this-&gt;Phones()-&gt;delete();
        $this-&gt;Phones()-&gt;createMany($normalized_phones);
    }
   ....
} خوب توی کد بالا ما یک mutator برای شماره تلفن های کاربر ایجاد کردیم که مسولیت ذخیره سازی شماره تلفن هایی که برای کاربر ارسال میشن رو به عهده میگیره. خوب ما اینجا اول شماره تلفن ها رو نرمال سازی کردیم، بعدش شماره های قبلی کاربر رو پاک کردیم که شماره های اضافی قبلی که کاربر داشته پاک بشن و شماره های جدید رو بعدش ذخیره میکنیم.اما توی این کد یک مشکل وجود داره. بیاین مثال زیر رو در نظر بگیریم:داده های که ما توی درخواست داریم به صورت زیره:[
    &#039;name&#039;=&gt;&#039;...&#039;,
    &#039;email&#039;=&gt;&#039;...&#039;,
    &#039;password&#039;=&gt;&#039;...&#039;,
    &#039;...&#039;,
    &#039;phones&#039;=&gt;[
        &#039;...&#039;,
        &#039;...&#039;,
        &#039;...&#039;
    ],
    &#039;...&#039;
];و متد ذخیره کردن مدل کنترلر ما هم به صورت زیره:/**
 * create new user
 *
 * @param Request $request
 * @return string
 */
public function store(Request $request)
{
    /** @var User $user*/
    $user  = User::query()-&gt;create($request-&gt;all());
    return redirect()-&gt;route(&#039;user.edit&#039;,$user-&gt;getKey());
}اما اینجا ما به یک مشکل بر میخوریم و اونم اینه که زمانی که ما اقدام به پر کردن مقادیر phones برای کاربر میکنیم، mutator ما فراخوانی میشه و باعث میشه که شماره تلفن های کاربر ما قبل از ذخیره شدن خود کار ذخیره بشن و باعث ایجاد خطای کلید خارجی در پایگاه داده میشه. برای حل این مشکل ما میتونیم از observerها استفاده کنیم و به صورت زیر mutator خودمون رو تغییر میدیم./**
 * accessor for user phones
 *
 * @param array|mixed $value
 * @return void
 */
public function setPhonesAttribute($value)
{
    $normalized_phones = $this-&gt;normalizePhones($value);
    if ($this-&gt;exists){
        $this-&gt;Phones()-&gt;delete();
        $this-&gt;Phones()-&gt;createMany($normalized_phones);
    } else {
        self::created(function (self $self) use ($normalized_phones){
            $slef-&gt;Phones()-&gt;createMany($normalized_phones);
        });
    }    
}خوب ما توی mutator خودمون از متغیر exists مدل  استفاده کردیم. این متغیر زمانی مقدار true داره که مدل ما توی دیتابیس وجود داشته باشه ( رکورد معادل مدل درون جدول مدل وجود داشته باشه).خوب اگر که مدل ما توی دیتابیس وجود داشت که مثل شماره تلفن های کاربر رو ذخیره می‌کنیم و اگر وجود نداشته باشه یک observer برای مدل تنظیم می‌کنیم که زمانی که مدل ذخیره شد، observer ما فراخونی میشه و شماره تلفن های ما ذخیره می‌شه. اینجوری دیگه مشکل ذخیره کردن شماره تلفن‌های کاربر قبل از ذخیره سازی خود کاربر حل میشه. از طرف دیگه از شلوغی کدهای توی کنترلر کم می‌شه  و خوانایی کد بالا میره. از طرفی هم اگر ما از چند جای مختلف کاربر جدید درست کنیم از کد زدن اضافی پرهیز کردیم.</description>
                <category>Soheil Rahmat</category>
                <author>Soheil Rahmat</author>
                <pubDate>Sun, 31 May 2020 23:43:09 +0430</pubDate>
            </item>
                    <item>
                <title>انتزاع کامپیوترها - تاریخچه بزرگترین برون‌سپاری بشر</title>
                <link>https://virgool.io/coderlife/%D8%A7%D9%86%D8%AA%D8%B2%D8%A7%D8%B9-%DA%A9%D8%A7%D9%85%D9%BE%DB%8C%D9%88%D8%AA%D8%B1%D9%87%D8%A7-%D8%AA%D8%A7%D8%B1%DB%8C%D8%AE%DA%86%D9%87-%D8%A8%D8%B2%D8%B1%DA%AF%D8%AA%D8%B1%DB%8C%D9%86-%D8%A8%D8%B1%D9%88%D9%86%D8%B3%D9%BE%D8%A7%D8%B1%DB%8C-%D8%A8%D8%B4%D8%B1-frvakyu8b0ap</link>
                <description>پیش‌ درآمدما از وقتی که تونستیم قدرت تفکر داشته باشیم همیشه بر اساس نیازهایی که داشتیم در حال تولید و اختراع چیز های جدید بودیم. اولش با برگ برای خودمون لباس درست کردیم چون نیاز به گرما و پوشیدگی داشتیم. خودکار و مداد رو درست کردیم چون یک چیزی لازم داشتیم که بتونیم باهاش وقایع رو ثبت کنیم.ماهیتدر ابتدا ما هرچی درست میکردیم با یک ماهیت قبلی درست میکردیم، یعنی اول ماهیت شی که میخوایم درست کنیم رو تعریف می‌کردیم و بعدش اون شی رو می‌ساختیم. بزارین با چند تا مثال بزنمما خودکار رو بر اساس یک ماهیت قبلی ساختیم: وسیله‌ای جهت نوشتن و ثبت وقایع.شمشیر:‌ وسیله ای برای جنگ و شکار.البته هنوز هم همینه و توی بیشتر اوقات ما داریم روی هول یک ماهیت از قبل تعریف شده تولیداتمون رو انجام میدیم. (به غیر از بک‌جا که زدیم جاده خاکی که یکم جلوتر بهش می‌رسیم)تفکر ماهیت پذیریهمینطور که توی سیر زمان روی زمین درگیر زنده موندن و پیشرفت بودیم، از مرزهای بقا رد شدیم  و زمانی که مطمئن شدیم که دیگه خطرهایی مثل خورده شدن توسط گرگ یا خرس مارو تهدید نمیکنه و خیالمون جمع شد که تقریبا خیلی احتمالش کمه که از سوء تغذیه بمیریم، شروع کردیم به برون سپاری کارهامون. آسیاب بادی رو ساختیم که که زحمت آسیاب کردن دستی رو نکشیم و مثال هایی زیاد دیگه که وجود داره که ما کارهامون رو دیگه خودمون انجام نمیدادیم یا یک بخش بزرگی از کار رو رو به کمک یک ابزار انجام میدادیم که خودمون کمتر انرژی مصرف کنیم. در واقع ما هر دفعه یک ماهیت‌های کوچکی جهت راحتی خودمون خلق می‌کردیم ( و می‌کنیم) که هر روز زندگی ما رو راحت‌تر میکرد (میکنه).این خلق کرد خیلی خوب بود ولی واسه ما کافی نبود. از اونجایی که ما ذاتا خیلی تنبل‌ایم به یک چیزی مثل خودمون نیاز داشتیم، چیزی که کمترین ماهیت ثابت رو داشته باشه و قابلیت افزودن ماهیت‌های دیگه رو به خودش داشته باشه و ما بر اساس نیاز خودمون براش ماهیت و دستورالعمل تعریف کنیم و در جهت رفع نیازهامون ازش استفاده کنیم. دقیقا مثل خودمون که موجوداتی هستیم که زمانی‌ که به دنیا می‌آییم تنها ماهیتی که داریم جنسیت و چند عدد ویژگی ظاهریه که قابل تغییر نیست.(اینجا منظور از ماهیت ویژگی هایی هستند که اگر حذف بشن تقریبا موجودیت یک شی خدشه دار میشه و تقریبا موجودیتش تغییر میکنه، پس در این صورت ماهیت هایی مثل ملیت توی دسته‌ی ماهیت‌های فطری دسته‌بندی نمیشه).و همین بی‌ماهیت بودنمونه که به بزرگترین ویژگی انسان تبدیل شده و خودمون با ساختن مسیر زندگیمون به خودمون ماهیت میدیم و به وسیله اون ماهیت بین اطرافیانمون شناخته می‌شیم.کامپیوتر، بی‌ماهیت ترین ساخته دست بشرما هم به ابزاری شبیه به خودمون (ابزاری ماهیت پذیر) احتیاج داشتیم. ابزاری که ماهیت فطری خیلی محدود و انتزاعی داشته باشه و مابقی ماهیت‌هایی که ما نیاز داریم، بسته به نیازهامون به اون ابزار اضافه یا کم بشه. این همون اول راه کامپیوتر بودالبته اول دوره چیزی که ما امروز به عنوان کامپیوتر می‌شناسیم، بدون ماهیت نبوده و اتفاقا هم خیلی ماهیتی دقیقی داشته.اولین کامپیوتر هامیتونیم اولین چرتکه ها(۱۶۲۲) رو به عنوان شروع ظهور کامپیوتر‌ها در نظر گرفت، هرچند اولین دستگاهیی که ما به امروز عنوان کامپیوتر می‌شناسیم، بین سال‌های ۱۸۳۳ و ۱۸۷۱ به وسیله چارلز ببیج  به وجود اومد که دستگاهی جهت تحلیل مسائل ریاضی درست شد. راستی قبل از اون اصطلاح کامپیوتر (computer) به کسی می‌گفتند که تمام روز پشت میز می‌نشست و محاسبات ریاضی انجام می‌داد تا در آینده وارد کتاب شود تا از اون‌ها توی محاسبات جنگی و مهندسی استفاده بشه.ظهور کامپیوترهای انتزاعیوقتی ما قدرت کامپیوتر‌‌ها رو  توی عملیات ریاضی دیدیم و متوجه قدرت پردازشی اون شدیم،‌ به فکر استفاده چند منظوره از اون افتادیم،‌ شروع کردیم به جدا سازی قطعات و انتزاعی کردن وظایف هر قطعه درون کامپیوتر. مثلا اگر ما به پردازشگر کامپیوتر به صورت یک قطعه تنها (بدون هیچ دستگاه استفاده کننده از اون و مبدل اطلاعت) یا تقریبا هر دستگاه دیگه‌ای از اون نگاه کنیم، می‌بینیم که یک دستگاه بلا‌استفادس و ما هیچ استفاده مفیدی نمی‌تونیم ازش داشته باشیم.همین انتزاعی و تک‌منظوره کرده استفاده قطعات بود سرعت پیشرفت ما رو زیاد کرد. از اینجا به بعد ما تونستیم توی حوزه های مختلف تخصص کسب کنیم و هرکسی توی یک حوزه تخصص پیدا کنه بدون این‌که نگران موضوعات دیگه باشه. البته تخصصی شدن حوزه‌ها  و ارتباط بین اونها هم بدون دردسر نبود و همین موضوع باعث شد افرادی جهت استاندارد سازی ارتباط بین این حوزه‌ها تلاش کنند.گسترش کامپیوتر‌های انتزاعیبا این که انتزاعی شدن کامپیوتر یکی از بزرگترین دستاورد‌های ما با به وجود اومدن سیستم عامل ها (ویندوز،‌ لینوکس، مک) بیشتر از قبل سرعت گرفت تا جایی که ما بر اساس نیازمون و با چند تا کلیک کامپیوتر شخصی خودمون رو بر اساس نیاز لحظه‌ای، در بیشتر اوقات با نصب یک یا چند برنامه بر اساس نیاز لحظه‌ای مون تنظیم میکردیم و از اون استفاده میکردیم. و این عالی بود تا این که با وزن دستگاه‌هامون مشکل پیدا کردیم و شروع کردیم به کوچیک کردنشون تا جایی که تبدیل به گوشی تلفن همراه شدند. تلفن همراه هایی که پا به پای کامپیوتر های امروزی دارن میان و در بیشتر اوقات نیازهای روزمره مارو برطرف می‌کنند.ورود به دنیای یادگیری ماشین‌ها!تا اینجای کار همه چی عالی بود ولی یک مشکل وجود داشت، ما برای هر کاری که می‌خواستیم انجام بدیم یا هر مشکلی که داشتیم و می‌خواستیم کامپیوتر حلش کنه، باید مشکل رو به کامپیوتر کامل و با جزئیات توی ۳ مرحله توضیح میدادیم:۱- چی قراره بهش بدیم (داده اولیه)۲-وظایف کامپیوتر چیه(مراحل پردازش داده ها)۳-چه چیزی رو به ما تحویل بده (خروجی داده).تعریف وظایف برای کامپیوتر نیازمند متخصص بود(و هنوز هم هست) و به هرکسی که توی این کار تخصص داره و میتونه کارها رو برای کامپیوتر تبدیل به دستور‌العمل کنه میگیم برنامه نویس. کار برنامه نویس دقیقا اینه که ورودی و خروجی رو بهش میدن و اون وظایف کامپیوتر رو تعریف می‌کنه. از طرفی هم همه مشکلات در دنیای کامپیوتر به صورت دستورالعمل قابل پیاده سازی نبودند و یا تعریف دستورالعمل مناسب متناسب با مشکل خیلی سخت بود. در این زمان ما وارد دنیای جدیدی از کامپیوترها شدیم، یادگیری ماشین. فرمول های ریاضی و آمار و الگو برداری از فرآیندهای درون مغز انسان به ما کمک کرد تا مشکلات سخت ویا غیر ممکن رو آسون کنیم و بیشتر وظیفه تعریف الگو جهت تولید خروجی مناسب رو به کامپیوتر واگذار کنیم.حرف آخراین خلاصه راهی بود که ما از ابتدای به وجود اومدن کامپیوتر ها انجام دادیم تا به کامپیوتر های انتزاعی امروز برسیم و بتونیم بسته به نیاز روزمره خودمون از کامپیوترها استفاده کنیم. البته هم هنوز خیلی فاصله داریم تا اون روزی که کامپیوتر ها به انتزاع انسان‌ها برسند و تست تورینگ رو پاس کنند!(معروف‌ترین تست سنجش هوشمندی کامپیوتر ها. اینجا میتونین بیشتر درموردش بخونین.) این سفر همچنان ادامه دارد!</description>
                <category>Soheil Rahmat</category>
                <author>Soheil Rahmat</author>
                <pubDate>Thu, 26 Mar 2020 01:20:07 +0430</pubDate>
            </item>
                    <item>
                <title>اجرای خودکار tmux زمان ورود به سرور با ssh</title>
                <link>https://virgool.io/@soheilrt314/%D8%A7%D8%AC%D8%B1%D8%A7%DB%8C-%D8%AE%D9%88%D8%AF%DA%A9%D8%A7%D8%B1-tmux-%D8%B2%D9%85%D8%A7%D9%86-%D9%88%D8%B1%D9%88%D8%AF-%D8%A8%D9%87-%D8%B3%D8%B1%D9%88%D8%B1-%D8%A8%D8%A7-ssh-rtjyt5h4zstr</link>
                <description>ابزار  ssh به ما اجازه دستری به ترمینال سرور رو میده ولی یک بدی که داره اینه که اگر زمانی که داریم با ssh روی سرور کار میکنم اینترنت قطع یا دچار اختلال بشه، اتصال ما با سرور قطع میشه و تمام کارهای سیو نشده روی سرور از بین میره. برای این مشکل یک ابزاری به وجود اومد به نام tmux که این مشکل رو حل میکنه و برامون session هارو ذخیره میکنه تا اگر دوباره خواستیم استفاده کنیم به راحتی قابل استفاده باشه و کاراهمون رو از جایی که ولشون کردیم از سر بگیریم.ولی یک مشکلی که هست توی سرور هر دفعه باید یک session جدید بسازیم یا به یک session از پیش ساخته شده وصل بشیم تا بتونیم کاراهمون رو بدون هیچ دغدغه‌ی دست دادن کارها بر اثر قطعی انجام بدیم. برای حل این مشکل و اجرای خودکار tmux دستورات زیر رو داخل فایل .bash_profile اضافه میکنیم.nano ~/.bash_profileif [ -z &amp;quot$TMUX&amp;quot  ]; then
     tmux attach -t default || tmux new -s default
fiنکته: اگر فایل وجود نداشت یکی خودتون بسازید.و در مرحله آخر تغییرات خودتون رو ذخیره کنید و دوباره واردسرور بشین تا از کارکردش مطمئن بشین.این مطلب ترجمه این مطلب می‌باشد.</description>
                <category>Soheil Rahmat</category>
                <author>Soheil Rahmat</author>
                <pubDate>Fri, 21 Feb 2020 01:24:03 +0330</pubDate>
            </item>
                    <item>
                <title>آفلاین کردن وبسایت با WGET</title>
                <link>https://virgool.io/@soheilrt314/%D8%A2%D9%81%D9%84%D8%A7%DB%8C%D9%86-%DA%A9%D8%B1%D8%AF%D9%86-%D9%88%D8%A8%D8%B3%D8%A7%DB%8C%D8%AA-%D8%A8%D8%A7-wget-lrmjt3xp2gr9</link>
                <description>هرکسی که چند وقت توی دنیای لینوکسی زندگی کرده یا با bash آشنایی داره،‌ احتمال خیلی زیاد با ابزار wget یکی دوباری کار کرده. اولی که من با wget آشنا شدم فکر می‌کردم که فقط ابزار دانلود ساده باشه و نه بیشتر تا این که با ویژگی‌های خوبش آشنا شدم.خب مسلما هرکسی توی حوزه وب حضور داشته باشه، نیاز داشته یک موقع هایی یک سایتی رو آفلاین داشته باشه (این موضوع رو به فال نیک میگیریم و تصور میکنیم که میخوایم سایت رو آفلاین داشته باشیم که اگر یک زمانی دستشون خورد اینترنت قطع شد بتونیم به محتوای سایت دسترسی داشته باشیم!)توی این زمینه خیلی ابزار معرفی شده مثل HTTrack ولی خوب چه نیازی هست به این ابزار ها تا زمانی که می‌تونیم با یک دستور ساده کل محتوای یک سایت همراه با صفحات داخلی اون سایت رو یکجا داشته باشیم؟کل کاری که قراره بکنیم اینه که یکی از دو دستور زیر رو انتخاب کنید و ادرس http://example.com رو با آدرس سایتی که قراره کپیش کنیم عوض کنیم!wget -mkEpnp http://example.org  با جزییاتwget --mirror --convert-links --adjust-extension --page-requisites --no-parent http://example.orgپی‌نوشت ۱: این دستور کل فایل های css و js رو دانلود میکنه و داخل فایل های html که از صفحات درست کرده ادرس این فایل ها رو به نسخه محلی تغییر میده!پی‌نوشت ۲: این ابزار برای کاربران ویندوزی به صورت پیش فرض در دسترس نیست ولی میتونین از اینجا دانلودش کنین! </description>
                <category>Soheil Rahmat</category>
                <author>Soheil Rahmat</author>
                <pubDate>Sun, 26 Jan 2020 21:32:43 +0330</pubDate>
            </item>
                    <item>
                <title>اضافه کردن قابلیت تم بندی به لاراول</title>
                <link>https://virgool.io/@soheilrt314/%D8%A7%D8%B6%D8%A7%D9%81%D9%87-%DA%A9%D8%B1%D8%AF%D9%86-%D9%82%D8%A7%D8%A8%D9%84%DB%8C%D8%AA-%D8%AA%D9%85-%D8%A8%D9%86%D8%AF%DB%8C-%D8%A8%D9%87-%D9%84%D8%A7%D8%B1%D8%A7%D9%88%D9%84-qd5uqvb7u1gs</link>
                <description>سلام. یادم میاد چند وقت پیش که با پکیج ماژولار (صفحه گیت‌هاب ماژول بندی لاراول) لاراول آشنا شدم انگار همه اون چیزی که لاراول کم بود رو یکجا پیدا کرده بودم. خیلی خوب بود که میتونستم برنامم رو کپسوله کنم و هر بخشی رو کامل از بخش دیگه جدا کنم. این روند ادامه داشت تا کم‌کم کمبود یا نبود قابلیت تم بندی توی برنامم دیگه داشت اذیت میکرد. شروع کردم به گشتن. یکم گشتم ولی اون چیزی که دوست داشتم پیدا نشد. (https://github.com/FaCuZ/laravel-theme): این بهترین پروژه اوپن سورسی بود که پیدا کردم ولی بازم به دلم نشست چون باید همه کنترلرهامو تغییر میدادم و این خارج از صبر و حوصله من بود.بلاخره نشستم به خوندن سورس لاراول اون چیزی که میخواستم رو پیدا کردم. توی کلاس ‌Application بود!!!ولی قبل از این که کلاس Application رو تغییر بدیم نیاز داریم که یک سری پیش نیاز رو درست کنیم که اول به اونا می‌پردازیم و بعدش میریم سراغ Application.ساخت فایل themes.jsonیک فایل به نام themes.json درون پوشه resources درست می‌کنیم. دلیل این که این فایل رو با پسوند json درست کردیم اینه که بعدا هم توی php ازش استفاده میکنیم هم توی webpack! فایل themes.json دارای دو متغیر اصلیه، یکی active که اسم تم فعال برنامه رو درون خودش نگه‌داری می‌کنه، یکی دیگه هم list که برامون لیستی از تم‌های موجود توی برنامه رو نگه‌داری میکنه که بعدا اگر خواستم بتونیم به لیست تم‌های موجود دسترسی پیداکنیم. (لیست برای من بیشتر یک جنبه تکمیلی داره و شما میتونین حذفش کنین!)نمونه فایل themes.json انتقال resourceها به درون پوشه تمخب از اونجایی که میخوایم برنامه رو تم بندی کنیم، بهتره همه فایل هایی که تم ها استفاده میکنن رو از هم جدا کنیم که این فایل شامل هر فایلی که داخل پوشه resource هست می‌شه. خب از اونجایی که تمام فایل‌های درون پوشه resource در حال حاضر مربوط به یک تم می‌شه رو به داخل اسم همون تم درون پوشه تم انتقال میدیم. (اینجا تمی که من استفاده میکنم اسمش metronicه و واسه همین از این به بعد از این اسم واسه پوشه تمم استفاده می‌کنم.) ساختار پوشه resources بعد از انتقال فایل ها به پوشه مربوط به تمخب پس اگر تا اینجای کار درست پیش رفته باشیم درون پوشه resource ما یک فایل themes.json وجود داره و چند تا پوشه به نام تم‌های برنامه.فایل های webpack.mix.js و package.jsonخب ما میدونیم که هر تمی یک سری فایل js و css مربوط به خودش رو داره و ما برای این که بتونیم تا حد امکان برنامه رو منعطف نگه داریم و برای تغییر تم به کمترین تغییرات توی برنامه نیاز داشته باشیم فایل های webpack.mix.js و package.json رو درون پوشه هر تم درست میکنیم.درون فایل webpack.mix.js تمام محتوای webpack قدیمی که درون پوشه اصلی برنامه قرار داشت رو قرار میدیم و به شکل زیر تغییر میدیمش.قالب اصلی webpack.mix هر تمکه برای من به صورت زیر شد.فایلی که من درون webpack.mix خودم استفاده می‌کنم! و برای فایل package.json همه پیش نیاز های برنامه رو قرار میدیم.(چون ما قبلا کلا یک تم داشتیم میتونیم فایل رو به صورت مستقیم از پوشه اصلی برنامه درون پوشه تم مورد نظرمون کپی می‌کنیم.)نیاز به بهبود: از اونجایی که من تجربه زیادی توی nodjs و webpack ندارم ممکنه برای تغییراتم راه بهتری هم باشه و برای package.json راهی پیدا نکردم که npm نیازمند‌ی‌های پروژه رو به صورت خودکار از داخل package.json خود تم بخونه و نصب کنه و وقتی میخوایم تم رو عوض کنیم باید package.json رو از داخل پوشه تم به پوشه اصلی کپی کنیم که بتونیم نیازمندی‌هاشو نصب کنیم! ( از دوستان کسی اگر تجربه ای توی این زمینه داره ممنون میشم راهنمایی کنه تا این مطلب تکمیل تر بشه.)فایل webpack.mix.js اصلیاز اونجایی که فایل webpack نیاز داره از درون پوشه خود تم اجرا بشه ما یک فایل webpack.mix.js درون پوشه اصلی پروژه درست میکنیم (همون فایل اصلی که موقع نصب لاراول بین فایل ها وجود داره)  و به صورت زیر تغییرش می‌دیم.تغییر فایل webpack اصلی برای اجرا فایل webpack تم.از الان به بعد هر موقع دستورهای npm run ... رو اجرا کنیم فایل webpack مخصوص به تم اجرا میشه و ما نیازی به تغییر webpack نداریم.خب تقریبا تمام کارهایی که پیش نیاز بود رو انجام دادیم. تا الان ما فایل های css و js برنامه جدا شدن و به صورت خودکار از داخل پوشه تم خونده و اجرا میشن، فقط میمونه فراخوانی view ها که زمانی که ما یک view رو فراخوانی میکنیم، برنامه به صورت خودکار از تم مورد نظر بخونه و اجرا کنه!شروع از فایل index.phppublic/index.phpخوب از اونجایی که برنامه ما همیشه از داخل پوشه public و فایل index.php اجرا میشه، در اولین مرحله فایل autoload کومپوزر بارگذاری میشه که وظیفه لود کردن کلاس ها و فایل ها رو به عهده میگیره! بعد از اون میاد فایل app.php از داخل پوشه bootstrap رو بارگذاری میکنه که از این فایل به ما یک شی از کلاس Illuminate\Foundation\Application برگشت داده میشه. بعدش ما یک شی از درخواست کاربر تحت کلاس Illuminate\Http\Request درست میکنیم و به کرنل ارسال میکنیم که برامون پردازشش کنه و جواب متناسب رو برگرودنه. بعدش درخواست رو به کاربر بر می‌گردونیم و تموم، کاربرمون جوابشو گرفته. دستکاری کلاس Illuminate\Foundation\Applicationخوب از اونجایی که کلاس Illuminate\Foundation\Application داخل فایل bootstrap/app.php  ساخته میشه، میریم یک سری به اونجا میزنیم و یک سری تغییراتی که میخوایم بدیم رو اونجا اعمال میکنیم!فایل bootstrap/app.phpخب همینطور که می‌بینیم توی این فایل یک شی از کلاس Application می‌سازه ادرس پوشه جاری رو به عنوان آدرس اصلی اجرایی برنامه ارسال میکنه (البته اگر داخل $_ENV متغیر APP_BASE_PATH تنظیم نشده باشه!).ما نیاز داریم که این که کلاس رو مطابق نیازمون یک‌سری تغییرات ریز بدیم که در ادامه با هم اون تغییرات رو اعمال میکنیم تا برنامه به صورت پویا تم رو فراخونی کنه.ساخت کلاس Application داخل پوشه Appخب از اونجایی که ما نمیتونیم داخل پوشه vendor تغییرات ایجاد کنیم و اگر تغییری ایجاد کنیم با هر بار نصب یا اپیدت composer همه تغییرات به فنا میره، یک کلاس به اسم Application داخل پوشه app درست میکنیم و اونو از کلاس Illuminate\Foundation\Application ، Extend میکنیم و تغییرات زیر رو درونش میدیم. فایل Application تغییر داده شده اگر یک زمانی به فایل نیاز داشتین میتونین اینجا به این فایل دسترسی داشته باشین.خب دیگه تقریبا تغییرات تمومه و فقط میمونه فایل bootstrap/app.php که به صورت زیر تغییرش میدیم.فایل bootstrap/app.phpخب دیگه تغییراتمون تموم شد و از الان به بعد به راحتی میتونیم از تم بندی سایتمون لذت ببریم.راستی شما داخل کنترلرهاتون هیچ تغییری نیاز ندارین بدین چون داخل هسته لاراول پوشه تم مورد نظرتون رو به عنوان پوشه resource معرفی کردین و فقط کافیه مثل قدیم از تابع view() استفاده کنین تا فایل های viewتون رو فراخونی کنین.از الان به بعد موقع تعویض تم شما فقط نیاز دارین کهاسم تم فعال داخل فایل themes.json رو تغییر بدین.فایل package.json نیازمندی های پروژه رو کپی کنین.نیازمندی های پروژه رو نصب کنید.فایل های css و js تم رو خروجی بگیرید.</description>
                <category>Soheil Rahmat</category>
                <author>Soheil Rahmat</author>
                <pubDate>Sun, 15 Dec 2019 12:30:44 +0330</pubDate>
            </item>
                    <item>
                <title>نگاهی به تعصبات برنامه نویسان نسبت به یک زبان یا فریمورک!</title>
                <link>https://virgool.io/@soheilrt314/%D9%86%DA%AF%D8%A7%D9%87%DB%8C-%D8%A8%D9%87-%D8%AA%D8%B9%D8%B5%D8%A8%D8%A7%D8%AA-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%D8%A7%D9%86-%D9%86%D8%B3%D8%A8%D8%AA-%D8%A8%D9%87-%DB%8C%DA%A9-%D8%B2%D8%A8%D8%A7%D9%86-%DB%8C%D8%A7-%D9%81%D8%B1%DB%8C%D9%85%D9%88%D8%B1%DA%A9-d6vl1wg5bxbf</link>
                <description>سلام. چند وقت بود که می‌دیدم که همه دارن در مورد تکنولوژی و بهتری هر کدوم نسبت به یکی دیگه با هم صحبت میکنن و مزایای هر کدوم رو به رخ هم میکشن. واسه همین امروز میخوام در مورد همین موضوع صخبت کنم.قبل از این که صحبتم رو شروع کنم میخوام یک سوال بپرسم! سیب بهتره یا گلابی؟خب راستش خیلی وقتا می‌بینم خیلیا نسبت به زبان‌های برنامه نویسی نسبت به هم گارد میگیرن یا پز یک زبون رو به کسی میدن. راستش همین اول خیالتون رو راحت کنم: هر چیزی رو بهر کاری ساختن!این توی دنیای آی‌تی هم صدق میکنه! ینی چی؟ با این همه پیشرفت تکنولوژی هنوز هستن کسایی که دوست دارن گوشی دکمه دار داشته باشن و خیلی هم امکانات اون دستگاه براشون رضایت بخشه! وقتی هم ازشون میپرسی اکثرشون جواب‌های مشابه‌ای دارن: میخوام چی کار؟ یا همین بسه!آره واقعا بعضی اوقات همین بسه، حتی توی دنیای برنامه نویسی! ینی این که بعضی اوقات یک زبان ساده سمت سرور بدون هیچ امکانات برنامه نویسی که در حال حاضر داره ارائه میشه مثل برنامه نویسی همزمان nodejs برامون کافیه! واقعا بیایم با خودمون صادق باشیم! چند بار پروژه بهمون میخوره که آگر برنامه نویسی همزمان نداشته باشیم کارمون لنگ میمونه؟ یا چند نفرمون هاستی داریم که میزان کاربراش اینقدر بالا باشه که رسپانس ۱۰ میلی ثانیه توی بوت برنامه اینقدر تاثیر گذار باشه که نیازی باشه بریم سمت زبون های قوی مثل گولنگ یا راست! درسته این زبون ها فوق‌العادن و خیلی امکاناتی که ارائه میدن نسبت به تکنولوژی ها و زبون های دیگه بهبود یافته اند ولی واقعا چند بار از خودمون پرسیدیم این امکاناتو میخوایم چی کار؟راستش من احساس میکنم همین زبانهایی که داریم استفاده می کنیم یکم به اعماقشون سفر کنیم نظرمون نسبت به خیلی چیزا عوض میشه. مثلا من خودم تا قبل از این مجبور بشم واسه یک پروژه متن باز که روی گیت هاب گیر آورده بودم رو تغییرات بدم نمی‌دونستم با زبون php هم میتونیم توی رفتار کلاس ها تغییر ایجاد کنیم! تا وقتی در مورد  autoloader کومپوزر یا استاندارد psr-4  چیزی نمیدونستم قدرت رو درک نکرده بودم! وقتی هم تجربه کار با python رو کسب کردم فهمیدم بازخورد سریع گرفتن از کار ینی چی!وقتی ساختار مندی کدهای c# رو دیدم لذت بردم.....برنامه های نوشته شده با c رو دیدم به عظمت سرعت و پردازش سر تعظیم فرود آوردم! و... هر تکنولوژی و زبونی ویژگیهای خودشو داره و نمیشه اینو انکار کرد و بحث هم سر همینه، سیب? و گلابی?! تمام حرفم توی این نوشته به خاطر این بود که به این موضوع برسم که هر چیزی واسه کاری خوبه! من هیچ موقع نمیتونم خاصیت های سیب و انکار کنم و بگم فقط گلابی مفیده چون گلابی دوست دارم! هردوشون مفیدن و هر کسی هم بسته به سلیقش یک میوه ای رو دوست داره و ما نمیتونیم ازش خورده بگیریم یا میوه مورد علاقمون رو پیشش پز بدیم! راستی تا یادم نرفته: سلیقه شما مختص شماست و اون رو توی حلق بقیه نکنین. مرسی.پ.ن: بنده به دلیل این که تجربه کم و گذری که از زبان هایی مثل c#, python داشتم تنها تونستم چند مثال سطحی بزنم و نتونستم وارد جزییات بشم و بیشتر توضیحاتم معطوف به زبان php شد فقط به این دلیل که تجربم توی این زبان بیشتره و مدت زمان بیشتری نسبت به زبان های دیکه با این زبان درگیر بودم!</description>
                <category>Soheil Rahmat</category>
                <author>Soheil Rahmat</author>
                <pubDate>Tue, 10 Dec 2019 00:53:16 +0330</pubDate>
            </item>
                    <item>
                <title>نگهداری تغییرات فایل در گیت - تغییرات اتمیک!</title>
                <link>https://virgool.io/@soheilrt314/%D9%86%DA%AF%D9%87-%D8%AF%D8%A7%D8%B1%DB%8C-%D9%81%D8%A7%DB%8C%D9%84-%D8%AA%D8%BA%DB%8C%DB%8C%D8%B1%D8%A7%D8%AA-%D9%81%D8%A7%DB%8C%D9%84-%D8%AF%D8%B1-%DA%AF%DB%8C%D8%AA-moaoqrhgenyf</link>
                <description>امروز میخوام براتون از تجربه ۱ سال و خورده ای که توی یک شرکت استارت‌آپ داشتم بگم. خیلی نمیخوام در مورد همه جوانب صحبت کنم بلکه میخوام مستقیم برم سر اصل مطلب و اونم ورژن کنترلی به اسم گیت (GIT).  اگر در مورد ورژن گیت اطلاعاتی ندارین اینجا میتونین توضیحات خیلی خوبی در موردش بخونین.بزارین یکم مقدمه چینی کنم. خب من به عنوان اولین برنامه نویس این پروژه استخدام شدم و از اونجایی که تا مدتی داشتم تنهایی روی این پروژه کار می‌کردم و کسی هم نبود روی کارم مدیریت کنه منم هرجوری دلم میخواست داشتم توی پروژه مانور میدادم و از هر ابزاری دوست داشتم استفاده کردم که بعضی جاها به گریه کردن افتادم به خاطر مانورام ولی با یک هفته مرتب سازی فایل های پروژه بخیر گذشت.بعد از مرتب سازی پروژه به خاطر این که خیالم جمع بشه که گندی بالا نیومده و فایل ها و بخش های پیاده سازی شده مثل قبل کار میکنن یک پروژه جدید روی گیت‌هاب ساختم و پروژه جدیده رو کنار پروژه قبلیه اونجا آپلود کردم.(یادش بخیر ما هم میتونستیم پروژه خصوصی روی گیت‌هاب داشته باشیم)یک روز دیدم خیلی تاریخچه گیت بهم ریخته داره میشه و همه کامیت ها و ادغام ها دارن قاطی میشن و برگردودن یک سری از چیزا دیگه تقریبا غیر ممکنه. از طرفی هم همش میدیدم که پروژه های اوپن سورس خفنی که روی گیت هابه و چند هزار نفر دارن روش کار میکنن همیشه تاریخچه گیت تمیزی داره و این اصلا برام قابل درک نبود. مطمعن بودم یک جای کارم داره میلنگه (که همینطور هم بود).اینجوری که پیش میرفتم همیشه به یک چیزی مثل شکل زیر میرسیدم آخرش!تاریخچه شلوغ گیتمطمعنن شما هم مثل من چند باری با یک چیزی مثل شکل بالا مواجه شدین و چند بار سعی کردین متوجه بشین چی شده! واسه همین شروع کردم گوگل کردن تا با واژه کامیت اتمیک (Atomic Commit) آشنا شدم و رفتم دنبالش . دقیقا همون چیزی بود که دنبالش بودم. بهتره شروع کنیم.معنی اتمیک (Atomic): Atomic: Forming a single irreducible unit or component in a larger systemبه زبون خودمونی میگه یک قسمت از یک سیستم رو اینقدر کوچیک کنیم که از اون کوچکتر نشه!خب اولش منطقی بود و توی گیت هم همین کارو میکنیم و اینقدر کامیت رو کوچیک میکنم تا به کوچک ترین کامیت معنی دار ممکنه برسه (ممکنه این کامیت کوچک شامل چند تا فایل مرتبط به هم نیز بشه).شاید یک سوال پیش بیاد که خب این حجم از کامیت بازم اعصاب خورد کنه. به اونم میرسیم!خوب داشتم توی این سایت چرخی میزدم. مثال خیلی قشنگی زده بود و منم بهتر از این بلد نبودم مثال بزنم.بیاین فکر کنیم یکی داره رو پروژه کار میکنه و بخش ظاهری سایت دستشه و یک کامیت میزنه مثل شکل زیرAdd FrontEnd راستش این خیلی وحشتناکه مخصوصا برای کسی که میخوای کد رو بازبینی کنه. حالا برای این که مشکل حل بشه از دو تا چیز کمک میگیریم: شاخه (branch) و کامیت اتمیکحالا بیایم یک شاخه (Branch) جدید به اسم frontEnd بسازیم و تغییرات رو اونجا اضافه کنیم. مثل زیر:Create HTML for formStyle formAdd HTML5 validationFix unrelated JS bugAdd ajax submit to form with mock server results from PHPAdd JS validation to formSend form results via emailLog form results to databaseStyle form validation and success/error messagesخب الان دیگه خیلی راحت تره برای من اگر جایی موقع اضافه کردن یک ویژگی جدید به سیستم، خراب کاری کردم پیداش کنم و به راحتی میتونم اون کامیت رو برگردونم (revert). مورد بعدی اینه که برای هر کامیت شما فضای مخصوص به خودش رو دارین تا به غیر از متنی که برای کامیت انتخاب میکنین یک سری توضیحات در مورد کارهای انجام شده توی اون کامیت هم بنویسین. خوب این به شما این قدر رو میده که در مورد هر کامیت اتمی که دارین یک فضای مخصوص داشته باشین که در مورد اون کار هایی که توی اون کامیت انجام دادین یک دل سیر توضیح مفید بدین بدون این که نگران باشین با جای دیگه اشتباه گرفته بشه.بعد از اینکه این بخش ها گذشت اگر شما زمانی در آینده نه چندان دور خواستین ببینین که برای چی اون کد رو اونجا نوشتین و چه استفاده ای داشته خیلی راحت میتونید تاریخچه اون فایل توی گیت رو جست و جو کنید و شجره نامشو در بیارین. البته این بیشتر به درد مدیر پروژه و بالا دستیا میخوره که میخوان کد شمار رو برسی کنن چون هر برنامه نویسی میدونه برای چی کدی رو نوشته (معمولا).خب تا اینجا که همه چی مثل قبله فقط با این تفاوت که نه تنها تاریخچمون بهتر نشد بلکه داره شلوغ تر هم میشه. من هم اول همین حس رو داشتم و اصلا درک نمیکردم تا این که یک مفهوم دیگه ای آشنا شدم به اسم تاریخچه خطی.این تاریخچه اصل و اصولش بر این مبناست که هر شاخه باید بعد از ادغام شاخه قبل ایجاد شده باشه و توی گیت ما نباید تاریخچه ای داشته باشیم که از یک کامیت چند تا شاخه خارج شده باشه و بعد جلو تر به شاخه ادغام شده باشند. همینطور که توی عکس بالا مشاهده میکنین، گیت سمت چپ میشه تاریخچه غیر خطی و سمت راست میشه خطی. خب تا اینجا اوکیه ولی اولش ذهن آدم اینجوری درگیر میشه که من چطور میتونم تاریخچه خطی داشته باشم وقتی چند نفر همزمان دارن روی چند تا ویژگی به صورت جدا کار میکنن. برای منم اولش نمیشد تا اینکه با rebase آشنا شدم. من بهش میگم معجزه تمیز کننده. Rebaseخوب از اونجایی که گیت به ما یک ابزاری میده که پروژه و تغییرات رو به صورت یک گراف مدیریت کنیم. و زمانی که ما یک شاخه جدید ایجاد میکنیم. پدر اولین کامیت ما توی شاخه یکی از کامیت های شاخه پدره. rebase اومده که به ما این لطف رو بکنه و برای ما جای پدر شاخمون رو عوض کنه.خب همونجور که توی عکس مشخصه، ابزار rebase میاد و برای ما این کار رو انجام میده که پدر شاخمون رو اخرین کامین شاخه پدر قرار میده و این به ما این قدرت رو میده که بتونیم تاریخچه ای خطی داشته باشیم. از طرفی هم میتونیم آخرین تغییراتی که روی کد اومده رو هم داشته باشیم و با کدی که نوشتیم تست کنیم و ببینیم آیا مشکلی وجود داره یا نه. فقط یادتون باشه اگر شاختون رو از قبل روی منبع فرستادین الان باید force push  کنید به دلیل این که اولین کامیت شاختون تغییرات داشته و با منبع یکی نیست.خب تا اینجا همه چی عالی شد ولی هنوز یک چیز ممکنه مشکل داشته باشه و اونم طولانی بودن لیست کامیت هایی که توی یک شاخه انجام شده. در اینجا هم ابزاری به من کمک کرد به اسم squash.Squashاین ابزار میاد برای ما این ویژگی رو فراهم میکنه که کامیت هایی که ما مشخص کردیم رو برامون یکی میکنه. دیگه چی از این بهتر، هم خطی هم تک کامیت. اینجوری هم تاریخچه خطیه و هم کوچیک و خلاصه. حالا سوالی که پیش میاد اینه که اون همه توضیحی که واسه کامیت ها نوشتیم پس چی؟ خب همشون پاک میشن و اشکالی هم نداره به دلیل این که کد شما داره وارد منبع میشه و معمولا توضیحات  داخل هر کامیت تا زمانی مورد استفاده قرار میگیرن که هنوز کد وارد منبع نشده (این مساله ممکنه توی جاهای مختلف فرق کنه و بعضی جاها از توضیحات به عنوان مستند استفاده کنند.). بعد از این که کد وارد منبع شد یعنی هیچ مشکلی نداشته و همه تست ها انجام شده و تمام.حالا شما هم میتونید مثل ما با یک ترفند کوچیک ابتدا تمام کامیت های شاختون رو squash کنین و بعد از اون شاخه پدر رو هم روی این شاخه rebase کنین. اینطوری تغییراتتون به آخر شاخه master اضافه میشه و هر دو شاختون به یک وضعیت یکسان میرسن و به راحتی میتونین شاخه ای داشتین روش کار میکردین رو پاک کنین چون همه تغییرات این شاخه رو الان شاخه پدر هم داره و تغییرات این شاخه به اخر شاخه پدر اضافه شده. تاریخچه خطیاینجوری شد که ما تونستیم یک تاریخچه مرتب داشته باشیم.مرورکلیکامیت اتمیک رو برسی کردیم و گفتم به تغییرات کد خوانایی میده و راحت تر قابل دنبال کردنه.دلیل استفاده از کامیت اتمیک رو برسی کردم ودیدیم چقدر برای اونایی که کد دیگران رو برسی میکنند میتونه مفید باشه.از rebase جهت تغییر پدر شاخه ای که داریم روش کار میکنیم استفاده کردیم.از sqash جهت یکی کردن کامیت ها بعد از اتمام کار استفاده کردیم که تاریخچه خلاصه تری داشته باشیم.دوباره از rebase استفاده کردیم که تغییراتمون رو بفرستیم روی شاخه پدر.</description>
                <category>Soheil Rahmat</category>
                <author>Soheil Rahmat</author>
                <pubDate>Wed, 11 Sep 2019 22:44:04 +0430</pubDate>
            </item>
            </channel>
</rss>