<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های سید محمدرضا سید اسمعیل</title>
        <link>https://virgool.io/feed/@seyedmr</link>
        <description>توسعه دهنده بک‌اند</description>
        <language>fa</language>
        <pubDate>2026-06-16 22:45:41</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/1599660/avatar/8TQagE.jpeg?height=120&amp;width=120</url>
            <title>سید محمدرضا سید اسمعیل</title>
            <link>https://virgool.io/@seyedmr</link>
        </image>

                    <item>
                <title>همه چیز در مورد PSR (بخش سوم)</title>
                <link>https://virgool.io/@seyedmr/all-about-psr-part-3-sl7inr2uuhi2</link>
                <description>سلام خدمت همه شمامدت زیادی بود میخواستم این پست رو منتشر کنم ولی کار پیش میومد و وقت نمیشد بشینم و این کار رو تمومش کنم اما بالاخره پس از مدت ها نشستم و کارشو تموم کردم :)توی این پست تمرکز اصلی من روی psr-12 بود و psr-7 و psr-11 رو به صورت اجمالی توضیح دادم که فقط باهاشون آشنا باشید. اگر عمری باقی باشه اینا رو هم مفصل توضیح میدم بهتون.اینکه خیلی روی psr-12 وقت گذاشتم دلیلش اینه که خیلی توی کار تیمی کمکم کرده و وجود این استاندارد باعث میشه که کل تیم یه حداقل هایی رو رعایت کنند تا کدها یک‌دست باشه و موقع خوندن پروژه، سردرگمی کمتر بشه.خب دیگه بریم سراغشون...PSR-7: HTTP message interfacesهمونطور که میدونید psr میاد و یه سری قوانین و استاندارد برای کارهای مختلف وضع میکنه. داخل این سند هم اومدن و یه استاندارد برای چگونگی کار کردن با HTTP Message ها ارائه دادن. یه پکیج هم براش ارایه دادن که یه سری اینترفیس داخلش هست تا با استفاده از اون ها بتونیم ساختار متناسب با PSR 7 رو پیاده سازی کنیم. این پکیج شامل دو اینترفیس RequestInterface و ResponseInterface که به ترتیب برای دریافت پارامتر ها و برای ارسال پارامتر ها با استفاده از پروتکل Http می‌باشد.در صورتی که با فریم‌ورک لاراول کار کرده باشید، کار کردن با این ساختار رو تا حدودی تجربه کردید.توضیح دادن این استاندارد پیچیدگی خاصی داره که توی این سری مقالات نمی‌گنجه. ایشالا این مدل استاندارد ها رو توی پست‌های جداگانه‌ای بهتون معرفی خواهم کرد.PSR-11: Container interfaceحتما تا حالا اسم کانتینر یا IoC Container به گوشتون خورده! اگر با این مفاهیم آشنا نیستید بهتره اول اینجا رو مطالعه کنید.ما توی php ، تعداد زیادی پکیج برای پیاده‌سازی این سیستم داریم. برای مثال میشه موارد زیر رو نام برد:AcclimateAura.DIdcp-diMoufPHP-DIZend ServiceManagerکار psr هم اینه که بیاد و برای ما استاندارد‌هایی رو بیاره که برنامه‌نویس‌ها راحت‌تر بتونن با کدهای همدیگه ارتباط بگیرن. خب بسم‌الله! این‌هم یه زمین عالی برای بازیِ بچه‌های PHP-FIG !داخل psr-11 یه ساختاری بیان شده که همه بیان و از اون برای ساخت کانتینر‌هاشون استفاده کنند.این psr چندتا اینترفیس رو برای ما میاره که که در ادامه با مهم‌ترین اونها آشنا میشیم.&lt;?php
namespace Psr\Container;
/**
 * Describes the interface of a container that exposes methods to read its entries.
 */
interface ContainerInterface
{
    /**
     * Finds an entry of the container by its identifier and returns it.
     *
     * @param string $id Identifier of the entry to look for.
     *
     * @throws NotFoundExceptionInterface  No entry was found for **this** identifier.
     * @throws ContainerExceptionInterface Error while retrieving the entry.
     *
     * @return mixed Entry.
     */
    public function get($id);

