۲۹ شهریور، ۱۴۰۰

٣ ساعت پیش ١۰۰+ امتیاز
@reskipper به گفتگوی ارسال کد ثبت نام(عدم لاگین قبل و بعد) جواب داد.

اول اینکه شما دوست عزیز معلوم php خام دارین مینویسن و قطع کدهاتون خیلی مشخص نمیکنه توی فایل ها چکاری انجام دادین سورس رو اگه امکان داره روی github بزارید.

ولی مشکل با یک تابع is_login که لاگین بودن کاربر و از طریق session که براش ایجاد کردین حل میشه به نظرم و هر جا که خواستین صفحه ی نمایش نده با یک if ساده میتونید مدیریتش کنید.

برای بحث verify هم اگه بار اول ریحستر میکنه و شروع به لاگین میکنه در صورت verify شدن باید فلگ verified_email به صورت true در بیاد در دیتابیس و اینو توی کویٔری مدیریت کنید و اگه دیبایس هنوز دخیل نکردین session ست کنید باز مثل همون قضیه لاگین بودن مدیریتش کنید.

۲۷ شهریور، ۱۴۰۰

٢ روز پیش ١۵۰۰+ امتیاز
نویسنده @reskipper یک مقاله تازه به اسم راهنمایی کامل روابط جداول در لاراول - بخش ۲ نوشت.

همانطور که اطلاع داشتین ما در ۲ بخش می خواستیم تمام حالت های ارتباطات جداول در لاراول را شرح دهیم، اگر احیانا بخش اول را مطالعه نکرده اید لطفا (راهمایی کامل روابط جداول در لاراول بخش ۱) روی این لینک کلیک کنید و در صورت نیاز آن را مطالعه کنید. ما در مقاله قبلی در مورد سه نوع ارتباط به نام های One To One، One To Many، Many To Many صحبت کردیم و در ادامه به مطالعه موارد در پایین ذکر شده می پردازیم :

Has One Through .4 (یک به یک واسطه ای)

Has Many Through .5 (یک به چند واسطه ای)

One To One (Polymorphic) .6 (یک به یک پلی مورفیک)

One To Many (Polymorphic) .7 (یک به چند پلی مورفیک)

Many To Many (Polymorphic) .8 (چند به چند پلی مورفیک)

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

ثبت و ویرایش

شما اگر بخواهید در جدول واسط اطلاعات را درج کنید می توانید از دو متد save() و یا attach() استفاده کنید به مثال زیر دقت کنید :

$role = App\Role::find(5);

App\User::find(1)->roles()->save($role);

// or

App\User::find(1)->roles()->attach($role);

دقت کنید آرگومانی که پاس می دهیم به متد های save() و attach() باید از نوع Model باشند. همچنین ما میتوانیم برای پاک کردن چندین نقش و نسب دادن نقش های جدید به صورت هم زمان از متدی به نام sync() استفاده کنیم به کد زیر دقت کنید :

$roles = App\Role::whereIn('id', [1, 2, 3])->get();

App\User::find(1)->roles()->sync($roles);

اگر نخواهیم نقش های قدیمی پاک شود به آرگومان دوم متد sync مقدار false می دهیم یا از متد زیر استفاده می کنیم‌ :

$user->roles()->syncWithoutDetaching([1, 2, 3]);

برای حذف کردن نقش های نسبت داده شده به یک کاربر از متد detach() استفاده می‌کنیم:

$roles = App\Role::whereIn('id', [1, 2, 3])->get();

App\User::find(1)->roles($roles)->detach();

سعی کردم تقریبا تمام مباحث مهم و کاربردی تا اینجا برای بحث های باقی مانده پوشش بدهم بریم سراغ مباحث جدید با من همراه باشید.

Has One Through (یک به یک واسطه ای)

در رابطه has-one-through همانطور که از اسمش پیدا است مدل ها از طریق یک واسطه باهم ارتباط می گیرند. خب با مثال زیر به توضیح آن می پردازیم :

users
    id - integer
    reviewer_id - integer

reviewers
    id - integer

activities
    id - integer
    user_id - integer

در اینجا به سه مدل User و Reviewer و Activity را در نظر داشته باشید که در این مثال قرار است فعالیت هر کاربر رو از طریق داوران بدست بیاریم، در اینجا دقت کنید که در جدول activites کلیدی به نام reviewer_id وجود ندارد برای همین منظور ما از ارتباط hasOneThrough استفاده می کنیم.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Reviewer extends Model
{
    /**
     * Get the reviewer's activity.
     */
    public function activity()
    {
        return $this->hasOneThrough(
            'App\Activity',
            'App\User',
            'reviewer_id', // Foreign key on users table...
            'user_id', // Foreign key on activities table...
            'id', // Local key on reviewers table...
            'id' // Local key on users table...
        );
    }
}

این اینجا مدلی باید در آرگومان اول پاس بدهیم Activity می باشد و آرگومان بعدی که پاس میدهیم همان مدلی است که می خواهیم به صورت واسطه از طریق آن ارتباط بگیریم من شکل این متد را به صورت کامل آورده ام که شما می توانید به ترتیب بعد آرگومان های Foreign key و Local key مشاهده کنید.

خب حالا خیلی راحت می توانید از طریق کد زیر به اطلاعات دسترسی داشته باشید :

$reviewer = Reviewer::first();
$activity = $reviewer->activity;

Has Many Through (یک به چند واسطه ای)

در رابطه has-many-through همانطور که از اسمش پیدا است ما در این رابطه مدلی را داریم که ارتباط با چند موجودیت مدل دیگر دارد به عنوان مثال یک مدل Country ممکن است دارای بسیاری از مدل های Post از طریق یک مدل User ​​باشد خب حالا شما به راحتی میتوانید تمام پست های مربوط به یک کشور خاص را از طریق مدل User بدست بیاورید.

countries
    id - integer
    name - string

users
    id - integer
    country_id - integer
    name - string

posts
    id - integer
    user_id - integer
    title - string

همانطور که مشاهده می کنید ما ستون country_id را در جدول posts نداریم برای همین منظور ما دنبال رابطه هستیم که بتوانیم از طریق آن به این صورت $country->posts تمام پست های یک کشور را به دست بیاریم. برای این کار فقط کافی است در مدل Country ارتباط از طریق متد hasManyThrough برقرار کنیم :

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Country extends Model
{
    /**
     * Get all of the posts for the country.
     */
    public function posts()
    {
        return $this->hasManyThrough(
            'App\Post',
            'App\User',
            'country_id', // Foreign key on users table...
            'user_id', // Foreign key on posts table...
            'id', // Local key on countries table...
            'id' // Local key on users table...
        );
    }
}

همانطور که مشاهده می کنید ما ارتباط کشور را با مدل پست از طریق مدل کاربر برقرار کردیم حالا فقط کافی است به صورت زیر از آن استفاده کنیم :

$country = Country::find('Asia');

dump($country->posts);

Polymorphic Relationships

به زبان ساده این رابطه به ما اجازه می دهد یک رابطه به بیش از یک مدل تعلق داشته باشد، خب بریم تمام حالت های ارتباطات Polymorphic برسی کنیم.

One To One (Polymorphic) (یک به یک پلی مورفیک)

رابطه one-to-one polymorphic خیلی شبیه به رابطه one-to-one می باشد، خب حالا بیایم با یک مثال اون و برسی کنیم فرض کنید شما سه مدل User و Post و Image دارید در اینجا یک وجه مشترک وجود دارد و آن این است که هم مدل User و هم مدل Post به مشخصات درون Image نیاز دارند یعنی ما به تصویر هم برای کاربران و هم برای پست ها خودمون نیاز داریم پس به همون جلمه اول بر میگردیم که گفتیم یک رابطه می تواند به مدل های مختلفی تعلق داشته باشد. به مثال زیر دقت کنید :

posts
    id - integer
    name - string

users
    id - integer
    name - string

images
    id - integer
    url - string
    imageable_id - integer
    imageable_type - string

نکته بسیار مهم که اینجا وجود دارد دوتا ستونی است که در جدول images قرار دارند به نام های imageable_id و imageable_type که هر کدام وظیفه مشخصی دارند. imageable_id در خود مقدار شناسه users یا posts رو نگه میداره و imageable_type مقدار مدلی که مربوط به اون شناسه می باشد برای ارتباط گرفتن کلاس Eloquent می باشد.

همیشه قرارداد لاراول برای دوتا فیلد imageable_id و imageable_type به این صورت است که اسم مدل مقصد + کلمه able. اینجا مدل ما Image هست که با کلمه able میشه imageable.

ساختار کلی تمام جدول ها را در زیر مشاهده کنید :

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Image extends Model
{
    /**
     * Get the owning imageable model.
     */
    public function imageable()
    {
        return $this->morphTo();
    }
}

class Post extends Model
{
    /**
     * Get the post's image.
     */
    public function image()
    {
        return $this->morphOne('App\Image', 'imageable');
    }
}

class User extends Model
{
    /**
     * Get the user's image.
     */
    public function image()
    {
        return $this->morphOne('App\Image', 'imageable');
    }
}

حالا وقتش رسیده ازش استفاده کنیم به عنوان مثال بیایم تصویر مربوط به یک پست را برگردانیم، فقط کافی است از ویژگی image dynamic property که ایجاد کردیم استفاده کنیم :

$post = App\Post::find(1);

$image = $post->image;

همانطور که مشاهده کردید ما توانستیم یک رابطه یک به یک از طریق متد morphOne() ایجاد کنیم.

ثبت ویرایش و حذف

