• نوتیفیکیشن های لاراول ۵٫۳

    جدیدا توی چیتاسافت مجبور شدم از لاراول ۵ دل بکنم و سوییچ کنم روی لاراول ۵٫۳.  یکی از امکانات جالبی که تو این ورژن به لاراول اضافه شده notification ها هستند و میخوام یکم در موردشون حرف بزنم. لاراول قبلا ارسال ایمیل رو با سویفت میلر ممکن کرده بود و با درایورهای مختلف میتونستیم ایمیل ارسال کنیم.

    تو نوتیفیکیشن ها اوضاع بهتر هم میشه و میتونیم نوتیفیکیشن رو علاوه بر ایمیل بصورت SMS  و حتی بصورت نوتیفیکیشن slack و تلگرام و… هم بفرستیم که لیستشو میتونید تو سایت  laravel-notification-channels ببینید. برای شروع از کامند آشنای make استفاده میکنیم :

    php artisan make:notification Pay
    

    یه کلاس Pay توی Notificatios ساخنه میشه که از کلاس Notification مشتق شده… یه متد به نام via توش وجود داره بصورت پیشفرض که کانال های ارسال اعلان(نوتیفیکیشن) رو توش مشخص میکنیم. و یک سری متد دیگه که اعلان شما رو پردازش میکنن تا با کانال مورد نظر بتونن نوتیف رو ارسال کنن… مثل توابع toMail و…

    با دو روش میتونید ارسال کنید نوتیف رو :

    1. استفاده از Notifiable Trait
    2. استفاده از فساد Notification

     

    استفاده از Notifiable Trait

    این trait بصورت پیشفرض توی مدل User وجود داره و معمولا برای ارسال نوتیفیکیشن به یک یوزر استفاده میشه… یک متد notify داره که یک ورودی از نوع Notification میگیره. به این صورت مثلا :

    use App\Notifications\Pay;
    
    $user->notify(new Pay($invoice));
    
    استفاده از فساد Notification

    پیشنهاد میشه از این روش استفاده کنید. چون میتونید به چند کاربر و مثلا به یک کالکشن هم اعلان بفرستید خیلی شیک :

    Notification::send($users, new Pay($invoice));

    میتونید در هر ارسال به پراپرتی notifiable دسترسی داشته باشید و مثلا مشخص کنید که اس ام اس برای این یوزر فعال هست و شماره موبایلش تایید شده و بعد اقدام به ارسال اس ام اس به این یوزر کنید.

  • nodejs در مقابل php

    اخیرا مجبور شدم روی یک پروژه چت آنلاین کار کنم که یک موتور چت داره و یک سری ریکوئست رو میگیره و جواب مناسب رو میده…  با php و فریمورک لاراول (♥) و وب سرور آپاچی شروع کردم  برای هرچه بهینه تر شدن موتور از روش comet استفاده کردم که یک درخواست رو تا دریافت درخواست بعدی به تاخیر میندازه و خلاصه به روشی خلاقانه باعث پایین اومدن حجم درخواست ها به سرور و در عین حال real time شدن کامل برنامه میشه. واضحه که با این حجم read و write که توی همچین سیستمی وجود داره، mysql گزینه مناسبی برای مدیریت داده ها نیست و بخاطر همین از همون اول از mongodb بعنوان یک سیستم مدیریت پایگاه داده noSQL استفاده کردم…

    تا اینجا یه موتور چت (chat engine) با لاراول و مانگو دارم… برای تست ، ۲۰ کاربر با سشن های مختلف روش فعال کردم که هر کدوم دارن چت میکنن و بیشتره تایم رو هم گوش میکنن و منتظر دریافت پیام طرف مقابلن… با ۲۰ تا کاربر با اینکه منابع نسبتا بالایی از سرور استفاده میشد ولی سرعت جواب ها قابل قبول بود… وقتی تعداد کلاینت های سیستم پایین هست بالطبع تعداد درخواست هایی که برای سیستم میاد هم پایین خواهد بود و مشکلی پیش نمیاد… اما وقتی تعداد کلاینت ها رو ۱۰۰ برابر کردم… بووووم… سیستم ترکید☺

    اینجا بود که به ضعیف بودن php و یه وب سرور مثل آپاچی ایمان آوردم… یه چرخی تو اینترنت زدم و مقاله هایی رو خوندم که دقیقا حرف الان من رو تایید میکردن… کم کم با پدیده ای به نام nodejs آشنا شدم… syntax و داکیومنت خوبش باعث شد که سمتش برم و موتور چت رو ببرم روی node…

    گرچه تحقبق روی پروژه انقد طولانی شد که شرکت، پروژه رو شکست خورده تلقی کرد و رفتم روی پروژه ی بعدی… ولی به شما پیشنهاد میکنم اشتباه من رو تکرار نکنید و اگه سیستم مشابهی رو برای کارتون نیاز دارید به node بعنوان یک گزینه خوب نگاه کنید… یه مقایسه قشنگه node و php رو هم توی این لینک ببینید. موفق باشید 🙂

     

  • حل مشکل Warning: putenv() has been… در laravel

    Warning: putenv() has been disabled for security reasons in /home/yoursite/public_html/vendor/vlucas/phpdotenv/src/Dotenv.php on line 86

    اگه ورژن php هاستتون زیر ۵٫۶ باشه این پیام نمایش داده میشه… برای حل این مشکل از قسمت select php version  هاستتون اقدام کنید و یا با پشتیبانی هاستتون تماس بگیرید

  • کارکردن با pivot table ها یا جداول محور در laravel

    مجددا باید بگم که من همه کارام رو توی لاراول ۵٫۰٫۰ انجام میدم 🙂

    امروز میخوام در مورد یک چیز خیلی مهم توی لاراول صحبت کنم و اونم نحوه ی ارتباط برقرار کردن چند به چند بین دو جدول در لاراول ۵ هست.

    یک مثال کاملا واقعی در مورد رابطه های چند به چند در لاراول

    توی داکیومنت رسمی لاراول مثالی که واسه روابط چند به چند اومده ، رابطه ی role و user هست که یک یوزر میتونه متعلق به چند نقش باشه و برعکس، یعنی یک نقش مثل ادمین هم میتونه متعلق به چند کاربر باشه. من یه مثال ملموس تر براتون میزنم : رابطه ی محصولات و فروشگاهها رو در نظر بگیرید. شما نیاز دارید که بدونید مثلا گوشی فلان رو چه فروشگاههایی دارن و همچنین نیاز دارید بدونید که فلان فروشگاه چه گوشیهایی داره.

    $Shop->products();//for grab products of a shop...
    $Product->shops();//and reverse...

    جدول های مورد نظر میتونن به شکل زیر باشن :

    shops
    – id
    – name
    products
    – id
    – name
    product_shop
    – product_id
    – shop_id

    برای اینکه بین ذو جدول رابطه چند به چند بوجود بیاد ، بهترین راه استفاده از یک جدول میانی هست که ارتباط بین دو جدول رو تشکیل بده. این جدول حداقل باید دو فیلد داشته باشه ، که آیدی دو ریکورد از دو جدول رو به هم نسبت بده.

    برای اینکه این جدول رو درست کنیم میتونیم از مایگریشن های خود لاراول استفاده کنیم. مثلا در یک وبلاگ، پست ها و تگ ها دارای رابطه چند به چند هستند که جدول post_tag رو میتونیم به صورت زیر بسازیم :

    Schema::create('post_tag', function(Blueprint $table)
    {
    	$table->integer('post_id')->unsigned();
    	$table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');
    
    	$table->integer('tag_id')->unsigned();
    	$table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade');
    });

    جدول  post_tag رو اصطلاحا بهش میگن pivot table. نام جدول pivot باید بصورت first_second باشه که first نام جدول اول و second نام جدول دوم هست. ترتیب هم باید بر اساس حروف الفبا باشه.  بصورت پیشفرض جدول pivot دوتا فیلد داره : post_id و tag_id که میتونید فیلد های بیشتری هم بهش اضافه کنید . مثلا برای اینکه شما یک پلن رو به یک کاربر اختصاص بدید میتونید تاریخ پایان پلن رو هم توی جدول میانی یا همون pivot ذخیره کنید. برای بدست آوردن مقدار فیلد های دیگه هم میتونید از این روش استفاده کنید :

    public function products()
    {
        return $this->belongsToMany('App\Products')
        	->withPivot('products_amount', 'price')
        	->withTimestamps();
    }
    
  • حل مشکل invalid default value for created_at در لاراول

    در ادامه طرح سوالات ابتدایی لاراول ، این پست رو منتشر میکنم 🙂

    توی اولین مرحله که میخواید مایگریشن های لاراولیتونو ران کنید به این اررور احتمال داره بخورید :

     [Illuminate\Database\QueryException]
      SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'created_at' (SQL: create table `
      users` (`id` int unsigned not null auto_increment primary key, `name` varchar(255) not null, `email` varchar(255) n
      ot null, `password` varchar(60) not null, `remember_token` varchar(100) null, `created_at` timestamp default 0 not
      null, `updated_at` timestamp default 0 not null) default character set utf8 collate utf8_unicode_ci)

    این خطا بخاطر اینه که مای اس کیو ال شما مقدار صفر رو بعنوان مقدار پیشفرض تاریخ قبول نمیکنه . احتمالا شما NO_ZERO_DATE رو توی تنظیمات mysqlتون فعال کردید… اگه با ومپ کار میکنید به پوشه ی (مثلا) C:\wamp64\bin\mysql\mysql5.7.9  برید و فایل my.ini  رو باز کنید و مقادیر NO_ZERO_DATE,NO_ZERO_IN_DATE, رو سرچ بزنید و حذف کنید و mysql رو ریستارت کنید

    الان همه چی حله… php artisan migrate  رو برای تست ران کنید.

  • آموزش نصب Illuminate/HTML در لاراول ۵

    چند روزیه تو یه گروه تلگرامی لاراول عضوم ، انقد سوالای سطح پایین پرسیده میشه که قلبت درد میگیره… تصمیم گرفتم هر از چندگاهی در مورد مقدمات لاراول حرف بزنم و خب اولین چیزی که ملت درگیرشن همین Illuminate/HTML هست… توی لاراول ۴ هلپر  HTML بصورت پیشفرض وجود داره و توی لاراول ۵ برداشته شده… خوشبختانه HTML بصورت یه پکیج جدا وجود داره و میتونید ازش استفاده کنید براحتی…

    برای نصب Illuminate/HTML ابتدا کد زیر رو توی روت پروژه ران کنید :

    composer require "illuminate/html":"5.0.*"

    قدم دوم اینه که /config/app.php  رو باز کنید و خطهای زیر رو اضافه کنید :

    'providers' => [
    	...
     
    	'Illuminate\Html\HtmlServiceProvider',
    ],
     
    'aliases' => [
     
    	...
     
    	'Form'=> 'Illuminate\Html\FormFacade', 
    	'Html'=> 'Illuminate\Html\HtmlFacade',
    ],

    الان همه چی حله… برای تست هم میتونید از ابزار tinker استفاده کنید

    php artisan tinker
    > Form::text('foo')
    "<input name=\"foo\" type=\"text\">"

    موفق باشید 🙂

    الان دیگه html از هسته لاراول جدا شده و بصورت پکیج جدا از illuminate در laravelcollective.com توسعه داده میشه… برای نصبش توی composer.json کد زیر رو اضافه کنید :

     

  • مفهموم و کاربرد Facade در لاراول

    با سلام مجدد ، حتما اگه با لاراول کار کرده باشید، بارها اسم facade به گوشتون خورده. اما facade واقعا چیه؟ طبق گفته ی سایت خود لاراول “فساد یک ظاهر استاتیک رو برای کلاسهایی که در کانتینر وجود دارن ایجاد میکنه”. در مورد IOC container قبلا توی این پست صحبت کردم . حتما در مورد کلاسهای استاتیک هم اطلاع دارید دیگه و قبلا در این باره هم اینجا حرف زدم.

    لاراول خودش کلی فساد داره که شما بدون اینکه شاید متوجه بشید دارید ازشون استفاده میکنید. مثلا همین Session یا Form که استفاده میکنید همگی فساد هستند. لیست کامل فسادهای لاراول رو میتونید اینجا ببینید. از اونجایی که من خودم با لاراول ۵ کار میکنم لینک هایی که به داکیومنت لاراول میدم هم به ورژن ۵ هست و شما میتونید اون بالا سمت راست، روی ورژن دلخواهتون سوئیچ کنید که البته توی این مورد تفاوت خاصی ندارن. شما میتونید توی لاراول فساد دلخواهتون رو تعریف و استفاده کنید و بعضی جاها کارتون رو خیلی جلو میندازه و البته نشان از حرفه ای بودن شما هم هست این کار. قبل از اینکه بپردازید به ساخت فساد برید و در مورد کانتینر لاراول اطلاعات کامل رو بدست بیارید.

    ساخت یک فساد – facade دلخواه در لاراول

    هر فسادی که شما میسازید توی لاراول، باید از کلاس پایه ی Facade مشتق شده باشن و حتما باید متد getFacadeAccessor  رو ایمپلیمنت کنید. توی این متد شما به لاراول میگید که وقتی این فساد رو صدا زدم، کدوم کلاس که توی کانتینر هست رو لود کنه. کلاس پایه ی Facade  از متد جادویی __callStatic()  برای این کار استفاده میکنه. بعد از ساخت یک فساد به راحتی میتونید به روش زیر به فساد متد مورد نظرتون دسترسی پیدا کنید :

    $value = Cache::get('key');

    برای ساخت یک فساد سه تا کار رو باید انجام بدید:

    اولین کاری که باید بکنید اینه که کلاس مورد نظرتون رو توی سرویس کانتینر بایند کنید. همونطور که گفتم قبلا در مورد این موضوع مطلبی نوشتم و میتونید توی خود داکیومنت لاراول هم در بارش بخونید. فرض کنید که یه کلاس مثل کلاس زیر رو داریم و میخوایم بصورت استاتیک و فسادگونه! ازش استفاده کنیم:

    namespace PaymentGateway;
    
    class Payment {
    
        public function process()
        {
            //
        }
    
    }

    قدم اول این بود که این کلاس رو در کانتینر بایند کنیم، بصورت زیر :

    App::bind('payment', function()
    {
        return new \PaymentGateway\Payment;
    });

    بهترین جا هم برای این کار همونطور که میدونید متد register  یک service provider هست که من اسمش رو میذارم PaymentServiceProvider.

    قدم دوم : حالا میتونید کلاس فسادتون رو بسازید.

    use Illuminate\Support\Facades\Facade;
    
    class Payment extends Facade {
    
        protected static function getFacadeAccessor() { return 'payment'; }
    
    }

    قدم سوم اینه که فساد رو به لاراول معرفی کنید. برای این کار باید توی config/app.php  یک نام اختصاری برای فساد خودتون بذارید :

    'Payment'       => 'Illuminate\Support\Facades\Payment',

    حالا به راحتی میتونید به روش آشنای زیر به متد های کلاستون دسترسی داشته باشید:

    Payment::process();

    مزایای استفاده از Facade بجای کلاس معمولی

    استفاده از فساد ها چند تا دلیل داره. اولی اینه که ظاهر ساده ای به شما میدن. ینی شما دیگه لازم نیست namespace های پیچیده رو بخاطر بسپارید. این مهمه ولی تنها دلیل استفاده از فساد نیست. دلیل بعدی که به نظرم مهمتر هم هست Testable بودن کد هایی هست که با فساد نوشته شدن. ینی چی حالا؟ ینی اینکه شما فساد ها رو خیلی راحت میتونید mock کنید و بگید که اگر این فساد رو صدا زدم این خروجی برگرده. چیزی که در کلاس معمولی بدون استفاده از interface قابل پیاده سازی نیست. مثال میزنم که دقیقتر بررسی کنیم. در مثالی که زدم از قابلیت automatic facade در لاراول استفاده کردم که در یه پست دیگه در موردش صحبت کردم. یه فولدر در دایرکتوری app\Base درست کردم که فایلهای زیر رو داخلش قرار دادم. ابتدا فایل Product.php بصورت زیر تعریف شده که همونطور که میبینید فضای نام Publisher پیشوند Facades داره که اون رو بصورت اتوماتیک فساد تبدیل کرده و ما میتونیم بصورت استاتیک به اون دسترسی داشته باشیم.

    <?php
    
    namespace App\Base;
    
    use Facades\App\Base\Publisher;
    
    class Product {
        public $name;
        public function __construct($name)
        {
            $this->name = $name;
        }
        public function publish() {
            Publisher::publish($this);
        }
    }

    و publisher.php که یک کلاس معمولی در PHP هست:

    <?php
    
    namespace App\Base;
    
    class Publisher
    {
        public function publish($product)
        {
            echo "Publishing the {$product->name}...";
            return true;
        }
    }

    میدونیم که consumer خیلی راحت میتونه با ویژگی automatic facade از این کلاس Publisher مثل یک فساد استفاده کنه:

    <?php
    
    use App\Base\Product;
    use Illuminate\Support\Facades\Route;
    
    Route::get('/', function () {
        $product = new Product("Book");
        $product->publish();
    });

    من کد بالا رو در فایل web.php نوشتم. برای اینکه کد رو تست کنیم ابتدا کامند زیر رو بزنید که تست بسازه واستون:

    php artisan make:test ProductTest --unit 

    و تست رو اینجوری کامل کنید:

    <?php
    
    namespace Tests\Unit;
    
    use App\Base\Product;
    use Tests\TestCase;
    use Facades\App\Base\Publisher;
    
    class ProductTest extends TestCase
    {
        /** @test */
        public function it_can_publish_a_post() {
            $product = new Product("Book");
            Publisher::shouldReceive('publish')
                ->with($product)
                ->andReturn(true);
    
            $this->assertTrue($product->publish());
        }
    }

    همونطور که میبینید بدون اینکه نیاز باشه که کلاس پابلیشر ران بشه کد بالا چیزی که ما گفتیم بهش رو در اختیارمون قرار داده. در واقع DI یا همون Dependency Injection اومد که ما بتونیم نیازمندی ها رو از بیرون به کلاسها پاس بدیم که بتونیم بصورت testable کد بزنیم ولی میبینید که فساد ها در کنار داشتن فابلیت testablility به ما سادگی هم میدن و چیز خوبی هستن در مجموع. خروجی کد بالا چیزی مثل این خواهد بود:

     PASS  Tests\Unit\ProductTest
      ✓ it can publish a post
    
      Tests:  1 passed
      Time:   0.06s

    امیدوارم کمکی کرده باشه بهتون این پست. موفق باشید.

  • پراپرتی و متدهای استاتیک در php

    قبل از اینکه بخوام در مورد facade  در لاراول صحبت کنم باید اطلاعات کلی در مورد توابع یا متدهای استاتیک php داشته باشید. متدهای استاتیک متدهایی از یک کلاس هستند که بدون نمونه گیری از کلاس و بصورت استاتیک قابل دسترسی هستند. یعنی بدون داشتن شئ از کلاس ، میتونیم از این نوع متدها استفاده کنیم.

    قبل از مثال در مورد متدهای استاتیک میخوام کمی در مورد متغیرها یا پراپرتی های استاتیک صحبت کنم. یک پراپرتی استاتیک بدون استفاده از $this  و به راحتی با استفاده از ::  قابل دسترسی هست. همچنین میتونید یک متغیر استاتیک رو با استفاده از کلمه کلیدی static  تعریف کنید. به مثال زیر توجه کنید :

    class test
    {
    public static $a;//Static variable
    }
    test::$a = 5;
    echo test::$a;

    میبینید که چقدر راحت میشه به پراپرتی های استاتیک دسترسی داشت. با استفاده از کلمه های کلیدی self  و parent  هم میتونید به پراپرتی های این کلاس و یا کلاس پدر دسترسی داشته باشید.

    class testParent
    {
    public static $var1;
    }
    class testChild extends testParent
    {
    public static $var2;
    public $abc =2;
    function testFunction()
    {
    self::$var2 = 3;
    parent::$var1 = 5;
    }
    }
    echo testChild::$abc; //throw fatal error

    نحوه ی تعریف متدهای استاتیک

    <?php
    class Game
    {
    	public static function start()
    	{
    		echo "Go!";
    	}
    }
    
    Game::start();

    همونطور که در بالا میبینید متد start()  بصورت استاتیک تعریف شده و خیلی شیک و مجلسی میشه ازش نمونه ساخت. این نوع توابع در نگاه اول خیلی جالب به نظر میرسن… و سوالی که پیش میاد اینه که چرا همه متد هارو استاتیک تعریف نمیکنیم؟ 

    متدهای استاتیک با اینکه اولش خیلی باحال به نظر میرسن ولی محدودیتی دارن که تنها در بعضی موارد میتونیم ازشون استفاده کنیم : “بخاطر استاتیک تعریف شدن این متدها ، امکان استفاده از $this  در این نوع متدها وجود ندارد.” ولی در مجموع این نوع متدهای خیلی پرکاربرذ هستند.

  • متغییر های استاتیک در PHP

    متغییر های استاتیک در PHP متغییر های خیلی جالبین 🙂 . متغیر هایی هستند که مقداری که دارند رو از دست نمیدن ، حتی داخل یک تابع و بعد از به اتمام رسیدن پردازش تابع.

    مثال میزنم :

    <?php
       function keep_track() {
          STATIC $count = 0;
          $count++;
          print $count;
          print "<br />";
       }
       
       keep_track();
       keep_track();
       keep_track();
    ?>

    خروجی کد بالا به شکل زیر خواهد بود :

    ۱
    ۲
    ۳

    میبینید که مقدار متغیر استاتیک ثابت مونده بعد از اتمام هر تابع…

  • حذف کلید خارجی در لاراول

    همونطور که میدونید اگه یه کلید خارجی توی مایگریشن ها و متد up()  اضافه کنیم ، باید اون رو توی متد down()  حذفش کنیم و یا به اصطلاح drop کنیم. روابط رو میتونید در phpmyadmin->structure->Relation view  ببینید . برای حذف این روابط داکیومنت خود لاراول گفته این کار رو بکنید :

    To drop a foreign key, you may use the dropForeign method. Foreign key constraints use the same naming convention as indexes. So, we will concatenate the table name and the columns in the constraint then suffix the name with “_foreign”:

    $table->dropForeign('posts_user_id_foreign');

     

    یک راه دیگه که توی داکیومنت لاراول گفته نشده اینه :

    $table->dropForeign(['user_id']);