    /**
     * Returns true if the container can return an entry for the given identifier.
     * Returns false otherwise.
     *
     * `has($id)` returning true does not mean that `get($id)` will not throw an exception.
     * It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`.
     *
     * @param string $id Identifier of the entry to look for.
     *
     * @return bool
     */
    public function has($id);
}در تمام IoC Container هایی‌که این استاندارد رو رعایت کردند (از جمله کانتینر لاراول)، ما این متد‌ها رو داریم و می‌تونیم ازشون استفاده کنیم.دو اینترفیس دیگه‌ای که این psr داره برای اکسپشن‌هایی هستش که این متدها دارند.PSR-12: Extended Coding Styleاین psr یکی از مهم‌ترین استاندارد‌ها هستش که رعایت اون میتونه کلی دعای خیر براتون به‌همراه داشته باشه :)توی پست‌های قبلی با psr-1 آشنا شدیم. آشنایی با PSR-1حالا توی این PSR می‌خوایم یه سری قراردادهای حرفه‌ای تر برای کد‌نویسی رو یاد بگیریم.این PSR خیلی جزئی تر از PSR-1 هستش. با رعایت این استانداردها برنامه‌نویس‌ها کمتر سردرگم میشن و همکاری بین گروه‌های مختلف توسعه راحت‌تر انجام میشه.اولین قانون PSR-12 اینه که از قوانین PSR-1 تبعیت کنیم.بعد از این مورد میریم سراغ یه سری قوانین عمومی.قوانین عمومیتمام فایل های PHP باید از Unix LF به عنوان line ending استفاده کنند. کاراکتر LF (مخفف Line Feed) کاراکترهایی برای کنترل پایان خطوط در یک فایل هستن. در واقع کامپیوترها برای اینکه بفهمن یک خط کجا تموم شده و باید به خط بعدی برن از این کاراکتر ها استفاده می کنن اما شما نمی‌تونید اونا رو ببینید. ما برای اعلام پایان خط دو نوع کاراکتر CR و LF داریم که به ترتیب کدهای 0x0D و 0x0A هستند. ویندوز برای اعلام انتهای خط از هر دو کاراکتر CR LF، سیستم های Unix مانند لینوکس از LF و سیستم های مک (کمپانی اپل) از CR استفاده می کنن. احتمالا شما این مقادیر را به شکل r\ برای CR و n\ برای LF دیده باشید (ویندوز از r\n\ استفاده می‌کنه). PSR-12 میگه که فایل های PHP شما باید از LF استفاده کنن.تگ پایانی PHP که به شکل &lt;? هستش، باید در فایل‌هایی که فقط کد PHP دارند حذف بشه.  همچنین در انتهای خطوط نباید فضای خالی (whitespace) باشه.هر خط نباید از ۸۰ کاراکتر بیشتر باشه و اگر اینطور شد باید اون خط رو به دو یا چند خط تقسیم کرد. همچنین هر خط فقط باید یک statement داشته باشه. برای indent کردن (تورفتگی خطوط) باید از چهار اسپیس استفاده بشه و استفاده از tab ممنوعه.تمام کلمات کلیدی و رزرو شده در PHP باید با حروف کوچک نوشته بشن. همچنین استفاده از کلمات مشخص کننده نوع داده باید با حروف کوچک باشه؛ به طور مثال به جای boolean از bool و به جای integer از int استفاده کنید.قوانین declaration ها، namespace ها و import هازمانی که تگ های آغازین PHP را می‌نویسین باید اون‌ها رو در خط خودشون بنویسید و هیچ اطلاعات دیگه‌ای توی اون خط نباشه مگر اینکه کدهای PHP شما با کدهای دیگه‌ای مثل HTML ترکیب شده باشن. در واقع ابتدای فایل PHP یا header آن باید به ترتیب لیست زیر باشه. البته اگه اسکریپت شما به یکی از این موارد نیازی نداشت، اون رو نادیده بگیرید اما ترتیب باید حفظ شود:تگ آغازین PHP که به شکل php?&gt;خطوط docblockیک یا چند دستور declareتعریف namespace برای فایل (namespace declaration)یک یا چند دستور use برای استفاده از کلاس هایک یا چند دستور use برای استفاده از توابعیک یا چند دستور use برای استفاده از ثابت هابقیه کدهای فایلدستورات import (وارد کردن منابع در فایل) نباید با علامت backslash شروع بشن بلکه همیشه آدرس باید به صورت کامل نوشته بشه. کد زیر یه مثال کامل از تمام این دستورات هستش:&lt;?php

/**
 * This file contains an example of coding styles.
 */

declare(strict_types=1);

namespace Vendor\Package;

use Vendor\Package\{ClassA as A, ClassB, ClassC as C};
use Vendor\Package\SomeNamespace\ClassD as D;
use Vendor\Package\AnotherNamespace\ClassE as E;

use function Vendor\Package\{functionA, functionB, functionC};
use function Another\Vendor\functionD;

use const Vendor\Package\{CONSTANT_A, CONSTANT_B, CONSTANT_C};
use const Another\Vendor\CONSTANT_D;

/**
 * FooBar is an example class.
 */

class FooBar
{
    // ... additional PHP code ...
}namespace های ترکیبی (compound namespace) که بیشتر از دو سطح داشته باشن مجاز نیستن. به طور مثال کد زیر یه نمونه غلط و غیر مجاز از وارد کردن namespace ها هستش:&lt;?php

use Vendor\Package\SomeNamespace\{
    SubnamespaceOne\AnotherNamespace\ClassA,
    SubnamespaceOne\ClassB,
    ClassZ,
};کد زیر هم نمونه یه کد صحیح و مجاز از وارد کردن namespace هاست:&lt;?php

use Vendor\Package\SomeNamespace\{
    SubnamespaceOne\ClassA,
    SubnamespaceOne\ClassB,
    SubnamespaceTwo\ClassY,
    ClassZ,
};توجه داشته باشید که این قانون مخصوص namespace های ترکیبی (compound namespace) هستش و ربطی به namespace های ساده نداره. ینی اگر می‌خواستید یه نیم‌اسپیس معمولی بنویسید، نگران چیزی نباشید و راحت کارتون رو بکنید.در صورتی که کدهای PHP شما با کدهای دیگه‌ای مثل HTML ترکیب شدن و می‌خواید strict_type رو هم فعال کنید باید اون رو توی خط اول و در کنار تگ آغازین PHP قرار بدید. همچنین حتما باید تگ PHP رو ببندید. مثال:&lt;?php declare(strict_types=1) ?&gt;
&lt;html&gt;
&lt;body&gt;
    &lt;?php
        // ... additional PHP code ...
    ?&gt;