حالا خیلی راحت میتونیم سه عملیات ثبت و ویرایش و حذف بر روی اون انجام بدیم :

// Insert
App\Post::find(1)->image()->create([
    'url' => '...'
]);

// Update
App\Post::find(1)->image()->update([
    'url' => '...'
]);

// Delete
App\Post::find(1)->image()->delete();

دقت داشته باشید که مقادیر imageable_id و imageable_type به صورت خودکار پر می شود.

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

$image = App\Image::find(1);

dump($image->imageable);

مقدار ->imageable یک پراپرتی دینامیک هست که حاوی مقدار مدل مبدا است، اینجا ما با مدل های User و Post سرکار داریم و این در واقع همون اسم مدلی هست که در مدل Image است.

One To Many (Polymorphic) (یک به چند پلی مورفیک)

رابطه one-to-many polymorphic خیلی شبیه به رابطه one-to-Many می باشد بیاین با یک مثال اون برسی کنیم شما فرض کنید سه مدل Video و Post و Comment دارید حالا تصور کنید که کاربران شما میخواهند روی پست ها و ویدیو های شما کامنت بگذارند . یعنی هم مدل Post و هم Video نیاز دارن با مدل Comment ارتباط داشته باشند برای همین یک رابطه یک به چند شکل می گیرد بین آنها، ولی نکته اینجاس که ما برای هر دو مدل جالب نیست دوتا جدول comments تعریف کنیم فقط کافی است ارتباط آنها را از طریق متد morphMany برقرار کنیم به مثال زیر توجه کنید :

posts
    id - integer
    title - string
    body - text

videos
    id - integer
    title - string
    url - string

comments
    id - integer
    body - text
    commentable_id - integer
    commentable_type - string

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

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    /**
     * Get the owning commentable model.
     */
    public function commentable()
    {
        return $this->morphTo();
    }
}

class Post extends Model
{
    /**
     * Get all of the post's comments.
     */
    public function comments()
    {
        return $this->morphMany('App\Comment', 'commentable');
    }
}

class Video extends Model
{
    /**
     * Get all of the video's comments.
     */
    public function comments()
    {
        return $this->morphMany('App\Comment', 'commentable');
    }
}

همنطور که مشاهده می کنید مدل Comment متد commentable را برای ارتباط با مدل های دیگ تعریف می کنیم و حالا فقط کافی است که ارتباط مدل Post و Video از طریق متد morphMany که آرگومان اول مدل ارتباطی و آرگومان دوم اسم رابطه پلی‌مورفیک که commentable است تعریف و ارتباط را برقرار کنیم.

ثبت و ویرایش اطلاعات و حذف

نحوه ثبت، ویرایش و حذف اطلاعات مثل رابطه پلی‌مورفیک یک به یک هست:

// Insert
App\Post::find(1)->comments()->create([
    'body' => '...'
]);

// Update
App\Post::find(1)->comments()->find(5)->update([
    'body' => '...'
]);

// Delete
App\Post::find(1)->comments()->delete();

برای به دست اوردن اطلاعات هم از طریق کد زیر این اقدام می کنیم :‌

$post = App\Post::find(1);

foreach ($post->comments as $item) {
    echo $item->body;
}

همانطور که قبلا گفتیم برای ارتباط معکوس آن هم به این صورت عمل می کنیم :‌

$comment = App\Comment::find(1);

$commentable = $comment->commentable;

Many To Many (Polymorphic) (چند به چند پلی مورفیک)

اخرین رابطه ی که میخوام در موردش صحبت کنم Many-to-many polymorphic می باشد که نسبتا توی روابط چند به چند پیچیدگی بیشتری نسبت بع روابط دیگر وجود دارد، خب حالا دوباره با یک مثال پیش میریم شما چهار مدل Post ٰو Video و Tag رو در نظر بگیرید، پست یا یک ویدئو میتونه چند تگ داشته باشه و هر تگ میتونه متعلق به هر پست و ویدیو باشه. توی روابط چند به چند، موجودیت‌ها مستقل از هم تعریف میشن و ما فقط به یک جدول واسط برای برقراری ارتباط آن ها نیاز داریم .

posts
    id - integer
    name - string

videos
    id - integer
    name - string

tags
    id - integer
    name - string

taggables
    tag_id - integer
    taggable_id - integer
    taggable_type - string

خب همانطور که مشاهده می کنید برای هر موجودیت یک جدول جدا تعریف کردیم و موجودیت ها همگی مستقل از همدیگر هستند و جدولی که به عنوان واسط عمل می کند taggables نام دارد، قبلا در مورد taggable_id و taggable_type صحبت کردیم ولی اینجا یک ستون دیگه به نام tag_id وجود داره که ارتباط و با مدل های دیگ برقرار کنه.

حالا بیایم مدل ها رو باهم اتباط بدیم :

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    /**
     * Get all of the tags for the post.
     */
    public function tags()
    {
        return $this->morphToMany('App\Tag', 'taggable');
    }
}

ارتباط مدل post را از طریق متد morphToMany مشخص می کنیم که با چندین تگ به صورت پلی‌مورفیک که taggable نام دارد در ارتباط است.

حالا فقط کافیه رابطه معکوس آن را مشخص کنیم :

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Tag extends Model
{
    /**
     * Get all of the posts that are assigned this tag.
     */
    public function posts()
    {
        return $this->morphedByMany('App\Post', 'taggable');
    }

    /**
     * Get all of the videos that are assigned this tag.
     */
    public function videos()
    {
        return $this->morphedByMany('App\Video', 'taggable');
    }
}

حالا برای بدست آوردن اطلاعات فقط کافی است به صورت زیر عمل کنیم :

$post = App\Post::find(1);

foreach ($post->tags as $tag) {
    //
}
$tag = App\Tag::find(1);

foreach ($tag->videos as $video) {
    //
}

ثبت و ویرایش اطلاعات و حذف

برای ثبت اطلاعات می‌تونیم از متد save() یا attach() استفاده کنیم:

$tag = App\Tag::find(5);

App\Post::find(1)->tags()->save($tag);

// or

App\Post::find(1)->tags()->attach($tag);

همانطور که قبلا گفتیم از متد sync() هم میتوانید استفاده کنید :

$tags = App\Tag::whereIn('id', [1, 2, 3])->get();

App\Post::find(1)->tags()->sync($tags);

جمع بندی

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

۲۵ شهریور، ۱۴۰۰

۴ روز پیش ١۵۰۰+ امتیاز
نویسنده @reskipper یک مقاله تازه به اسم راهنمایی کامل روابط جداول در لاراول - بخش ۱ نوشت.

مقدمه

همانطور که میدانید هنگامی که شروع به طراحی پایگاه داده می کنید بین جداولی که میسازید روابط مختلفی ایجاد می شود به عنوان مثال اگر شما جدولی به نام posts داشته باشید و درکنار آن جدول دیگری به نام comments باشد رابطه به این صورت تعریف می شود که هر post می تواند چندین comments داشته باشد و هر comment می تواند متعلق به یک post باشد. نوع رابطه بالا One To Many یا یک به چند می باشد، خب در این مقاله قصد دارم تمام حالت های مهمی که لاراول برای کار با Eloquent: Relationships بین روابط جداول قرارداد کرده است را باهم برسی کنیم.

انواع روابط در لاراول

  1. One To One (یک به یک)
  2. One To Many (یک به چند)
  3. Many To Many (چند به چند)
  4. Has One Through (یک به یک واسطه ای)
  5. Has Many Through (یک به چند واسطه ای)
  6. One To One (Polymorphic) (یک به یک پلی مورفیک)
  7. One To Many (Polymorphic) (یک به چند پلی مورفیک)
  8. Many To Many (Polymorphic) (چند به چند پلی مورفیک)

جداول شما از طریق مدلی به نام Eloquent که به متد های مختلفی برای روابط بین جداول شما تعریف شده است دسترسی دارد و کار شما را برای تعریف این روابط بسیار آسان کرده است. به عنوان مثال شما میتوانید با زنجیره زدن بین مدل های که تعریف کرده اید اطلاعات را به صورت های مختلف از دیتابیس واکشی کنید به مثال زیر دقت کنید :

$user->posts()->where('active', 1)->get();

قطع کد بالا به این مفهوم می باشد که تمام پست های که مربوط به یک کاربر خاص با ضعیت فعال می باشد برگرداند. خب به همین راحتی توانستید یک Query که باید زمان بیشتری را برایش صرف می کردین را از طریقی مفهومی به نام query builders به راحتی اجرا کنید.

خب حالا برویم تمام روابط را یک به یک با هم برسی کنیم.

One To One (یک به یک)

یکی از پایه ترین روابطی که بین جداول برقرار می شود رابطه ای One To One می باشد به عنوان مثال شما فرض کنید هر User دارای یک حساب یا Account می باشد. در اینجا شما با دو مفهوم hasOne و belongsTo آشنا می شوید بیاید باهم کد زیر را برسی کنیم :

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{

    public function account()
    {
        return $this->hasOne('App\Account');
    }
}

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

اولین کار تشکیل یک تابعی به صورت منفرد بر مبنای همان جلمه که بکار بردیم و گفتیم هر کاربر یک حساب دارد.

public function account()
{
}

بدنه این تابع را از طریق مدل User و کلمه کلید $this که به خود آن اشاره دارد به تابع دسترسی پیدا کردیم که متد hasOne با اولین ورودی خود مدل Account دریافت کرده و مقداری را باز میگرداند.

 return $this->hasOne('App\Account');