&lt;/body&gt;
&lt;/html&gt;دستورات declare نباید دارای فضای خالی (whitespace) باشن. همچنین اگر می‌خواید از دستورات block declare استفاده کنید حتما باید فرمتش به شکل زیر باشه (به مکان کروشه ها و فضای خالی دقت کنید):declare(ticks=1) {
    // some code
}قوانین کلاس ها، متدها و خصوصیات آن هامثل همیشه کلمه class به معنی class و trait و interface و موارد مشابه هستش. قانون اول اینه که بعد از کروشه پایانی (علامت })‌ نباید هیچ کامنت یا کدی (توی همون خط) قرار بگیره. برای ساخت یک نمونه/شیء از یک کلاس همیشه باید پرانتزها رو هم بزنید حتی اگر نیازی به هیچ آرگومانی نداشته باشیم:new Foo();دستورات extends و implements باید حتما توی همون خطی باشن که نام کلاس هستش و اجازه ندارن در خطوط بعدی نوشته بشن. کروشه آغازین برای باز کردن کلاس (علامت {)‌ باید حتما در خط خودش قرار بگیره. همچنین قبل یا بعد از این کروشه‌ها نباید خطی خالی وجود داشته‌باشه. کروشه پایانی هم باید بعد از بدنه کلاس و در خط دیگه‌ای قرار بگیره و قبل از اون خطی خالی وجود نداشته‌باشه. کد زیر یه نمونه ساده از این قوانین هستش:&lt;?php

namespace Vendor\Package;

use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class ClassName extends ParentClass implements \ArrayAccess, \Countable
{
    // constants, properties, methods
}لیست‌های دستورات implements و دستورات extends (در صورتی که برای interface ها باشه) می‌تونن به چند خط تقسیم بشن، البته به شرطی که indent (تورفتگی) بشن. در چنین حالتی اولین مورد باید از یه خط جدید شروع بشه و  هر interface هم فقط توی یه خط قرار بگیره:&lt;?php

namespace Vendor\Package;

use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class ClassName extends ParentClass implements
    \ArrayAccess,
    \Countable,
    \Serializable
{
    // constants, properties, methods
}اگر از دستور use برای استفاده از trait ها درون یک کلاس استفاده می‌کنین، باید اون‌ها رو توی یه خط جدا و دقیقا بعد از کروشه آغازین بنویسین:&lt;?php

namespace Vendor\Package;

use Vendor\Package\FirstTrait;

class ClassName
{
    use FirstTrait;
}در کد بالا توجه داشته باشید که حتی اگه یه کلاس فقط یه دستور use داشته باشه باید کروشه پایانی توی یه خط جدا قرار بگیره. همچنین اگه چندین دستور use داشته باشیم، نمی‌تونیم اون‌ها رو توی یه خط بیاریم بلکه باید هر کدوم رو توی یه خط جداگونه قرار بدیم:&lt;?php

namespace Vendor\Package;

use Vendor\Package\FirstTrait;
use Vendor\Package\SecondTrait;
use Vendor\Package\ThirdTrait;

class ClassName
{
    use FirstTrait;
    use SecondTrait;
    use ThirdTrait;
}در صورتی که کلاس شما علاوه بر use، کدهای دیگه‌ای هم داشته باشه، باید یک خط بین این کدها و آخرین use فاصله بذارید:&lt;?php

namespace Vendor\Package;

use Vendor\Package\FirstTrait;

class ClassName
{
    use FirstTrait;

    private $property;
}همچنین هنگام استفاده از اپراتورهای insteadof و as باید دقیقا به شکل زیر عمل کنید (به فضای خالی، رفتن به خط جدید و تو رفتگی ها توجه کنید):&lt;?php

class Talker
{
    use A;
    use B {
        A::smallTalk insteadof B;
    }
    use C {
        B::bigTalk insteadof C;
        C::mediumTalk as FooBar;
    }
}خصوصیات و ثابت هاvisibility باید برای تمام خصوصیات مشخص بشه و نباید به مقادیر پیش فرض اتکا کنیم. همچنین اگه از PHP 7.1 به بعد استفاده می کنین، یعنی قابلیت مشخص کردن visibility برای ثابت‌ها رو هم دارید بنابراین باید این کار را انجام بدید. استفاده از کلیدواژه var برای ساخت خصوصیات مجاز نیست. در هر statement فقط باید یک خصوصیت را تعریف کنید و نباید همه رو با یک دستور بسازین. در برخی از زبان ها مانند جاوا اسکریپت مبحث visibility تعریف نشده بنابراین از قراردادهایی مثل شروع نام خصوصیات با آندرلاین (علامت _) برای مشخص کردن خصوصیات private استفاده میشه. توسعه‌دهنده‌ها اجازه ندارن از این قراردادها در زبان PHP استفاده کنن و اگه نام خصوصیتی با آندرلاین شروع بشه نباید معنی خاصی داشته باشه. همیشه باید بین تعیین تایپ (نوع داده) و خصوصیت یه اسپیس فاصله باشد. تعیین تایپ یک خصوصیت به شکل زیر انجام می‌شه:&lt;?php

namespace Vendor\Package;

class ClassName
{
    public $foo = null;
    public static int $bar = 0;
}همانطور که می بینید int به ما میگه که این خصوصیت یه عدد هستش.متدها و توابعVisibility باید برای تمام متدها تعریف شود. قراردادهایی مانند شروع نام متد با آندرلاین برای مشخص کردن private بودنشان پذیرفته نیست (درست مثل پراپرتی‌ها) و توسعه‌دهندگان نباید از چنین قراردادهایی استفاده کنند. البته نام متدهای شما می‌تواند با _ شروع بشه اما نباید به قصد مشخص کردن private یا protected باشه.نام متدها و توابع نباید بعد از خودشان اسپیس داشته باشن، بلکه کروشه آغازین باید به خط بعدی بره و کروشه پایانی نیز باید پس از بدنه تابع/متد و در خط خودش قرار بگیره. همچنین در نظر داشته باشید که نباید هیچ اسپیسی بعد از پرانتز آغازین و قبل از پرانتز پایانی وجود داشته باشه. با این حساب اگر بخواهیم یک مثال ساده از تعریف متدها بزنیم، کد زیر را نشان خواهیم داد (به محل پرانتزها، کاما ها (ویرگول انگلیسی)، اسپیس ها و کروشه ها دقت کنید):&lt;?php

namespace Vendor\Package;

class ClassName
{
    public function fooBarBaz($arg1, &amp;$arg2, $arg3 = [])
    {
        // method body
    }
}این قوانین برای توابع هم صدق میکنن:&lt;?php

function fooBarBaz($arg1, &amp;$arg2, $arg3 = [])
{
    // function body
}آرگومان‌های متدها و توابعدر لیست آرگومان‌ها نباید قبل از ویرگول‌ها اسپیس داشته باشیم بلکه یه اسپیس بعد از هر ویرگول قرار می‌گیره. همچنین آرگومان هایی که دارای مقدار پیش فرض هستن همیشه باید در آخر لیست قرار بگیرن (حتی در php8) :&lt;?php

namespace Vendor\Package;

class ClassName
{
    public function foo(int $arg1, &amp;$arg2, $arg3 = [])
    {
        // method body
    }
}همچنین میشه لیست آرگومان ها را بشکنیم به طوری که هر آرگومان در یک خط قرار بگیره و یک indentation (تو رفتگی) داشته باشه. توجه کنید که در این حالت باید آرگومان اول رو هم در یک خط جدید قرار بدید نه اینکه نقطه شکست از آرگومان دوم باشه.بنابراین نباید هیچ آرگومانی در کنار هیچ کدام از پرانتزهای آغازین و پایانی داشته باشیم:&lt;?php

namespace Vendor\Package;

class ClassName
{
    public function aVeryLongMethodName(
        ClassTypeHint $arg1,
        &amp;$arg2,
        array $arg3 = []
    ) {
        // method body
    }
}اگر متد/تابع شما دارای return type باشه (مشخص کرده باشید که چه نوع داده ای را بر می‌گردونه) باید بعد از علامت دو نقطه یک اسپیس قرار بدید و بعدش return type رو مشخص کنید. حواستون باشه که return type و علامت دو نقطه باید توی همون خطی باشن که پرانتز پایانی لیست آرگومان‌ها در اون قرار داره به طوری که بین علامت دونقطه و پرانتز پایانی هیچ اسپیسی نباشه:&lt;?php

declare(strict_types=1);

namespace Vendor\Package;

class ReturnTypeVariations
{
    public function functionName(int $arg1, $arg2): string
    {
        return &#039;foo&#039;;
    }

    public function anotherFunction(
        string $foo,
        string $bar,
        int $baz
    ): string {
        return &#039;foo&#039;;
    }
}در صورتی که میخواید nullable type declaration انجام بدید (اجازه بدهید یک آرگومان null یا دلخواه باشد) نباید بین علامت سوال و نام آرگومان هیچ فاصله‌ای وجود داشته‌باشه:&lt;?php

declare(strict_types=1);

namespace Vendor\Package;

class ReturnTypeVariations
{
    public function functionName(?string $arg1, ?int &amp;$arg2): ?string
    {
        return &#039;foo&#039;;
    }
}همچنین زمانی که از اپراتور reference (علامت &amp;) برای یک آرگومان استفاده می‌کنید، نباید بعد از اون هیچ فاصله‌ای باشه. این موضوع رو میتونید داخل کد بالا مشاهده کنید.آیا با variadic three dot operator یا به زبان ساده تر همون اپراتور splat در PHP آشنا هستید؟ این اپراتور اجازه میده که تعداد نامشخصی داده رو به یک آرگومان ارسال کنید. به‌طور مثال:unction concatenate($transform, ...$strings) {
    $string = &#039;&#039;;
    foreach($strings as $piece) {
        $string .= $piece;
    }
    return($transform($string));
}

echo concatenate(&amp;quotstrtoupper&amp;quot, &amp;quotI&#039;d &amp;quot, &amp;quotlike &amp;quot, 4 + 2, &amp;quot apples&amp;quot);
// This would print:
// I&#039;D LIKE 6 APPLESبه عبارتی اولین آرگومان پاس داده شده به تابع concatenate، رشته strtoupper هستش اما از آرگومان اول به بعد (دوم و سوم و چهارم الی بی نهایت - مقادیر I&#x27;d و like و 4+2 و apples) همه در رشته string$ قرار می گیرند یا به عبارتی جزئی از آرگومان دوم محسوب میشن. زمانی که از این اپراتور استفاده می‌کنید نباید بین اون و نام آرگومان هیچ فاصله‌ای وجود داشته‌باشه:public function process(string $algorithm, ...$parts)
{
    // processing
}همچنین زمانی که می خواهید از اپراتور reference و splat با هم استفاده کنید، نباید هیچ فاصله ای بینشون وجود داشته‌باشه:public function process(string $algorithm, &amp;...$parts)
{
    // processing
}کلیدواژه‌های abstract و final و staticاگر قصد استفاده از abstract یا final رو دارید، باید اون ها رو قبل از دستورات visibility بنویسید اما static همیشه بعد از visibility میاد. کد زیر این مسئله رو به خوبی نشون میده:&lt;?php

namespace Vendor\Package;

abstract class ClassName
{
    protected static $foo;

    abstract protected function zim();

    final public static function bar()
    {
        // method body
    }
}فراخوانی توابع و متدهازمانی که متد یا تابعی رو فراخوانی می کنید، نباید بین نام تابع/متد و پرانتز آغازین فاصله وجود داشته باشه. همچنین نباید هیچ فاصله‌ای بعد از پرانتز آغازین و قبل از پرانتز پایانی وجود داشته باشه. در لیست آرگومان‌ها هم نباید قبل از ویرگول‌ها فاصله‌ای باشه بلکه این فاصله بعد از ویرگول‌ها میاد. مثال:&lt;?php

bar();
$foo-&gt;bar($arg1);
Foo::bar($arg2, $arg3);اگر آرگومان‌های زیادی دارید، اجازه دارید اون‌ها را بشکنید به طوری که هر آرگومان در خط خودش قرار گرفته و یک indentation (تورفتگی) داشته باشه. در چنین حالتی اولین آرگومان در خطی جدید قرار می‌گیره:&lt;?php

$foo-&gt;bar(
    $longArgument,
    $longerArgument,
    $muchLongerArgument
);در صورتی که می‌خواید فقط یک آرگومان رو بشکنید (مثلا آرگومان شما یک anonymous function یا آرایه هستش) مجاز به انجام این کار هستین اما این شکستن به معنی شکستن خود لیست آرگومان‌ها نیست بلکه می‌تونید فقط همون تک آرگومان رو بشکنید:&lt;?php

somefunction($foo, $bar, [
  // ...
], $baz);

$app-&gt;get(&#039;/hello/{name}&#039;, function ($name) use ($app) {
    return &#039;Hello &#039; . $app-&gt;escape($name);
});ساختارهای کنترل کنندهدستورات کلی برای استفاده از ساختارهای کنترل کننده (هر ساختاری که اجرای کد رو کنترل می‌کنه - مثلا شرط if) اینطور هستش:باید بعد از کلیدواژه ساختار کنترلی حتما یک اسپیس وجود داشته باشد.نباید بعد از پرانتز آغازین هیچ فاصله‌ای وجود داشته باشد.نباید قبل از پرانتز پایانی هیچ فاصله‌ای وجود داشته باشد.باید بین پرانتز پایانی و کروشه آغازین یک اسپیس وجود داشته باشد.بدنه ساختار کنترلی باید یک واحد indent شود (تو رفتگی داشته باشد).بدنه ساختار کنترلی حتما باید بعد از کروشه آغازین و در خطی جدید قرار بگیره.کروشه پایانی حتما باید پس از بدنه و در خطی جداگانه قرار بگیره.توسعه‌دهندگان اجازه ندارند که از ساختارهای کنترلی بدون کروشه استفاده کنند. استفاده از کروشه‌ها باعث میشه که با اضافه شدن خط‌های جدید، ساختار خوانا و قابل خواندن باشه.ساختارهای کنترل کننده (شرطی)ساختار یک شرط if باید به شکل زیر باشه. در این ساختار به محل پرانتزها و دستورات else و elseif توجه داشته باشید:&lt;?php

if ($expr1) {
    // if body
} elseif ($expr2) {
    // elseif body
} else {
    // else body;
}دستورات درون پرانتزهای ساختارهای کنترلی رو میشه شکست. برای شکستن این دستورات باید از قوانین ذکر شده در قسمت قبلی (قرار گرفتن هر دستور در یک خط و indent شدن یک واحدی) پیروی کنید. در چنین حالتی اپراتورهای boolean همیشه باید یا ابتدای خط و یا در انتهای خط باشند و هر کدوم از این دو مورد رو که انتخاب کردید باید در کل کدها رعایت کنید:&lt;?php

if (
    $expr1
    &amp;&amp; $expr2
) {
    // if body
} elseif (
    $expr3
    &amp;&amp; $expr4
) {
    // elseif body
}ساختار switchیک دستور switch باید به شکل زیر نوشته بشه. دستور case همیشه باید یک واحد نسبت به switch تورفتگی داشته باشه اما دستور break (یا هر دستور دیگری که switch رو متوقف می‌کنه) باید نسبت به case فرورفتگی نداشته باشه. در صورتی که یک case داشته باشیم که خالی نباشه اما رد شدن از آن به صورت عمدی نوشته شده باشه (دستوری نداشته باشه که ما رو از switch خارج کنه)، باید یک کامنت به شکل no break براش بنویسید تا توسعه‌دهنده‌های دیگه مطمئن بشن که شما دچار اشتباه نشدید. شما می توانید تمام این موارد رو در کد نمونه زیر مشاهده کنید:&lt;?php

switch ($expr) {
    case 0:
        echo &#039;First case, with a break&#039;;
        break;
    case 1:
        echo &#039;Second case, which falls through&#039;;
        // no break
    case 2:
    case 3:
    case 4:
        echo &#039;Third case, return instead of break&#039;;
        return;
    default:
        echo &#039;Default case&#039;;
        break;
}آرگومان‌های دستور switch قابلیت شکسته شدن دارند. اگر بخواید چنین کاری رو انجام بدید باید از تمام قوانین گفته‌شده برای این کار در ساختارهای شرطی نیز تبعیت کنید؛ یعنی هر آرگومان/دستور در یک خط جداگانه قرار گرفته و یک واحد indent می‌شه. پرانتز پایانی و کروشه آغازین باید در یک خط باشن و بینشون یک اسپیس باشه. همینطور اپراتورهای boolean هم باید همیشه یا در ابتدای خط و یا در انتهای آن باشند، شما باید یکی از این دو حالت رو انتخاب کنید و تمام کدهای خودتون رو دقیقا به همین شکل بنویسید:&lt;?php

switch (
    $expr1
    &amp;&amp; $expr2
) {
    // structure body
}ساختارهای while و do whileیک دستور while دقیقا به شکل زیر نوشته می‌شه. به محل قرار گرفتن پرانتزها و اسپیس ها دقت کنید:&lt;?php

while ($expr) {
    // structure body
}در مورد شکستن آرگومان‌ها هم دقیقا همون قوانینی رو پیروی می‌کنید که در قسمت switch توضیح دادم و برای تکراری نشدن موضوع دوباره اون‌ها رو ذکر نمی‌کنم.همچنین یک ساختار ساده do while به شکل زیر هستش:&lt;?php

do {
    // structure body;
} while ($expr);و اگر بخواید آرگومان‌ها رو بشکنید باید از تمام قوانینی که ذکر شد تبعیت کنید:&lt;?php

do {
    // structure body;
} while (
    $expr1
    &amp;&amp; $expr2
);ساختارهای for و foreachاز اونجایی که همه این قوانین شبیه هم هستند برای اینکه سرتون رو درد نیارم سعی میکنم مثال بزنم و از تکرار بیش از حد پرهیز کنم :) .&lt;?php