همچنین توجه داشته باشید پارامتر دومی که تابع hasOne می گیرد مقدار foreign_key می باشد که از طریق آن میتوانید کلید خارجی جدول خود را تعریف کنید ولی لاراول به صورت پیش فرض آن را برای این مثال طبق قرارداد های خودش user_id در نظر می گیرید.

خب حالا بیاید ببنیم چطور میتوانید از آن استفاده کنید:

$account = User::find(1)->account;

ببنید که ما چطور بصورت زنجیره ای توانستیم اطلاعات حساب یک کاربر را طبق رابطه ای که تعریف کردیم نمایش دهیم. در واقع توابع account همان رابطه ای است که در مدل User تعریف کردیم. لاراول دسترسی به این نوع رابطه (account<-) را Dynamic properties نامیده است یعنی به صورت یک پراپرتی درون کلاس موجود است.

پس از اجرای دستور بالا خروجی SQL زیر در پس زمینه حاصل می شود :

select * from `accounts` where `accounts`.`user_id` = ? and `accounts`.`user_id` is not null limit 1

حالا همین رابطه را به صورت معکوس برای جدول Account داریم، کلمه معکوس بخاطر این است که اگر ما بخوایم چه از جدول User به جدول Account دسترسی داشته باشیم چه برعکس باید این عمل انجام شود.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Account extends Model
{
    public function user()
    {
        return $this->belongsTo('App\User');
    }
}

خب همانطور که می یبینید حال وقت آن رسیده رابطه ای بین مدل Account و جدول User را برقرار کنیم . طبق مطالبی که گفته شد برای این رابطه باید همچین جلمه ای به کار ببریم هر حساب متعلق به یک کاربر می باشد دقیقا همین جمله را باید به صورت کد و قرارداد های لاراول پیاده سازی کنیم.

توجه داشته باشید چون مدل های ما در کنار هم دیگر هستن می توانید مقدار ورود توابع را از این حالت App\User به این حالت User::class تغییر دهید.

توابع belongsTo سه تا آرگومان را از خود عبور می دهد که به شرح زیر می باشد :

return $this->belongsTo('App\User', 'foreign_key', 'other_key');

۱. مدلی که میخواهید با آن ارتباط برقرار کنید.

۲. میتوانیم بگویم که کدام ستون accounts مد نظر ما می باشد که به صورت پیش فرض user_id را در نظر می گیرد.

۳. متیونم مشخص کنیم اگه از id استفاده نمی کنیم که کدوم ستون جدولusers مد نظر ما می باشد.به صورت پیش فرض id می باشد.

One To Many (یک به چند)

این رابطه به این معنی می باشد که ما یک مدلی به نام post داریم که با مدل دیگری مثل comment رابطه one-to-many دارد. بیاید در کد آن را برسی کنیم.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    /**
     * Get the comments for the blog post.
     */
    public function comments()
    {
        return $this->hasMany('App\Comment');
    }
}

همانطور که مشاهده می کنید در مدل Post ما یک رابطه با comments تشکیل داده ایم، همانطور که قبلا گفتم از درک مفهوم و تعریف کاری که می کنیم باید به پیاده سازی برسیم، خب حالا باید در یک جلمه آن را تعریف کنیم که به این صورت می باشد باید بگویم هر پست دارای چندین کامنت می باشد پس پیاده سازی گام به گام به این صورت می شود :

اولین کار توابعی تعریف می کنیم به نام comments که مفهوم کامنت ها را برساند.

public function comments()
{
}

در بدنه این تابع برای ارتباط hasMany مقدار زیر تعریف میکنیم :

return $this->hasMany('App\Comment');

ما توانستیم با فرض اینکه ستون post_id در جدول comments وجود دارد ارتباط آن را برقرار کنیم، حال فرض کنید که می خواهیم کامنت های یک پست را مشاهده کنیم، به کد زیر توجه کنید :

$comments = App\Post::find(1)->comments;

foreach ($comments as $comment) {
    //
}

خب با قطع کد بالا توانستیم به تمام کامنت ها با دستور <-comments دسترسی پیدا کنیم فقط دقت کنید توی مثال بالا یک پراپرتی داینامیک به کلاس Post اضافه شد و اگر بخواهیم محدودیت در آن ایجاد کنید باید از متد comments() استفاده کنید و به شکل زیر آن را تغییر دهید.

$comment = App\Post::find(1)->comments()->where('title', 'foo')->first();

حال همانطور که در صحبت های قبل گفتیم روابط باید به صورت معکوس تعریف شوند حالت نوبت به مدل Comment رسیده است رابطه خود را با مدل Post شکل بدهد.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    /**
     * Get the post that owns the comment.
     */
    public function post()
    {
        return $this->belongsTo('App\Post');
    }
}

خب همانطور که مشاهده می کنید معکوس رابطه به این صورت می باشد که هر comment متعلق به یک post است که با متد belongsTo نسبت داده می شود.

حال بیایم با قطع کد زیر یک کامنت را گرفته و پست مورد نظر او را نمایش دهیم :

$comment = App\Comment::find(1);

echo $comment->post->title;

شکل کامل متد belongsTo به شکل زیر می باشد :

    return $this->belongsTo('App\Post', 'foreign_key', 'other_key');

Many To Many (چند به چند)

اخرین بخشی که میخوام در بخش اول این مقاله بگم رابطه Many-to-many می باشد که نسبتا پیچیده تر از روابط hasOne و hasMany است، ما با فرض اینکه دوتا جدول به نام های users و roles داریم وارد این مثال می شویم . تعریف اولیه ما از رابطه چند به چند بین این جداول به معنی است که هر کاربر چندین نقش دارد و هر نقش میتواند مرتبط به چندین کاربر باشد.

بعنوان مثال هر کاربر میتواند نویسنده و مدیر باشد و برعکس آن هر نقش میتواند متعلق به چند کاربر باشد .

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

users
    id - integer
    name - string

roles
    id - integer
    name - string

role_user
    user_id - integer
    role_id - integer

خب گام به گام من جلو میرم و خوب توجه کنید در اینجا لاراول از مفهومی به نام Alphabetical order استفاده می کند، فرایند جداول واسط با این مفهوم شکل می گیرند. وقتی ما یک رابطه چند به چند یا n به n داریم جدولی واسط به وجود می آید به نام pivot_table که قرارداد لاراول می باشد. خب در این جا جدولی که از حاصل users و roles به وجود می آید role_user نام دارد. ولی چگونه باید این قرارداد را ما بسازیم برای همچین جداولی که به عنوان جدول واسط عمل می کنند.

اولین گام حروف الفبای انگلیسی را نوشته :

A-B-C-D-E-F-G-H-I-J-K-L-M-N-O-P-Q-R-S-T-U-V-W-X-Y-Z

دومین گام نگاه می کنیم ببینیم بین جداول users و roles کدام حرف اولش از چپ به راست عقب تر از دیگری می باشد برای مثال من اگه بین حروف حرکت کنم R عقب تر از U می باشد پس جدول من می شود (roles_users) .

اخرین گام حال که جدول واسط از نام دو جدولی که باهم رابطه چند به چند دارن شکل گرفت فقط کافی است که جفت جدول ها را نام هایشان را منفرد کنیم به این شکل (role_user).

خب حالا وقت آن است که مدل ها را از طریق متد belongsToMany که در کلاس Eloquent تعریف شده است بهم متصل کنیم .

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The roles that belong to the user.
     */
    public function roles()
    {
        return $this->belongsToMany('App\Role');
    }
}

خب دوباره من طبق صحبت های قبلی که گفتم وقتی میخوایم این روابط شکل بدیم باید اول به صورت مفهومی آن را درک کنیم و بعد آن را به کد تبدیل کنیم اینجا جمله که باید بگین به این صورت می باشد که هر کاربر چندین نقش دارد، این مفهوم همان belongsToMany می باشد.

هنگامی که این رابطه را به درستی تعریف کردیم شکل استفاده آن به این شکل می شود :

$user = App\User::find(1);

foreach ($user->roles as $role) {
    //
}

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

$roles = App\User::find(1)->roles()->orderBy('name')->get();

خب حالا رابطه معکوس آن هم به این شکل ایجاد می کنیم :

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Role extends Model
{
    /**
     * The users that belong to the role.
     */
    public function users()
    {
        return $this->belongsToMany('App\User');
    }
}

تعریف ما از این نوع رابطه می شود هر نقش متعلق به چند کاربر می باشد.

برای استفاده از آن به این شکل عمل می کنیم در قطع کد زیر جدولی که حرفش را زدیم در قالب پراپرتی به نام pivot را مشاهد میکنید:

$user = App\User::find(1);

foreach ($user->roles as $role) {
    echo $role->pivot->created_at;
}

خب شکل کلی متد belongsToMany هم به این شکل می باشد :

return $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id');

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

۱. مدلی که میخواهید ارتباط دهید.

۲. جدول واسط که تعریف کرده اید.

۳. معرفی کلید خارجی در جدول واسط برای جدول کاربران.

۴. معرفی کلید خارجی در جدول واسط برای نقش ها.

نکته آخر اگر پارامتر های ۳و ۴ را ندهید طبق قرارداد خود لاراول user_id و role_id را در نظر می گیرد.

در بخش بعدی به روابط دیگری که باقی ماند می پردازیم امیدوارم تا این جا مقاله برای شما مفید باشد.

۲۰ شهریور، ۱۴۰۰

١ هفته پیش ١۵۰۰+ امتیاز
نویسنده @reskipper یک مقاله تازه به اسم ویژگی های جدید لاراول ۸ نوشت.

مقدمه

همانطور که میدانید آخرین نسخه Laravel 8.0 در September 8 منتشر شد. در این مقال قصد داریم ویژگی های جدیدی که در این فریم ورک محبوب و قدرتمند اضافه شده است را باهم برسی کنیم.

همانطور که میدانید لاراول در هر نسخه ای که انتشار میدهد ویژگی های را طبق آپدیت های PHP و راه کار های جدید که هر توسعه دهنده را کنجکاو می کند ارایه می دهد. در این مقاله قصد داریم به ویژگی های مهم آن بپردازیم.

فقط نکته ای حائز اهمیتی که باید به آن اشاره کنم این است که Laravel در طی نسخه های انتشار داده، در نسخه 6 LTS طبق آماری که منتشر شده نسبت به سایر نسخه ها توسط لاراول پشتیبانی شده و مشکلات امنیتی و باگ های موجود و گزارش شده در آن رفع می شود و پایدارتر می باشد اگر نگاهی به جدول زیر بندازیم خواهیم فهمید نسخه 6 لاراول از نظر امنیتی تا سال 2022 پشتیبانی شده ولی با این حساب نمیشه از وپژگی های جدید لاراول گذشت.

ويژگی های جدید لاراول

بهترین ویژگی که در لاراول نسخه ۸ اضافه شد مفهومی به نام Jetstream می باشد که یک داربست کاربردی با طراحی بسیار زیبا برای لاراول است که می تواند یک نقطه شروع ایده آل برای پروژه شما باشد. حال علاوه بر این موارد زیر را به همراه داریم :

۱. Login/ Registration

۲. E-mail verification

۳. Two-factor authentication

۴. Session management

۵. API support via Laravel Sanctum

در ویژگی جدید لاراول همراه خود یک صفحه ورود جدید ارایه میدهد که دارای تم تیره و روشن می باشد که با استفاده از TailwindCSS ایجاد شده است.حالا بریم یکی یکی ویژگی ها جدید لاراول و معرفی کنیم.

Route Caching Improvements

این ویژگی ذخیره سازی مبتنی بر closure-based را پشتیبانی می کند‌، همانطور که میدانید قبل از لاراول ۸ ما می توانستیم مسیر های متنی بر کنترل ها را ذخیره کنیم و هر گونه closure-based و ایجاد بسته جدید باعث خرابی مسیر ذخیره می شود ولی حالا این مشکل در نسخه جدید لاراول حل شده است.

Route::get('/clear-cache-all', function() {
    Artisan::call('cache:clear');

    dd("Cache Clear All");
});

Dynamic Blade Components && attributes

در این بخش تمام child components ها داری ویژگی $attributes هستند، در لاراول ۷ هنگامی که یک کامپونت را گسترش می دهید دکمه فرزند خصوصیات $attributes را از خود نمی توانست رد کند.

<button {{'{{'}} $attributes }}>
   {{'{{'}} $slot }}
</button>

همانطور که مشاهده می کنید دکمه مورد نظر می تواند خصوصیات خود را به والدش معرفی کند. این ویژگی به شما کمک می کند تا اجزای قابل توسعه بسازید. گاهی اوقات شما نیاز دارید یک کامپونت را رندر کنید ولی نمی دانید که کدام جزء تا زمان رندر باید اجرا شود در همچین وضعیتی شما میتوانید از قابلیت جدید به نام x-dynamic-component برای رندر کردن کامپونت بر اساس مقدار اجرا یا متغییر استفاده کنید.

<x-dynamic-component :component="$componentName" class="mt-4" />

Migration Squashing

این ویژگی برای برنامه ها و یا مهاجرت های بزرگ پایگاه داده مفید می باشد، این ویژگی جدید که به نام Schema Dumping می باشد به شما کمک میکند که از پایگاه داده به خوبی نگهداری کنید. هنگامی که برنامه شما بزرگ می شود تعداد فایل های Migration شما هم به همان نسبت بزرگ می شود و نگهداری آن ها نسبتا سخت می کند به همین دلیل این ویژگی به شما کمک می کند با دستور زیر تمام آنها را در یک فایل SQL فشرده یا squash کنید. همچنین پایگاه داده های MySQL ، PostgreSQL و SQLite - همه از این ویژگی پشتیبانی می کنند.

php artisan schema:dump

// Dump the current database schema and prune all existing migrations...
php artisan schema:dump --prune

Models Directory

با توجه به تقاضای زیاد جامعه پشتیبانی لاراول پوشه پیش فرض model ها به مسیر app/Models منتقل شد و اگر این دایرکتوری وجود ندارد فریم ورک فرض می کند مسیر پیش فرض مدل های شما داخل پوشه app می باشد.

Model Factory Classes

ویژگی جدید model factories بر مبنای class based به طور کامل باز نویسی شده، این ویژگی در حال حاضر قوی تر و سازگار با توسعه دهندگان می باشد در این ویژگی برای هر مدل می تواند یک factory class وجود داشته باشد. به لطفا وجود trait جدید HasFactory در مدل ایجاد شده می توانید برای ایجاد تعداد مشخص از آن مانند روش زیر عمل کنید:

use App\Models\User;

User::factory()->count(50)->create();

متد definition مجموعه ای از ویژگی ها بر می گرداند، آن را در زیر مشاهده کنید:

class UserFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = User::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'name' => $this->faker->name(),
            'email' => $this->faker->unique()->safeEmail(),
            'email_verified_at' => now(),
            'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
            'remember_token' => Str::random(10),
        ];
    }
}

از آنجایی که model factory های شما از نوع کلاس PHP ساده هستند همچنین می توانید تغییر حالت ها یا state transformations به عنوان متد در کلاس خود اضافه کنید و میتوانید هر کلاس کمکی دیگر را به Eloquent model factory اضافه کنید. به عنوان مثال، ممکن است مدل کاربر شما بخواهد به حالت تعلق یا suspended state در بیاید و یکی از ویژگی ها پیش فرض آن را تغییر بدهد. شما می توانید با استفاده از روش factory's state تغییرات حالت خود را تعریف کنید شما میتوانید روش حالت خود را با هر نامی که میخواهید نامگذاری کنید.

/**
 * Indicate that the user is suspended.
 *
 * @return \Illuminate\Database\Eloquent\Factories\Factory
 */
public function suspended()
{
    return $this->state([
        'account_status' => 'suspended',
    ]);
}

حتی این ویژگی به شما این امکان را می دهد که از model factory برای روابط بین جداول خود استفاده کنید.

$users = User::factory()
            ->hasPosts(3, [
                'published' => false,
            ])
            ->create();

Improved Rate Limiting

این ویژگی محدودیت نرخ یا Rate Limiting بهبود می بخشد، با این ويژگی میتواند مدیریت محدودیت نرخ را با انعطاف پذیری پیشرفته کنترل کنید. شما می توانید با استفاده از RateLimiter facade و متد for که یک توابع بازگشتی را بر می گرداند پیکربندی route هایی که باید محدود شوند را انجام دهید.

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;

RateLimiter::for('global', function (Request $request) {
    return Limit::perMinute(1000);
});

از آنجایی که تابع بازگشتی همراه خود HTTP را برمی گرداند شما میتوانید تمام درخواست ها را به صورت دینامیک دریافت کنید.

RateLimiter::for('uploads', function (Request $request) {
    return $request->user()->vipCustomer()
                ? Limit::none()
                : Limit::perMinute(100);
});

گاهی اوقات ممکن است بخواهید محدویت نرخ را با مقادیر دلخواه کنترل کنید برای مثال شاید شما بخواهید به کاربران اجازه دهید در هر 100 دقیقه در هر ادرس IP به یک مسیر مشخص دسترسی داشته باشند برای انجام این امر می توانید از کد زیر استفاده کنید.

RateLimiter::for('uploads', function (Request $request) {
    return $request->user()->vipCustomer()
                ? Limit::none()
                : Limit::perMinute(100)->by($request->ip());
});

همچنین میتوانید از ratelimiter خود به عنوان middleware در گروهی ازroute ها در لاراول استفاده کنید

Route::middleware(['throttle:uploads'])->group(function () {
    Route::post('/audio', function () {
        //
    });

    Route::post('/video', function () {
        //
    });
});

Job Batching

این ویژگی به شما این مکان را می دهد که دسته از jobs را به راحتی اجرا کنید و سپس بعد اتمام هر job برخی از اقدامات را انجام دهید. می توانید از متد batch از facade Bus برای ارسال دسته از job ها استفاده کنید و در هنگام بازگشت در صورت تکمیل فراخوانی از متد های then, catch, finally استفاده کنید.

$batch = Bus::batch([
    new ProcessPodcast(Podcast::find(1)),
    new ProcessPodcast(Podcast::find(2)),
    new ProcessPodcast(Podcast::find(3)),
    new ProcessPodcast(Podcast::find(4)),
    new ProcessPodcast(Podcast::find(5)),
])->then(function (Batch $batch) {
    // All jobs completed successfully...
})->catch(function (Batch $batch, Throwable $e) {
    // First batch job failure detected...
})->finally(function (Batch $batch) {
    // The batch has finished executing...
})->dispatch();

return $batch->id;

Routing Namespace Updates

در ویژگی های نسخه قبلی لاراول در فایل RouteServiceProvider دارای خصوصیتی به نام $namespace نامیده می شد. این پسوند فضای نامی یا namespace کنترلر های شما را تغیین می کرد.