for ($i = 0; $i &lt; 10; $i++) {
    // for body
}برای شکستن آرگومان های for هم به این شکل عمل میکنیم:&lt;?php

for (
    $i = 0;
    $i &lt; 10;
    $i++
) {
    // for body
}همچنین استفاده از ساختار foreach به ای شکله:&lt;?php

foreach ($iterable as $key =&gt; $value) {
    // foreach body
}در این ساختار شکستن آرگومان مجاز نیست.ساختار try-catch-finallyساختار try-catch-finally آخرین ساختار در این دسته هستش و شکل صحیحش به صورت زیر هستش:&lt;?php

try {
    // try body
} catch (FirstThrowableType $e) {
    // catch body
} catch (OtherThrowableType | AnotherThrowableType $e) {
    // catch body
} finally {
    // finally body
}اپراتورهاقوانین استایلینگ در اپراتورها بر اساس مفهوم arity اون‌هاست؛‌ یعنی چه تعداد operand یا «عَمَلوَند» دریافت می کنند. عملوند همان عنصریه که اپراتور یا «عملگر» روی آن اجرا می‌شه. توی این قسمت وقتی میگیم استفاده از whitespace (اسپیس یا همان فضای خالی) در کنار یک اپراتور مجازه، می‌تونید از چند اسپیس استفاده کنید تا خوانایی کد بهتر بشه.اپراتورهای unaryاپراتورهای افزایش و کاهش واحد نباید هیچ اسپیسی را بین خود و عملوند داشته باشند:$i++;
++$j;همچنین اپراتورهای Type casting نباید درون پرانتزهای خودشون هیچ اسپیسی داشته باشند:$intValue = (int) $input;اپراتورهای باینریتمام اپراتورهای حسابی، مقایسه ای، انتسابی، bitwise، منطقی، رشته ای و type باید قبل و بعد از خود حداقل یک اسپیس داشته باشند. به مثال زیر توجه کنید:if ($a === $b) {
    $foo = $bar ?? $a ?? $b;
} elseif ($a &gt; $b) {
    $foo = $a + $b * $c;
}اپراتورهای ternaryاپراتور شرطی ternary operator باید قبل و بعد از کاراکتر های ؟ و : حداقل یک اسپیس داشته باشند:$variable = $foo ? &#039;foo&#039; : &#039;bar&#039;;زمانی که عملوند میانی این اپراتور حذف می شه باید از همون قوانین ذکر شده برای اپراتورهای مقایسه‌ای پیروی کنید:$variable = $foo ?: &#039;bar&#039;;Closure هاهمونطور که می دونید closure ها در زبان‌های برنامه نویسی یک هدف اصلی دارند: شلوغ نکردن global namespace یا global scope. در واقع closure ها راهی برای نوشتن یک تابع به صورت محلی هستند که فقط هدف خاص و کوچکی را دارد و نیازی به وجود آن در scope سراسری نیست. یک مثال ساده از اون ها رو در کد زیر می بینید:function replace_spaces ($text) {
    $replacement = function ($matches) {
        return str_replace ($matches[1], &#039; &#039;, &#039; &#039;).&#039; &#039;;
    };
    return preg_replace_callback (&#039;/( +) /&#039;, $replacement, $text);
}در PSR-12 هم قوانینی مربوط به closure ها داریم که باید رعایت بشن. هر closure باید بعد از کلیدواژه function یک اسپیس داشته باشه. همچنین باید قبل و بعد از کلیدواژه use هم یک اسپیس داشته باشه. کروشه آغازین نباید به خط بعدی بره و در خط فعلی باقی می‌مونه اما کروشه پایانی باید بعد از بدنه تابع و در خط جداگانه خودش قرار داشته باشه. نباید بعد از پرانتز آغازین آرگومان ها یا متغیرها، اسپیسی وجود داشته باشه. این مسئله برای پرانتز پایانی هم صدق میکنه. در لیست آرگومان ها نباید قبل از ویرگول‌ها اسپیس داشته باشیم بلکه باید پس از هر ویرگول یک اسپیس قرار بدید. آرگومان‌های closure با مقادیر پیش فرض باید به انتهای لیست آرگومان ها منتقل بشن. اگر return type رو مشخص کردید باید به قوانین اون پایبند باشید: در صورت وجود کلیدواژه use، علامت دو نقطه باید پس از بسته شدن پرانتز use و بدون هیچ فاصله‌ای بیاد. در صورتی که تمام قوانین ذکر شده رو در کنار هم بگذارید چنین نتیجه ای می‌گیریم:&lt;?php

$closureWithArgs = function ($arg1, $arg2) {
    // body
};

$closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) {
    // body
};