لاراول ۸ این ویژگی را حذف کرده است و شما میتوانید کلاس های کنترل خود را بدون مشکل در فایل routes وارد کنید.
در نسخه های قبلی لاراول RouteServiceProvider دارای یک ویژگی به نام $namespace بود. مقدار این ویژگی به طور خودکار در تعاریف مسیر کنترل کننده و فراخوانی به action helper / URL::action اضافه می شود. در لاراول ۸، این ویژگی به طور پیش فرض خالی است. این بدان معناست که هیچ پیشوند فضای نام خودکار توسط لاراول انجام نمی شود. بنابراین ، در برنامه های جدید لاراول تعاریف مسیر کنترل کننده باید با استفاده از قاعده استاندارد PHP قابل فراخوانی باشد :

use App\Http\Controllers\UserController;

Route::get('/users', [UserController::class, 'index']);

فراخوانی به روش های دیگر هم باید به شکل زیر باشد :

action([UserController::class, 'index']);

return Redirect::action([UserController::class, 'index']);

improved Maintenance Mode

در نسخه های قبلی لاراول ممکن است با استفاده از از دستور php artisan down برنامه خود را به حالت تعمیر ببرید و ممکن است آدرس های مجاز یا "allow list" از IP ها اجازه دسترسی به برنامه را داشته باشند. با استفاده از این ویژگی میتوانید با افزودن یک secret در نسخه 8 لاراول آن را امن کنید.

می توانید از این پس به شکل زیر از یک secret استفاده کنید:

php artisan down --secret="1630542a-246b-4b66-afa1-dd72a4c43515"

جمع بندی

من سعی کردم در این مقاله اکثر امکانات افزودن شده در نسخه 8 لاراول را شرح دهم، امیدورام از بکار گیری آنها در پروژه های خود لذت ببرید و همچنین برای کامل کردن اطلاعات خود لطفا به مستندات لاراول که آن را برای شما لینک کردم یک سر بزنید. امیدوارم این مقاله برای شما مفید باشد.

۱۷ شهریور، ۱۴۰۰

٢ هفته پیش ١۵۰۰+ امتیاز
نویسنده @reskipper یک مقاله تازه به اسم بهترین شیوه کد نویسی نوشت.

بهترین شیوه کد نویسی ( Best Coding Practice )

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

همیشه اولین چیزی که در کد به چشم می آید مرتب بودن ساختار و نامگذاری ها و کامنت گذاری ها وغیره در سورس پروژه شما می باشد. لذا هر چه کد شما مرتب و استاندارد تر باشد باعث می شود بهتر ارایه دهید و در ضمن آن را به دیگران انتقال دهید، برای همین اکثر شرکت ها برنامه نویسانی که این اصول را رعایت می کنند را بهتر ترجیح می دهند.

مثلا در PHP قوانین برای این امر تعریف شده است به نام PSR که می توانید با کلیک کردن بر روی آن مستندات آن را مشاهده کنید.

من مخزنی را بر روی GitHub به شما معرفی میکنم که کد خوب و کد بد را در زبان JavaScript باهم مقایسه کرده است .

https://github.com/rezasaleki/clean-code-javascript

کتاب های متعددی هم در این زمینه وجود دارد که من میتوانم به یکی از معروف ترین ها که توسط Robert C.Martin نوشته شده است به نام The Clean Code اشاره کنم .

از تمام این صحبت ها میخواستم بگم که بدانید چقد اهمیت این قضیه بالا می باشد تا نکات زیر را برای هرچه بهتر نوشتن کد هایتان بیان کنم .

۱. همیشه متغییر ها و توابع خود را با نهایت دقت سعی کنید نام گذاری کنید و بطور کامل توضیح دهید.

۲. اسنادی برای سناریو فنی خود بسازید، حتی اگر مختصر یا توصیفی باشند.

۳. کدی که اجرا می شود کمتر از زمان خواندن آن وقت میگیرد پس سعی کنید همیشه برای شفافیت آن بیشتر زمان صرف کنید.

۴. هر تابعی که تعریف می کنید باید یک کار را انجام دهد ولی به درستی، این اصل به طراحی الگو یا Design Pattern و قوانین SOLID اشاره می کند که یک بند در آن به نام Single Responsibility Principle اشاره دارد.

۵. هر تابع باید به صورت Black Box عمل کند به این معنی که اگر کسی تابع شما را می بیند فقط از نام تابع متوجه فرایند آن شود و نیازی نباشد به بدنه آن سر بزند و از آن خبر داشته باشد.

۶. تا می توانید در سورس کد های خود از تعریف متغییر های سراسری امتناع کنید و آن ها را متصل به بلاک های خود نگهدارید.

۷. سعی کنید برای کد های خود علاوه بر تست های انسانی تست های سیستمی بنویسید که به عنوان مثال میتوانید در JavaScript به JestJS مراجعه کنید و برای PHP به PHPUnit مراجه کنید.

۸.شما هیچ وقت نمیتوانید 100% صحت کدی را که نوشته اید را تضمین کنید ولی با تست گرفتن و آزمون و خطا کردن می توانید تا حدی بالایی جلوی خطا های احتمالی را بگیرید.

۹. هرگاه در در برنامه ی به مشکلی می خورید یا میخواهید مشکلی را حل کنید حتما قبل از نوشتن کد در مورد آن فکر و تحقیق کنید تا کاملا نحو حل کردن آن را درک کنید.

۱۰. در صورت بروز مشکل اولین اقدامی که می کنید مشکل را به قطعات کوچک تر تقسیم کنید و بعد هر قسمت را به صورت جدا برسی و حل کنید، یکی از موارد که می توان به آن اشاره کرد همین ساختارمند و استاندارد بودن کد هایتان است که اینجا به طور چشمگیری به شما کمک می کند.

۱۱. تا میتوانید توابع خود را به توابع کوچکتر بشکنید و وظایف آن ها را تا حدالممکن ساده تعریف کنید.

۱۲. برنامه خود را برای دیگران توضیح دهید این امر به شما کمک میکند خودتان بهتر آن را درک کنید.

۱۳. از VCS ها از قبیل Git در برنامه خود استفاده کنید تا تغییرات را در برنامه های شما همیشه دنبال کند و کارهای گروهی شما را سازماندهی کند.

نتیجه گیری

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

موارد ذکر شده در بالا از کتاب های کد نویسی تمیز و Data Structures and Program Design in C می باشد.

۱۶ شهریور، ۱۴۰۰

٢ هفته پیش ١۵۰۰+ امتیاز
نویسنده @reskipper یک مقاله تازه به اسم Deploy Laravel Application توسط وب سرور Nginx نوشت.

مقدمه

در این مقاله قصد داریم که تمام پیکربندی های که هنگام راه اندازی اپلیکیشن لاراول، بر روی سرور Ubuntu 18.04 توسط وب سرور Nginx به آن ها نیاز دارید را آموزش دهیم.

نصب پیش نیازها بر روی سرور

۱. Nginx

2. PHP8

3. MySQL

این مقاله برای کسانی مفید می باشد که درک خوبی از مباحث شبکه و تجربه کافی برای کار با سرور را داشته باشند.

هنگامی که شما یک سرور اشتراکی یا سرور VPS خریداری می کنید میتوانید از طریق telnet یا ssh به سرور خود ورود کنید، قبل از اجرای دستورات بر روی سرور می توانید برای telnet یا ssh کردن اگر سیستم عامل شما لینوکس است از دستورات زیر استفاده کنید :

نکته: البته سرور اشتراکی به شما پنل مدیریتی می دهد و میتوانید از طریق پنل خود هاستینگ به DirectAdmin یا Cpanel ورود کنید.

ssh -p 22 [email protected]
telnet ipserver

پس از ورود اولین دستور که اجرا می کنید به این صورت می باشد :‌ apt-get update، این دستور تمام مخزن های خود را بر روی سرور لینوکس بروز رسانی می کند

۱. Nginx

Nginx یکی از محبوب ترین وب سرور ها در جهان می باشد که وظیفه میزبانی برخی از بزرگترین و پر بازیدترین سایت های اینترنتی را برعهده دارد. در حال حاضر انتخاب بین Apache و Nginx بوده ولی بخاطر عملکرد و سرعت و امنیت و مدیریت منابع میتوان Nginx را به عنوان وب سرور و یا پروکسی معکوس معرفی کرد.

۱.۱ نصب Nginx

 apt-get install nginx

۱.۲تنظیم فایروال

قبل از راه اندازی Nginx باید تنظیمات مربوط به فایروال انجام شود تا دسترسی به ان امکان پذیر باشد. Nginx هنگام نصب خود را به عنوان یک سرویس به ufw معرفی می کند و این امر دسترسی به آن را ساده می کند.

تنظیمات برنامه فایروال را که ufw می داند با تایپ کردن دستور زیر لیست کنید :

ufw app list

شما باید فهرستی از مشخصات برنامه را به شکل زیر دریافت کنید :

//Output
Available applications:
Nginx Full
Nginx HTTP
Nginx HTTPS
OpenSSH

حال می توانید HTTP را با تایپ فعال کنید .

ufw allow Nginx HTTP

حال می توانید لیست وضعیت تغییرات انجام شده را به این شکل ببنید، ما با این عمل اجازه عبور ترافیک بر روی HTTP را صادر کردیم.

ufw status

خروجی :

//Output
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere                  
Nginx HTTP                 ALLOW       Anywhere                  
OpenSSH (v6)               ALLOW       Anywhere (v6)             
Nginx HTTP (v6)            ALLOW       Anywhere (v6)

۱.۳ برسی وضعیت وب سرور

در پایان انجام این فرایند ها باید چک کنیم توسط دستور زیر که وب سرور در حالت فعال قرار گرفته باشد.

systemctl status nginx

خروجی :‌