$closureWithArgsVarsAndReturn = function ($arg1, $arg2) use ($var1, $var2): bool {
    // body
};همچنین شکستن لیست متغیرها/ آرگومان‌ها تابع قوانینی هستش که قبلا توضیح داده بودیم:&lt;?php

$longArgs_noVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) {
   // body
};

$noArgs_longVars = function () use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // body
};

$longArgs_longVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // body
};

$longArgs_shortVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use ($var1) {
   // body
};




$shortArgs_longVars = function ($arg) use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // body
};توجه داشته باشید که قوانین ذکر شده در تمام حالات برقرار هستند، حتی در زمانی که closure مستقیما در یک متد یا در فراخوانی تابع استفاده بشه:&lt;?php

$foo-&gt;bar(
    $arg1,
    function ($arg2) use ($var1) {
        // body
    },
    $arg3
);کلاس های ناشناس (anonymous class)کلاس‌های ناشناس از قوانین ذکر شده در قسمت closure ها پیروی می‌کنن:&lt;?php

$instance = new class {};کروشه آغازین می‌تونه روی همون خطی باشه که کلیدواژه class در آن قرار داره البته به شرطی که لیست interface آنقدر طولانی نباشه که از حد مجاز طول خط رد شده و به خط بعدی بریم. اگر به خط بعدی بریم باید کروشه آغازین رو در خط جدیدی قرار بدیم:&lt;?php

// Brace on the same line
$instance = new class extends \Foo implements \HandleableInterface {
    // Class content
};

// Brace on the next line
$instance = new class extends \Foo implements
    \ArrayAccess,
    \Countable,
    \Serializable
{
    // Class content
};خب دیگه باید بهتون یه خسته نباشید بگم که تا اینجا رو مطالعه کردید. اگر قابل می‌دونید بنده رو فالو کنید چون در آینده میخوام یه سری مطالب جالب در مورد php بهتون بگم و احتمالا ضبط ویدئو هم داشته باشم برای بعضی از مطالب.براتون آرزوی موفقیت میکنم.</description>
                <category>سید محمدرضا سید اسمعیل</category>
                <author>سید محمدرضا سید اسمعیل</author>
                <pubDate>Tue, 23 Aug 2022 21:40:15 +0430</pubDate>
            </item>
                    <item>
                <title>همه چیز در مورد PSR (بخش دوم)</title>
                <link>https://virgool.io/@seyedmr/what-are-psr-3-and-4-zbkufmohy8g5</link>
                <description>در پست قبلی با PSR آشنا شدیم و فهمیدیم چی هستش و قراره برامون چیکار کنه. همچنین با PSR-1 هم آشنا شدیم. حالا در ادامه با PSR-3 و PSR-4 آشنا می‌شیم.قبل از شروع باید به این نکته هم اشاره کنم که دلیل توضیح ندادن PSR-2، منسوخ شدن اون هستش.PSR-3: Logger Interfaceاگر بخوام خیلی ساده این استاندارد رو توضیح بدم باید بگم این استاندارد برای سیستم‌های لاگینگ هستش تا به صورت سراسری بتونیم از اونها داخل تمام پروژه‌هامون استفاده کنیم. (توضیح کامل این PSR داخل این پست نمی‌گنجه و اینجا فقط در حدی که باهاش آشنا بشیم در موردش می‌نویسم اما در آینده یه پست با مثال‌های خوب در مورد این PSR خواهیم داشت)حالا بریم ببینیم باید چیکار کنیم... قدم اول برای استفاده از این استاندارد، استفاده از پکیج psr/log هستش. این پکیج تمام اینترفیس‌ها، کلاس‌ها و تریت‌هایی که برای پیاده‌سازی و استفاده از این استاندارد نیاز داریم رو در خودش داره.اولین چیزی که نیاز داریم در مورد محتویات این پکیج بدونیم، اینترفیس LoggerInterface هستش.این اینترفیس ۸ متد رو در اختیار ما قرار میده که به وسیله‌ی اونها می‌تونیم لاگ‌هامون رو توی ۸ لول زیر ایجاد کنیم:EmergencyAlertCriticalErrorWarningNoticeInfoDebugهمچنین یه متد دیگه هم بهمون میده به اسم log که ورودی اول این متد، یکی از لول‌های بالا هستش.تمام متد‌های بالا باید یه ورودی message داشته باشن که رشته قبول کنه. (همچنین میتونه آبجکت‌هایی که متد ()toString__ دارن هم قبول کنه)علاوه بر message، متدها یه ورودی context هم نیاز دارند که آرایه قبول میکنه. این ورودی به منظور نگهداری اطلاعات اضافی که قابلیت تبدیل شدن به رشته رو ندارند استفاده میشه.این رو باید بدونیم که اگر خواستیم یه سری اکسپشن به عنوان context به لاگر بفرستیم حتما باید داخل کلید  exception قرارشون بدیم.حالا وقتی بخوایم داخل یکی از کلاس‌هامون عملیات لاگ کردن رو انجام بدیم فقط کافیه یه ورودی از نوع LoggerInterface رو به کلاسمون تزریق کنیم و بعد به راحتی از متد‌هایی که در اختیارمون قرار می‌ده استفاده کنیم. اینجوری می‌تونیم مطمین باشیم که همیشه لاگری که توسط استاندارد PSR-3 ایجاد شده به کلاسمون تزریق میشه و کلاسمون میتونه همه‌جا بدون مشکل کار کنه.در آینده داخل یه پست فقط و فقط در مورد این PSR صحبت می‌کنیم و یه لاگر هم با استفاده از این استاندارد می‌سازیم.PSR-4: Autoloaderاین استاندارد یکی از استاندارد‌های مهم و پر کاربرد هستش و همونطور که از اسمش پیداست در مورد لود خودکار کلاس‌ها هستش.اگه نمی‌دونید لود خودکار یا همون Autoloading چی هستش میتونید از این مطلب استفاده کنید.و حالا بریم سراغ لیست مواردی که باید در مورد PSR-4 بدونیم.منظورمون از کلاس در این مطلب، کلاس‌ها، اینترفیس‌ها، تریت‌ها و هر ساختار اینچنینی هستش.نام‌گذاری کلاس‌ها در این استاندارد باید به شکل زیر باشد.\&lt;NamespaceName&gt;(\&lt;SubNamespaceNames&gt;)*\&lt;ClassName&gt; ۳. کدی که عملیات اتولود رو انجام میده نباید هیچ اروری بده (اکسپشن بده) و همچنین نباید هیچ مقداری رو برگردونه.مورد دوم یه سری نکته داره که اونها رو اینجا می‌نویسم.(نمیدونم چجوری میشه توی ویرگول لیست تو در تو درست کرد برای همین آوردمشون اینجا وگرنه باید بره زیر همون مورد دوم :) )هر نیم‌اسپیسی باید شامل یک top level namespace باشه که بهش vendor namespace هم میگن.هر نیم‌اسپیسی میتونه شامل یک یا چند sub-namespace باشه. (همون قسمت وسطیه)نیم‌اسپیس باید با نام کلاسمون تموم بشه.آندرلاین هیچ معنی خاصی توی نیم‌اسپیس نمیده.(برخلاف PSR-0)ما‌ می‌تونیم از حروف کوچک و بزرگ در نیم‌اسپیس‌ها استفاده کنیم.برای ارجاع نیم‌اسپیس‌ها به کلاس باید به حروف بزرگ و کوچک حساس باشیم.خب دوستان در این مطلب با استانداردهای PSR-3 و PSR-4 آشنا شدیم. هر دوی این استانداردها نکته‌های بیشتری دارند که ایشالا در آینده به صورت مفصل در پستی جداگانه بهشون می‌پردازیم.</description>
                <category>سید محمدرضا سید اسمعیل</category>
                <author>سید محمدرضا سید اسمعیل</author>
                <pubDate>Wed, 20 Apr 2022 11:37:53 +0430</pubDate>
            </item>
                    <item>
                <title>همه چیز در مورد PSR (بخش اول)</title>
                <link>https://virgool.io/signal-tech/all-about-psr-part-1-jncucv0dxvnh</link>
                <description>یکی از مشکلاتی که اکثر ما برنامه‌نویس‌ها با اون مواجه شدیم، این بوده که وارد یک پروژه جدید شدیم و باید کلی زمان صرف آشنایی با روش کدنویسی برنامه نویس قبلی می‌کردیم.خیلی وقت‌ها هم شاید برای خودمون یه سری قاعده و قانون گذاشته باشیم اما هر سری وقتی عضو جدید به تیم اضافه شده، باز هم کلی وقت هدر رفته تا اون عضو جدید با استاندارد های ما آشنا بشه.باید بگم که یه سری برنامه‌نویس‌ داخل کنفرانس PHP-tek سال ۲۰۰۹ این قضیه خیلی اذیتشون کرد و به این نتیجه رسیدن که بیان و یه استاندارد کلی برای زبان PHP ارائه بدن تا همه از این استاندارد داخل کدهاشون استفاده کنند و با استفاده از این استاندارد، راحت تر بتونن با کدهای هم ارتباط بگیرن و درکش کنند. اسم این استاندارد هم گذاشتن PHP Standards Recommendations.من هم امروز و توی اولین پستم در ویرگول میخوام شروع کنم و این استاندارد‌ها رو معرفی کنم. باشد که رستگار شویم :)از سال ۲۰۰۹ تا امروز، ۲۲ تا استاندارد تعریف شده اما از این تعداد فقط ۱۳ تا درحال حاضر مورد استفاده قرار می‌گیره و بقیه‌ی اون‌ها یا هنوز کاملا تایید نشدن یا منقضی شدن و ... . (روال تایید شدن استانداردها هم یه راه و رسم خاصی داره که بعدا توی یه پست جدا توضیح میدم ایشالا)در ادامه با چندتا از این استاندارد‌های تایید شده آشنا می‌شیم.PSR-1: Basic Coding Standardدر این PSR، یه سری استاندارد‌های اولیه کدنویسی رو باهم قرارداد می‌کنیم.به صورت خلاصه این استاندارد موراد زیر رو بیان می‌کنه:فایل‌های php فقط باید از تگ &#x60;php?&gt;&#x60; و &#x60;=?&gt;&#x60; استفاده کنند.فایل‌های php فقط باید از UTF-8 استفاده کنند.فایل‌های php یا فقط باید چیزی را تعریف کنند (کلاس، تابع، ثابت و ...) یا side-effect ایجاد کنند اما نباید هر دو را انجام دهند. (در ادامه بیشتر در موردش توضیح میدم)نیم‌اسپیس‌ها و کلاس‌ها باید از یکی از استانداردهای autoloading استفاده کنند.(PSR-0,PSR-4) نام کلاس ها باید به صورت StudyCase باشد. (PascalCase)ثابت‌ها در کلاس باید تماما با حروف بزرگ نوشته شده و کلمات آن‌ها با آندرلاین از هم جدا شوند.متد‌ها باید به صورت camelCase تعریف شوند.مورد اول و دوم که نیازی به توضیح بیشتر ندارن. اما مورد سوم... !منظور از اینکه گفتیم باید چیزی رو تعریف کنند یعنی اینکه یه فایل بسازیم که داخلش کلاسمون رو تعریف کنیم و داخل اون فایل کار دیگه‌ای انجام ندیم. اما منظور از ساید افکت چیه؟تعریف اصلیش اینه:The phrase &quot;side effects&quot; means execution of logic not directly related to declaring classes, functions, constants, etc.همونطور که در بالا ذکر شده، منظور از ساید افکت، اجرای منطقیه که به صورت مستقیم ربطی به تعریف کلاس و تابع و ... نداره.یه مثال از فایلی که داخلش هم تعریف انجام شده و هم ساید افکت وجود داره این هستش:&lt;?php