//Output
● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) since Sun 2019-06-09 00:00:00 ; 3h 33min ago
     Docs: man:nginx(8)
  Process: 2062 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
  Process: 1803 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
 Main PID: 2064 (nginx)
    Tasks: 5 (limit: 4915)
   CGroup: /system.slice/nginx.service
           ├─2064 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
           ├─2066 nginx: worker process
           ├─2068 nginx: worker process
           ├─2071 nginx: worker process
           └─2072 nginx: worker process

اکنون اگر از طریق مرورگر خود IP سرور یا دامنه مورد نظر را تایپ کنید باید خروجی به شکل ذیل مشاهده کنید :

2.MySQL

اگر از اوبنوتو 18.04 استفاده می کنید به صورت پیش فرض در مخرن بسته APT موجود است، برای نصب آن از دستور زیر استفاده کنید.

apt-get install mysql-server

پس از نصب MySQL بر روی سرور خود از شما گذرواژه را نمی خواهد یا تغییرات پیکربندی دیگر را انجام دهید، اکنون این امر باعث می شود نصب MySQL ناامن باشد، برای همین امر دستور بعدی اجرا کنید.

 mysql_secure_installation

این امر ما را از طریق مجموعی از درخواست راهنمایی می کند که در آن می توانیم تغییراتی در گزینه های امنیتی نصب MySQL خود ایجاد کنیم. مانند تعیین رمزعبور برای کاربر اصلی و غیره. از طریق دستور زیر میتوانید برای کاربر اصلی یک رمزعبور تعیین کنید با دستورات SQL خود را جرا کنید.

mysql -u root -p

پس از انجام تمام فرایند های ذکر شده باید وضعیت فعال بودن سرویس MySQL خود را از طریق دستور بعدی چک کنید.

systemctl status mysql

خروجی :

// Output
● mysql.service - MySQL Community Server
   Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled)
   Active: active (running) since Sun 2019-06-09 00:00:00; 3h 53min ago
  Process: 1948 ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid (code=exited, status=0/SUCCESS)
  Process: 1792 ExecStartPre=/usr/share/mysql/mysql-systemd-start pre (code=exited, status=0/SUCCESS)
 Main PID: 1950 (mysqld)
    Tasks: 28 (limit: 4915)
   CGroup: /system.slice/mysql.service
           └─1950 /usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid

و در آخر شما باید یک کاربر و دیتابیس ایجاد کنید بر روی سرویس MySQL خود که به ترییب دستورات زیر را وارد کنید .

۲.۱ ورود به MySQL

mysql -u root -p

۲.۲ تعریف کاربر جدید و اعمال دسترسی ها

mysql> GRANT ALL PRIVILEGES ON *.* TO 'username'@'localhost' IDENTIFIED BY 'password';

پس از ایجاد کاربر با دستور \q از سرویس MySQL خود خارج شوید و بعد با دستور بعدی با کاربر جدید وارد شوید.

mysql -u username -p

۲.۳ ایجاد دیتابیس

CREATE DATABASE dbname;

۳. PHP

اگر از اوبنوتو 18.04 استفاده می کنید به صورت پیش فرض در مخرن بسته APT موجود است، برای نصب آن از دستور زیر استفاده کنید.

sudo apt install php8.0

با دستور زیر از ورژن PHP نصب شده مطما شوید.

php -v

برای نصب PHP در کنار Nginx باید بسته FPM را نصب کنید .

sudo apt install php8.0-fpm

سپس تمام php-extensions های مورد نیاز را نصب کنید.

sudo apt install php8.0-common php8.0-mysql php8.0-xml php8.0-curl php8.0-gd php8.0-imagick php8.0-cli php8.0-dev php8.0-imap php8.0-mbstring php8.0-opcache php8.0-soap php8.0-zip -y

همانطور که می دانید توسط Composer تمام بسته های PHP مدیریت می شود، اکنون بعد از نصب موارد بالا حال می خواهیم Composer را هم نصب کنیم. دستورات زیر را به ترتیب اجرا کنید در بالا لینک نصب و پیکربندی از از روی سایت composer هم لینک داده شده است.

cd ~
curl -sS https://getcomposer.org/installer -o composer-setup.php

و بعد از آن توسط دستور زیر شروع به نصب کنید.

php composer-setup.php --install-dir=/usr/local/bin --filename=composer

در آخر با زدن دستور زیر شما composer را نصب دارید

composer

پیکربندی و راه اندازی برنامه

پس از انجام تمام موارد بالا مسیری که برای میزبانی برنامه های خود در نظر گرفته می شود در این مسیر /var/www/html می باشد. من با در نظر گرفتن اینکه شما Git را میدانید بقیه مقاله را ادامه می دهم، البته در یک مقاله دیگ سعی میکنم راه اندازی FTP سرور راه هم پوشش بدهم ولی فعلا مبنا Git می باشد .

با رفتن به مسیر /var/www/html مخزن خود را با دستور زیر clone کنید.

git clone https://github.com/username/project-name.git

سپس با دستورات زیر :

cp .env.example .env
nano .env

و باز کردن فایل .env میتوانید تمام تنظیمات خود را نسبت به سروری که پیکربندی کردین تغییر دهید.

حال برای نصب وابستگی ها بسته ها خود بر روی اپلیکیشن دستور زیر را اجرا کنید.

composer update

با دستورات زیر تمام کش ها و لاگ های قبلا تست گرفته اید را میتوانید پاک کنید و کلید منحصر اپ خود را ایجاد کنید و عمل migrate دینابیس را انجام دهید.

composer dump-autoload
php artisan config:clear
php artisan key:generate
php artisan migrate
php artisan db:seed

اکنون موقع آن رسیده است که پیکربندی لاراول را بر روی Nginx انجام دهیم که وب سرور ما درخواست ها به درستی مدیریت کند مسیری که به صورت پیش فرض خود Nginx تعیین کرده است این /etc/nginx/sites-available/default.conf مسیر می باشد. اولین دستور که باید تایپ کنید به شکل زیر می باشد :

nano /etc/nginx/sites-available/default.conf

تنظیمات زیر را جایگزین محتوای داخل فایل کنید :

// /etc/nginx/sites-available/default.conf file
server {
    listen 80;
    listen [::]:80;

    root /var/www/html/public;
    index index.php index.html index.htm index.nginx-debian.html;

    server_name <our.application.name>;

    location / {
    try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
      try_files $uri /index.php =404;
      fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;
      fastcgi_index index.php;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      include fastcgi_params;
    }

    location ~ /\.ht {
        deny all;
    }
}

به جای کلمه server_name در تنظمیات باید دامنه یا IP سرور خود را قرار دهید.

حال فقط کافی است که یک symbolic link به مسیر /etc/nginx/sites-enabled/ ایجاد کنیم.

ln -S /etc/nginx/sites-available/default.conf /etc/nginx/sites-enabled/

اکنون میتوانیم پیکربندی که انجام دادیم را با دستور زیر از صحت آن بر روی nginx مطما شویم و اگر پیغام زیر را دریافت کردید یعنی همچی به درستی انجام شده است.

nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

آخرین گامی که باید انجام دهید ریستارت کردن nginx است و اگر همچی به درستی انجام داده باشید سایت شما رور دامنه و یا IP بالا امده و میتوانید خدمات خود را به کابرانتان ارایه دهید.

systemctl restart nginx

کلام آخر

در این پست سعی کردم راهنمای کاملی به شما بدهم که چگونه می توانید برنامه Laravel خود را با Nginx در Ubuntu 18.04 در سرور به کار بگیرید. امیدوارم این مقاله به همه شما کمک کند.

۱۳ شهریور، ۱۴۰۰

٢ هفته پیش ١۵۰۰+ امتیاز
نویسنده @reskipper یک مقاله تازه به اسم معرفی مفاهیم asynchronous, promises, async/await در جاوا اسکریپت نوشت.

یکی از مفاهیم نسبتا سخت و پیچیده که بیشتر اوقات باعث گیج شدن و سردرگمی برخی از برنامه نویسان می شود مفهوم غیرهمزمان یا Asynchronous می باشد .

در اکثر مصاحبه ها دیده می شود که این مفهوم مورد سوال قرار میگیرد، من قصد دارم که این مبحث را یکبار باز کرده تا کسانی که میخواهند درکی از برنامه نویسی ناهمزمان داشته باشند کمکی کرده باشم.

این بخش سه قسمت دارد :

  1. asynchronous JS
  2. Promises
  3. async/await

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

موضوع غیر همزمان بودن در دو بخش سرور و کلاینت مورد اهمیت می باشد ولی در این مقاله بیشتر بر روی کلاینت تمرکز میکنم ولی در اینده حتما برای باز کردن مباحث بیشتر مایلم آن را به بخش سرور ببرم.

ابتدا باید بدانیم که جاوا اسکریپت همیشه همزمان و تک رشته ای است. به عبارت دیگر ، هنگامی که یک بلوک کد اجرا می شود، هیچ بلوک دیگری از کد اجرا نمی شود.

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

برنامه های که با جاوا اسکرپیت نوشته می شوند معمولا تحت وب و رویداد محور هستن. به عبارت دیگر، جاوا اسکریپت تا زمانی که کاربر بر روی چیزی کلیک نکند یا ضربه نزد رویدادی اتفاق نمی افتد (سمت مشتری). در بخش دیگر که سرور قرار دارد و مبتنی بر JS می باشد منتظر می باشد که در سمت کلاینت از طریق اینترنت درخواستی به آن ارسال شود.

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

شما تصور کنید که تصویری با حجم زیادی از سمت سرور باید از بالای سایت شما بارگذاری شود، اگر سرور برای بارگذاری کردن این تصویر باید منتظر بمانند تا فرایند آن از سمت سرور به پایان برسد و بعد به سراغ بارگذاری بقیه محتوای سایت برود حتما این موضوع برای کاربر های شما جالب نمی باشد و عملکرد سایت شما را پایین می آرود زیرا نمی دانید این فرایند قرار است چقد طول بکشد.!

برنامه نویسی ناهمزمان توسط Callback ها

قبل از اینکه وارد Promise ها بشویم اساسی ترین مفهومی که باید بفهمیم فراخوانی می باشد (گذراندن یک تابع دیگر در یک تابع و هنگامی که شرایطی برآورده می شود یا رویدادی رخ می دهد، فراخوانی می شود).

همچنین روش قدیمی مدیریت برنامه نویسی ناهمزمان قبل از معرفی Promise در ES6 است. اما برخی از این callback ها هنوز معمولاً بدون promise دیده می شوند.

اولین آرگومان ()setTimeOut یک تابع callback و آرگومان دوم یک فاصله زمانی است که بر حسب میلی ثانیه اندازه گیری می شود.

معرفی Promise ها

Promises در ES6 برای ساده سازی برنامه نویسی ناهمزمان یا نامتقارن معرفی شدند. در این بخش به موارد زیر می پردازیم:

  • چرا promise ها معرفی شدند؟‌ (هشدار خرابکاری:‌ مشکل در فراخوانی و شلوغی callback ها)
  • تمام promise ها به ما قول میدهند که پاسخ را در سه حالت برگرداند : (then, catch, finally)

حال باید مثالی بزنیم شما تصور کنید در کافه ای میخواهید قهوه ای سفارش دهید در سه مرحله باید این فرایند اتفاق یبفتد ابتدا باید تصمیم بگیرید که چه نوع قهوه ای می خواهید، سپس سفارش خود را با باریستا ثبت کنید، سپس قهوه خود را دریافت کنید، آخرین و مهمترین، نحوه فراخوانی مجدد ظاهر می شود (اشاره به سند MDN در promise) :

chooseCoffee(function(order) {
  placeOrder(order, function(coffee) {
    drinkCoffee(coffee);
  }, failureCallback);
}, failureCallback);

ظاهر بسیار کثیفی دارد! این همان چیزی است که اغلب به عنوان callbacks-hell یا جهنم فراخوانی ها‍‍‍ نامیده می شود. promise ها اجازه می دهند این نوع callback های تو در تو به عنوان زنجیره promise مجدداً بیان شوند، که در ادامه مقاله بیشتر به آنها می پردازیم.

قاعد کلی تعریف promise به شکل زیر می باشد :

let promise = new Promise(function(resolve, reject) {
  // executor
});

آرگومان ها resolve و reject در callback آبجکت promise که توسط جاوا اسکریپت ارائه شده است فراخوانی می شوند.

در اینجا شما با سه مفهوم رو به رو می شوید که به شرح ذیل می باشد :‌

  • pending: هنگامی که promise ایجاد می شود، در حالت موفقیت یا شکست قرار می گیرد.
  • resolved: هنگامی که promise بازگشت داده می شود و در حالت حل شده قرار می گیرد.
  • fulfilled: هنگامی که promise با موفقیت حل می شود مقدار را برمیگرداند که میتوان با زنجیره زدن then به مقدار آن دسترسی پیدا کرد.
  • rejected:‌ هنگامی که promise بدون موفقیت حل می شود که یک پیغام خطا را برای رد شدن آن برمی گرداند که با زنجیره زدن catch به مقدار آن می توان دسترسی پیدا کرد.

شکل زیر نمایانگر فرایند اجرای promise می باشد:

قطعه کد زیر یک promise کامل را با تمام حالت ها نمایش میدهد :

let example = () => {
   return new Promise(function(resolve, reject) => {
     let value = function1();
     if (job success) {
       resolve(value);
     } else (job unsuccessful) {
       reject(console.log("something's wrong!! :("));
     }
   }).then(function(value)) {
     // success
     return nextFunction(value);
   }).catch(rejectFunction);
  }

مفهوم async / awiat

کلمات کلیدی async و await در ES2018 برای کاهش دیگر تکرارات و حل محدودیت "در شکستن زنجیره" در promise ها معرفی شد.

بیایید تفاوت بین Promises و async/await را ببینیم!

promise:

const promise = () => {
  return new Promise(resolve => {
    setTimeout(() => resolve("done!"), 1000);
  })
};

async/await :

const promise = async () => {
  console.log(await promiseAsync());
};

در نتیجه هنگامی که از async/await استفاده می شود، then/catch به ندرت استفاده می شود. چرا که در درون خود مقادیر به صورت مستفیم به promise مورد نظر برمیگردند و دیگر نیازی به نوشتن زنجیره ای برای آنها نیست .

نتیجه گیری

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

۱۲ شهریور، ۱۴۰۰

٢ هفته پیش ١۵۰۰+ امتیاز
نویسنده @reskipper یک مقاله تازه به اسم مفاهیم اولیه Node.js نوشت.

یک برنامه تحت وب را تصور کنید که در هر ثانیه صدها درخواست را در ثانیه به سرور ارسال می کند که قبل از انتقال به درخواست دیگر، هر بار فقط یک درخواست را پردازش کند! احتمالا با مشکلات عملکردی روبرو خواهید شد و تجربه بدی را برای کاربران خود فراهم می سازید.

Node js در سال ۲۰۰۹ توسط Ryan Dahl توسعه دهنده وب ایجاد شد چرا که در هنگام توسعه به جریان ورودی خروجی های شدید و برنامه نویسی همزمان و سیستم عامل های چند رشته در سمت سرور با مشکلات شدید روبرو شد.

بنابراین نود جی اس فناروی است برای حله مقابله با رویدادهای ورودی و خروجی (intense I/O) ناهمزمان شدید، خب بهترین زبان که ظرفیت این کار را دارد نیز جاوااسکریپت است.

خب در این مقاله من قصد دارم تجربه شخصی خودم و مطالعاتی که در مورد این زبان مدرن سمت سرور را دارم با شما به اشتراک بگذارم و سوالات و چرایی های که افراد میخواهند از این زبان استفاده کنند را جواب بدهم.

۱. نود جی اس چیست ؟

به زبان ساده بخواهم برایتان بگویم یک پلتفرم منبع باز جاوا اسکریپت برای برنامه نویسی سمت سرور است که بر روی موتور Chrome's V8 JavaScript ساخته شده است، به این معنی که موتور جاوا اسکرپیت را در مروگر وب کامپایل می کند و همانطور موتور نود جی اس را در آن اجرا می کند.

چنین هسته ای در کنار مروگر باعث می شود برنامه های تحت وب که با نود جی اس نوشته شده است با سرعت بالا اجرا بشوند.

۲. چرا نود جی اس ؟

نود جی اس یک پلتفرم قدرتمند برای توسعه برنامه های مدرن وب در سمت سرور می باشد! این زبان بخاطر پایدار بودن و قابل اعتماد بودن مورد توجه شرکت های جهانی از قبیل : Netflix, Uber, LinkedIn and PayPal .

معماری های رویداد محور به دلیل ویژگی های تک رشته ای (Single-Thread) همراه با یک پلتفرم چند رشته ای (Multi-Thread) که در پس زمینه اجرا می شود این زبان برای برنامه های با ورودی و خروجی (intense I/O) شدید بسیار مناسب است که این امر باعث بهبود عملکرد و کمتر شدن سخت افزار برای خدمات به مشتریان می شود.

2.1 Non-Blocking I/O

روش غیر مسدود کردن (Non-Blocking) یک ورودی را دریافت کرده و خروجی را به صورت ناهمزمان برمی گرداند، این عمل برای سرور این امکان فراهم می کند که بتواند تعداد زیادی درخواست را بدون مسدود کردن برنامه دریافت کند، در حالی که پاسخ در پس زمینه پردازش می شود.

2.2 Single Thread

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

این ویژگی با استفاده از حافظه کم و ظرفیت زیر ساختی برای پردازش تعداد زیادی از درخواست ها آن را سبک، مقایس پذیر و کارامد می کند.

۲.۳ Event Driven

نود جی اس یک فناوری رویدادگرا است، بدین معنی که جریان کنترل این پلتفرم سمت سرور توسط وقوع رویدادها هدایت می شود.

بنابراین در لحظه که یک برنامه تحت Node شروع به کار می کند یک شنونده رویداد به نام Event Loop شروع به انتظار رویداد می کند و تا خاموش شدن برنامه متوقف نمی شود. به عنوان مثال یک پیشخدمت رستوان که در هر لحظه آماده دریافت سفارش مشتری تا زمان بسته شدن رستوران باشد.

تصویری که در پایین مشاهد می کنید چرخه حیات رویداد مشخص می کند.

۲.۴ Node Package Manager

Node Package Manager بزرگ ترین کتابخانه متن باز در جهان است تمام ابزار های که برای برنامه در حال توسعه خود با نود جی اس نیاز دارید را میتوانید توسط آن نصب و استفاده کنید و حتی اگر بخواهید میتوانید بسته های را برای خود توسعه داده و به عنوان یک کتابخانه بر روی آن قرار دهید تا بقیه توسعه دهندگان از آن استفاده کنند.

۲.۵ No Buffering

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

2.6 Scalable

مقیاس پذیری ویژگی اصلی نود می باشد، زیرا ظرفیت بالایی در رسیدگی به حجم زیادی از درخواست ها را به صورت غیرهمزمان با زیر ساخت کم از طریق معماری آن دارد.