// side effect: change ini settings
ini_set(&#039;error_reporting&#039;, E_ALL);

// side effect: loads a file
include &amp;quotfile.php&amp;quot

// side effect: generates output
echo &amp;quot&lt;html&gt;\n&amp;quot

// declaration
function foo()
{
    // function body
}یه مثال هم از فایلی که فقط داخلش تعریف و چیزی که مستقیما به تعریف مربوطه این هستش:&lt;?php
// declaration
function foo()
{
    // function body
}

// conditional declaration is *not* a side effect
if (! function_exists(&#039;bar&#039;)) {
    function bar()
    {
        // function body
    }
}درمورد namespace ها هم این نکته رو باید بگم که اگر از php ورژن 5.2 به قبل استفاده می‌کنید هم نباید از نیم‌اسپیس‌ها غافل بشید و باید اونها رو به این شکل پیاده کنید.&lt;?php
// PHP 5.2.x and earlier:
class Vendor_Model_Foo
{
}این مثال در نسخه های جدید php به صورت زیر پیاده‌سازی میشه.&lt;?php
// PHP 5.3 and later:
namespace Vendor\Model;

class Foo
{
}برای خالی نبودن عریضه یه مثال هم برای تعریف ثابت در کلاس ها می‌زنیم.اگر خواستیم داخل کلاسی ثابت تعریف کنیم، این کار رو به شکل زیر انجام میدیم.&lt;?php
namespace Vendor\Model;

class Foo
{
    const VERSION = &#039;1.0&#039;;
    const DATE_APPROVED = &#039;2012-06-01&#039;;
}و در انتها این نکته رو باید بگم که این استاندارد به صورت عمدی هیچ استانداردی برای تعریف property ها قرار نداده و فقط گفته که برای محدوده‌ی معقولی از کدهاتون، استاندارد‌های واحدی برای تعریف property ها داشته باشیم. همین و بس!خب دوستان این PSR دیگه نکته خاصی برای گفتن نداره و تموم شد. بقیه‌ی استاندارد‌ها رو هم ایشالا در پست‌های بعدی براتون قرار خواهم‌‌داد.</description>
                <category>سید محمدرضا سید اسمعیل</category>
                <author>سید محمدرضا سید اسمعیل</author>
                <pubDate>Tue, 19 Apr 2022 07:33:58 +0430</pubDate>
            </item>
            </channel>
</rss>