بر روی یک نخ واحد همراه با پلتفرم چند رشته ای کار می کند و به این ترتیب هزاران رویداد همزمان را دریافت و مدیریت می کند.

۳ Architecture Node.js

معماری نود جی اس دارای سه عنصر کلیدی است که مانند یک کارخانه پردازش رویداد باهم دیگر کار می کنند، بنابراین برای درک سهولت و نحوه تعامل این عناصر با یکدیگر یک مثال در نود جی اس میزنم.

فرض کنید یک مشتری چندین درخواست به این برنامه ارسال می کند:

۳.۱ Event Queue

به محض رسیدن این درخواست ها به برنامه، آنها به صف رویداد (Event Queue) می روند، صفی که در آن تمام رویداد های رخ داده در برنامه اتفاق می افتد و در آنجا منتظر ارسال شدن هستند، آنها برای پردازش در چرخه ای به نام Event Loop به سر می برند.

۳.۲ Event Loop

همگامی که یک درخواست (عملیات مسدود سازی) در حلقه رویداد وارد می شود، یک پلتفرم تک رشته ای است که موتر ٰV8 در هسته خود برای کامپایل جاوااسکرپیت اجرا می کند، بعد از آن به پلتفرم Thread Pool واگذار می شود تا در پس زمینه پردازش شود، بنابراین با این جریان معماری نخ اصلی برای رسیدگی به بقیه رویداد ها در دسترس قرار می گیرد.

۳.۳ Thread Pool

یک پلتفرم چند رشته ای است که کتابخانه ای به نام libuv را اجرا می کند و C++ را در هسته خود دارد، درخواست (Blocking Operation) به صورت ناهمزمان در پس زمینه پردازش اجرا می شود تا کامل شود و اماده بازگشت باشد.

نتیجه گیری

امیدوارم این مقاله به شما کمک کنند نه تنها نحوه عملکرد Node.js را درک کنید، بلکه همچنین بدانید چرا نود جی اس به این سرعت رشد کرده و در حال حاضر در اکثر شرکت ها و استارت آپ ها مورد استفاده قرار می گیرد.

در دنیایی مدرن و فوق العاده متصل به هم، فناوری ای که بتواند با زیرساخت های پایین به سرعت مقیاس بندی شود، مطمئناً مهره مهمی است که باید به آن توجه کرد.

٢ هفته پیش ١۵۰۰+ امتیاز
نویسنده @reskipper یک مقاله تازه به اسم ۸ دلیل که چرا PHP هنوز برای توسعه دهندگان مهم است نوشت.

PHP یک زبان سمت سرور است که بیش از ۲۵ سال است که وجود دارد و امروزه تمایل زیاد دارد که نظرات قوی را در میان توسعه دهندگان برانگیزد که چرا از زبان پی اچ پی استفاده می شود.!

هر زمان که یک زبان برنامه نویسی یا ابزار جدید ظاهر می شود، شما احتمالا در انجمن ها و گفتگو ها در مورد این می شنوید که PHP مرده است.!

این درست است که PHP بین رتبه بندی محبوب ترین زبان های برنامه نویسی از نظر رتبه در سال ۲۰۰۷ (رتبه ۵) و در سال ۲۰۲۰ در رتبه (۸) در میان توسعه دهندگان سایت Stack Overflow قرار گرفته است و این یک روند رو به کاهش بوده است ولی با این وجود تقریبا ۸۰٪ از همه وب سایت ها از PHP استفاده می کنند و حتی برخی از پتلفرم های اصلی مثل وردپرس و یا facebook هنوز از آن استفاده می کنند.

تصویر بالا نمایان این است که چه ترافیکی توسط چه زبان های از سایت های مختلف عبور کرده است.

چرا PHP هنوز به صورت گسترده استفاده می شود ؟

هماهنطور که می دانید PHP (Hypertext Preprocessor) یک ابر پردازنده متن می باشد و به عنوان یک زبان برنامه نویسی همه منظوره شناخته می شود که می تواند برای توسعه وب سایت ها پویا و تعاملی مورد استفاده قرار گیرد. زبان PHP یکی از اولین زبان های بود که میتوانست در بین HTML جایگذاری شود، و این امکان این شرایط و فراهم می کرد بدون نیاز به فراخوانی داده ها و استخراج کردن آنها، کد های PHP را در بین تگ ها HTML به صورت آسان استفاده کنیم.

استفاده از PHP در طی سالها تکامل یافته است و حالا با ارتقاء مداوم (نسخه PHP 8.0 در نوامبر ۲۰۲۰ منتشر شد) آن ویژگی ها جدید اضافه کرده و قفل قابلیت ها جدید در بین زبان ها دیگر را باز کرده است.

<!DOCTYPE html> 
<html> 
  <head>
    <title>Example</title>
 </head>
<body>
  <!--?php echo "Hi, I'm a PHP script!"; ?--> 
</body> 
</html>

اگر چه این زبان جزو بهترین زبانها در نظر گرفته نمی شود ولی من قصد دارم برخی از مزیت های کلیدی این زبان اشاره کنم که دلیل اصلی توسعه آن در بین توسعه دهندگان می باشد.

۱. یادگیری و استفاده از آن آسان است : یکی از دلیلی رایج استفاده از PHP این است که استفاده از آن آسان است، حتی بدون داشتن دانش گسترده و تجربه در زمینه توسعه وب اکثر افراد می توانند در مدت زمان نسبتا کوتاهی یک صفحه وب یا فایل PHP ایجاد کنند، سادگی قاعده نوشتن کد و استفاده از توابع آن باعث یادگیری سریع این زبان شده است این تعاریف بدین معنا می باشد که موانع ورود برای یادگیری این زبان خیلی کمتر از زبان های دیگر می باشد.

۲. متن باز است (open source) :‌ این به توسعه دهندگان کمک می کند تا با زبان PHP شروع به کار کنند، می توان آن را به سرعت و بدون هزینه نصب کرد.

همچنین دسترسی باز به طیف گسترده ای از چهارچوب های PHP از قبیل :‌ Laravel و Symfony می توان اشاره کرد. این ویژگی برای بسیاری از شرکت ها جذاب است زیرا به کنترل هزینه های توسعه وب کمک می کند.

۳. همه کاره است : یکی از مهمترین مزیت های PHP مستقل بودن از پلتفرم می باشد، به این معنی که می توان آن را در سیستم عامل های مختلف از قبیل Mac ، Windows ، Linux و اکثر مروگر های وب استفاده کرد و همچنین از اکثر وب سرور های اصلی پشتیبانی می کند و استقرار آن در سیستم ها و سیستم عامل های مختلف را با حداقل هزینه اضافی آسان می کند.

۴.از پشتیبانی جامعه قوی برخوردار است (community) :‌ به عنوان یک زبان برنامه نویسی قدیمی که به طور گسترده مورد استفاده قرار می گیرد PHP دارای یک پایگاه اجتماعی بزرگ و وفادار می باشد که از آن حمایت می کنند در آن تعداد زیادی آموزشی و پرسش و پاسخ و راهنمایی وجود دارد که به توسعه دهندگان جدید کمک می کند تا آسان تر مسیر خود را برای یادگیر پیدا کنند این مسیر از طریق بروز رسانی های که PHP انجام می دهد همیشه ادامه دارد.

۵.سریع و ایمن است:‌ دو مورد از ویژگی ها که سازمان ها میخواهند جزو ویژگی زبان توسعه آنها باشد ایمن و سریع بودن آن زبان است، PHP از حافظه خود استفاده می کند و این امر از نظر سرعت می تواند به خوبی رقابت کند، همچنین در ورژن های جدید PHP از نظر امنیت در جایگاه بالاتری نسبت به ورژن های قدیمی تر دارا می باشد.

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

۶. اتصال به پایگاه داده : PHP اتصال ایمن را تقریبا با هر نوع پایگاه داده آسان می کند، این امر به توسعه دهندگان آزادی بیشتر می دهد تا انتخاب کنند که کدام پایگاه داده در حال توسعه بهتر می باشد.

۷. آزمایش شده است : بدین معنی می باشد که کدهای PHP در یک ربع قرن اول در محیط های واقعی آزمایش شده است و اشکالات اصلی پیدا شده و برطرف شده است و این امر باعث می شود زبان مورد نظر در بین توسعه دهندگان مورد اعتماد باشد.

علاوه بر این چهاچوب ها و ابراز های زیادی در طول زمان ساخته شده است که به ایمن تر و کارامد تر شدن این زبان در توسعه PHP کمک می کند.

۸. کد های قدیمی PHP وجود دارد : این امر به تنهایی مزیت محسوب نمی شود بلکه وقتی تعداد زیادی از وب سایت های موجود با PHP نوشته شده اند به یک ملاحضه مهم تبدیل می شود، به زبان آسان تر بهتر است بروز رسانی ها را با یک زبان انجام دهید تا این که با یک زبان دیگر همه چیز را باز نویسی کنید، این امر به خودی خود کمک می کند که توسعه دهندگان آن بجای مهاجرت از یک زبان جدید دیگر خود زبان اصلی که با آن سرویسی را توسعه داده اند را بروز رسانی کند.

همچنین یافتن افرادی که توسعه زبان PHP را انجام میدهند آسان تر هست ولی در صورت که مهارت های لازمه را داشته باشند.

نتیجه گیری

در نهایت، زبان انتخاب شما بستگی به این دارد که میخواهید که چه چیزی را بسازید و چه ویژگی های را در اولویت قرار دهید.