تالار گفتمان nCIS.ir

نسخه‌ی کامل: مسیریابی و ایجاد URL در Yii2
شما در حال مشاهده نسخه آرشیو هستید. برای مشاهده نسخه کامل کلیک کنید.
مقدمه

با توجه به حجم زیاد درخواست برای آموزش نحوه مسیریابی و ایجاد لینک‌ها و آدرس‌ها در Yii2 تصمیم گرفتم این تاپیک رو ایجاد کنم. این تاپیک ترجمه صفحه Routing and URL Creation از سایت رسمی YiiFramework هست که البته سعی کردم تجربیات و توضیحات خودم رو هم بهش اضافه کنم.

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

فرایند معکوس مسیریابی هم «ساخت URL» نام داره که طی اون، یه URL ازطریق مسیر مشخص‌شده و پارامترهای Query (روش GET) که توی قوانین مسیریابی (Rules) تعیین کردیم، تولید میشه.

بخش مرکزی که مسئول مسیریابی و ساخت URLها هست، URL Manager نام داره که بعنوان کامپوننت urlManager توی فایل تنظیمات برنامه ثبت شده. مدیر URL متد خاصی داره بنام parseRequest() برای تفسیر یه درخواست ورودی به یه مسیر و پارامترهای Get مربوطه و همچنین متد createUrl() برای ایجاد یک URL از مسیر مشخص و پارامترهای تعریف‌شده. با تنظیم‌کردن کامپوننت urlManager توی فایل تنظیمات برنامه، میتونین به برنامه خودتون اجازه بدین که فرمت‌های URL مختلف رو بدون نیاز به تغییر سورس‌کد برنامه اصلاح کنه. برای مثال میتونید از کد زیر برای ایجاد یک آدرس برای اکشن post/view استفاده کنید:

use yiihelpersUrl;

// Url::to() calls UrlManager::createUrl() to create a URL
$url = Url::to(['post/view', 'id' => 100]);

بسته به تنظیمات urlManager، آدرس تولیدشده ممکنه شبیه یکی از موارد زیر (یا یک فرمت دیگه) باشه و اگه بعداً URL تولیدشده هم توسط کاربران درخواست شد، مجدداً به فرمت مسیر اصلی و پارامترهای GET مربوطه تبدیل میشه:

/index.php?r=post%2Fview&id=100
/index.php/post/100
/posts/100
فرمت‌های URL

مدیر URL از دو قالب URL پشتیبانی میکنه:
  • قالب URL پیشفرض
  • قالب URL زیبا
فرمت پیشفرض از یه پارامتر GET به اسم r برای مشخص‌کردن مسیر (Route) استفاده میکنه و بقیه پارامترهای GET هم به آدرس مثل حالت عادی اضافه میشن. برای مثال آدرس:
/index.php?r=post/view&id=100

مشخص‌کننده مسیر post/view و پارامتر GET بنام id با مقدار 100 هست. این فرمت پیشفرض هیچ تنظیمات خاصی برای مدیر URL لازم نداره و با هر پیکربندی وب‌سروری کار میکنه.

فرمت زیبا از یه مسیر اضافه بعد از اسم اسکریپت ورودی (index.php) برای نمایش مسیر و پارامترهای GET مربوطه استفاده میکنه. برای مثال، مسیر اضافه در URL زیر:
/index.php/post/100

میشه /post/100 که اگه قاعده URL مناسب رو بکار برده باشین، میتونه معادل مسیر post/view با پارامتر GET به اسم id و با مقدار 100 باشه. برای استفاده از فرمت‌های زیبا باید مجموعه‌ای از قوانین URL رو براساس نیازمندی‌های واقعی خودتون درخصوص نحوه نمایش ظاهری URLها تعریف کنید.

میتونید با فعال یا غیرفعال‌کردن خاصیت enablePrettyUrl از کامپوننت مدیر URL بین این دو فرمت (پیشفرض و تمیز) بدون نیاز به تغییر سایر قسمت‌های برنامه، جابجا بشین.
مسیریابی

مسیریابی شامل دو مرحله است. در مرحله اول درخواست ورودی تبدیل به یه مسیر همراه با پارامترهای GET مربوطه میشه. در مرحله دوم، یه اکشن از کنترلر مربوط به مسیر تفسیرشده ایجاد میشه تا درخواست رو مدیریت کنه.

وقتی که از فرمت پیشفرض استفاده میکنید، تبدیل درخواست به مسیر به سادگی بررسی پارامتر GET به نام r هست که همراه درخواست ارسال شده.

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

وقتی که URL تبدیل به مسیر شد، حالا زمان ایجاد اکشن کنترلر مشخص‌شده توسط مسیر میرسه. مسیر با کمک اسلش‌های (/) داخلش، به بخش‌های مختلف شکسته میشه. برای مثال site/index به دو بخش site و index تقسیم میشه. هر بخش، یه ID هست که ممکنه به یه ماژول، یه کنترلر یا یه اکشن اشاره کنه. با شروع از اولین بخش مسیر، برنامه مراحل زیر رو اجرا میکنه تا ماژول‌ها (درصورت وجود)، کنترلر و اکشن مناسب رو ایجاد کنه:

  1. خود برنامه رو بعنوان ماژول فعلی درنظر میگیره.
  2. چک میکنه آیا نقشه کنترلر ماژول فعلی شامل ID کنترلر هست یا نه. اگه بود، یه شئ از کنترلر براساس تنظیماتی که داخل نقشه پیدا کرده ایجاد میکنه و میره سراغ مرحله 5 تا بقیه بخش‌های مسیر مدیریت بشه.
  3. چک میشه که ID به یه ماژول که توی خصوصیت modules از ماژول فعلی تعریف شده، اشاره میکنه یا نه. اگه اینطوری بود، یه ماژول براساس تنظیمات مربوطه توی فهرست ماژول‌ها ایجاد میشه و مرحله 2 مجدداً اجرا میشه تا بخش بعدی مسیر رو در فضای ماژولی که جدیداً ایجاد شده مدیریت کنه.
  4. با ID بعنوان شناسه کنترلر برخورد میشه و یه شئ از کلاس کنترلر مربوطه ساخته میشه و مرحله بعد برروی بخش بعدی مسیر اجرا میشه.
  5. کنترلر دنبال ID جاری توی نقشه اکشن‌های خودش میگرده. اگه پیداش کرد، یه شئ از اکشن مربوطه براساس تنظیمات موجود در نقشه ایجاد میکنه. درغیر اینصورت سعی میکنه یه اکشن درون‌خطی از متد اکشنی که معادل ID اکشن جاری هست، بسازه.
توی هرکدوم از مراحل بالا، اگه هرگونه خطایی رخ بده، یه استثنای yiiwebNotFoundHttpException تولید میشه که مشخص‌کننده شکست در فرایند مسیریابیه.

مسیر پیشفرض

وقتی یه درخواست بصورت یه مسیر خالی تفسیر بشه، مسیر پیشفرض بجاش استفاده میشه. بطور پیشفرض مسیر پیشفرض site/index هست که به اکشن index از کنترلر site اشاره میکنه. میتونید این مسیر رو با تنظیم خاصیت defaultRoute برنامه تغییر بدین. دقیق کنید که این خاصیت مربوط به خود Application هست نه کامپوننت URL Manager :

[
    // ...
    'defaultRoute' => 'main/index',
];

مسیر catchAll

گاهی اوقات ممکنه بخواین برنامه وب خودتون رو موقتاً در وضعیت نگهداری و توسعه بگذارین و یه پیام توضیح در جواب تمام درخواست‌های کاربران بهشون نشون بدین. راههای زیادی برای رسیدن به این هدف هست ولی یکی از ساده‌ترین راه‌ها تنظیم خاصیت yiiwebApplication::$catchAll از برنامه است (باز هم این خاصیت مربوط به کاموننت URL Manager نیست:

[
   // ...
   'catchAll' => ['site/offline'],
];

با تنظیمات بالا، اکشن site/offline برای پاسخ به تمام درخواست‌های ورودی برنامه بکار میره.

خاصیت catchAll باید یه آرایه باشه که پارامتر اولش مسیر رو مشخص میکنه و بقیه پارامترها (که زوج‌های کلید - مقدار هستن)، پارامترهایی خواهند بود که به اکشن ارسال میشن.

نقل قول:توضیح: پنل Debug در محیط توسعه درصورت فعال‌بودن این خاصیت، کار نخواهد کرد.
ساخت URLها

Yii یه متد کمکی به اسم yiihelpersUrl::to() برای تولید انواع مختلف URL با کمک مسیرها و پارامترهای GET مرتبط با اونها ارائه میکنه. برای مثال:

use yiihelpersUrl;

// creates a URL to a route: /index.php?r=post%2Findex
echo Url::to(['post/index']);

// creates a URL to a route with parameters: /index.php?r=post%2Fview&id=100
echo Url::to(['post/view', 'id' => 100]);

// creates an anchored URL: /index.php?r=post%2Fview&id=100#content
echo Url::to(['post/view', 'id' => 100, '#' => 'content']);

// creates an absolute URL: http://www.example.com/index.php?r=post%2Findex
echo Url::to(['post/index'], true);

// creates an absolute URL using the https scheme: https://www.example.com/index.php?r=post%2Findex
echo Url::to(['post/index'], 'https');


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

مسیری که به متد yiihelpersUrl::to() نسبت داده میشه، نسبت به مکان مورداستفاده حساسه. هم میتونید یه مسیر نسبی بدین و هم یه مسیر مطلق که با قوانین زیر نرمالسازی میشه:
  • اگه مسیر خالی باشه، مسیر درخواستی فعلی بکار میره.
  • اگه مسیر کلاً شامل اسلش / نباشه، بعنوان ID یه اکشن از کنترلر جاری تعبیر میشه و مقدار uniqueId کنترلر جاری بعنوان پیشوند بهش اضافه میشه.
  • اگه مسیر با اسلش شروع نشده باشه، بعنوان یه مسیر نسبی از ماژول فعلی درنظر گرفته میشه و پیشوند uniqueId ماژول جاری بهش اضافه میشه.


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

برای مثال فرض کنید ماژول فعلی admin و کنترلر جاری post هست:

use yiihelpersUrl;

// currently requested route: /index.php?r=admin%2Fpost%2Findex
echo Url::to(['']);

// a relative route with action ID only: /index.php?r=admin%2Fpost%2Findex
echo Url::to(['index']);

// a relative route: /index.php?r=admin%2Fpost%2Findex
echo Url::to(['post/index']);

// an absolute route: /index.php?r=post%2Findex
echo Url::to(['/post/index']);

// /index.php?r=post%2Findex     assume the alias "@posts" is defined as "/post/index"
echo Url::to(['@posts']);


متد yiihelpersUrl::to() با فراخوانی متدهای createUrl() و createAbsoluteUrl() از کامپوننت URL Manager پیاده‌سازی شده. در ادامه توضیح میدیم که چطور از URL Manager برای سفارشی‌کردن فرمت URLهای تولیدشده استفاده کنید.

ضمناً متد yiihelpersUrl::to() از تولید URLهایی که مرتبط با مسیر خاصی نیستن هم پشتیبانی میکنه. در این حالت، بجای اینکه یه آرایه بعنوان پارامتر اول بهش بدین، باید یه متن ساده بنویسید. برای مثال:

use yiihelpersUrl;

// currently requested URL: /index.php?r=admin%2Fpost%2Findex
echo Url::to();

// an aliased URL: http://example.com
Yii::setAlias('@example', 'http://example.com/');
echo Url::to('@example');

// an absolute URL: http://example.com/images/logo.gif
echo Url::to('/images/logo.gif', true);

درکنار متد to() کلاس yiihelpersUrl چند متد دیگه هم برای راحتی تولید URL فراهم کرده. برای مثال:


use yiihelpersUrl;

// home page URL: /index.php?r=site%2Findex
echo Url::home();

// the base URL, useful if the application is deployed in a sub-folder of the Web root
echo Url::base();

// the canonical URL of the currently requested URL
// see https://en.wikipedia.org/wiki/Canonical_link_element
echo Url::canonical();

// remember the currently requested URL and retrieve it back in later requests
Url::remember();
echo Url::previous();
استفاده از URLهای زیبا

برای استفاده از URLهای زیبا، کامپوننت urlManager رو در تنظیمات برنامه بصورت زیر تنظیم کنین:

[
    'components' => [
        'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'enableStrictParsing' => false,
            'rules' => [
                // ...
            ],
        ],
    ],
]

خاصیت enablePrettyUrl اجباریه چون فرمت URL زیبا رو فعال میکنه. بقیه خصوصیات اختیاری هستن. البته تنظیماتی که در بالا نشون دادیم، عموماً مورد استفاده قرار میگیرن.
  • showScriptName : این خاصیت تعیین میکنه که آیا اسکریپت ورودی باید توی URLهای تولیدشده ذکر بشه یا نه. برای مثال بجای ساخت URL مثل /index.php/post/100، با تنظیم این خاصیت روی false، آدرسی مثل /post/100 تولید میشه.
  • enableStringParsing : این خاصیت مشخص میکنه که باید تفسیر سخت‌گیرانه درخواست‌ها فعال بشه یا نه. اگه این مدل تفسیر فعال بشه، URL درخواستی باید حداقل با یکی از قوانین موجود در rules مطابقت داشته باشه وگرنه خطای yiiwebNotFoundHttpException تولید میشه.
  • rules : این خاصیت شامل فهرستی از قواعد هست که مشخص میکنه چطور باید URLها تولید و تفسیر بشن. درواقع، خاصیت اصلی که باید برای تولید URLهایی که فرمتشون با نیازهای برنامه شما مطابقت داره بکار بگیرین، همین خاصیته.

نقل قول:نکته: برای مخفی‌کردن اسم اسکریپت ورودی در URLهای تولیدشده، درکنار تنظیم‌کردن showScriptName با مقدار false باید وب‌سرورتون رو هم تنظیم کنید که بتونه به درستی تشخیص بده که چه اسکریپت PHP رو باید در زمانی که URL درخواستی صراحتاً چیزی رو مشخص نکرده، اجرا کنه. اگه از Apache استفاده میکنید، میتونین به تنظیمات پیشنهادی که توی قسمت نصب فریمورک توضیح دادیم مراجعه کنین.
قوانین URL

یه قانون URL یه شئ از کلاس yiiwebUrlRule یا کلاسهای مشتق‌شده از اونه. هر قانون URL شامل یه الگو که برای مطابقت با بخش مسیر URL درخواستی بکار میره، یه مسیر، و تعدادی پارامتر GET هست. یه قانون URL میتونه برای تفسیر یه درخواست بکار بره، اگه الگوش با URL درخواستی مطابقت پیدا کنه. یه قانون URL میتونه برای تولید یه URL هم بکار بره، اگه مسیرش و اسامی پارامترهای GET با مواردی که برای تولید URL ارائه‌شده، مطابقت داشته باشه.

وقتی که فرمت URL زیبا فعال باشه، مدیر URL از قوانین URL که توی خاصیت rules تعریف‌شدن برای تفسیر درخواست‌های ورودی و تولید URLها استفاده میکنه. درواقع برای تفسیر یه درخواست ورودی، URL Manager قوانین رو به‌ترتیبی که تعریف‌شدن بررسی میکنه و دنبال اولین قانونی میگرده که با URL درخواستی مطابقت داشته باشه. بعد از این قانون برای تفسیر URL و تبدیلش به مسیر و پارامترها استفاده میکنه و برای تولید لینک‌ها هم از همون قانون پیروی میکنه.

میتونین yiiwebUrlManager::$rules رو بصورت یه آرایه تنظیم کنید که کلیدهاش الگوها و مقادیرش مسیرهای متناظر هستن. هر زوج الگو - مسیر، یه قانون URL رو تشکیل میده. برای مثال، تنظیمات قوانین زیر دو قانون URL تعریف میکنه. اولین قانون با یه URL بنام posts مطابقت داره و اون رو به مسیر posts/index میفرسته. دومین قانون یه URL رو با کمک عبارات با قاعده post/(d+) شناسایی میکنه و اون رو به مسیر post/view میفرسته و پارامتر دریافتی که با پرانتز مشخص شده رو بعنوان id به اکشن مربوطه تحویل میده.

[
    'posts' => 'post/index', 
    'post/<id:d+>' => 'post/view',
]

نقل قول:توضیح: الگو توی یه قانون برای مطابقت بخش مسیر از URL بکار میره. برای مثال، مسیر /index.php/post/100?source=ad برابر با post/100 خواهد بود (اسلش‌های ابتدا و انتها نادیده گرفته میشن) و درنتیجه این URL با الگوی post/(d+) مطابقت پیدا میکنه.

درکنار تعریف قوانین URL بعنوان زوج‌های الگو - مسیر، میتونید اونها رو بصورت آرایه‌های تنظیمات هم مشخص کنید. هر آرایه از تنظیمات برای تنظیم یه قانون URL خاص بکار میره. این کار اغلب برای زمان‌هایی که میخواین خصوصیات دیگری از یه قانون URL رو مشخص کنید بکار میره. برای مثال:

[
    // ...other url rules...
    
    [
        'pattern' => 'posts',
        'route' => 'post/index',
        'suffix' => '.json',
    ],
]

بطور پیشفرض اگه خصوصیت class رو برای یه قانون مشخص نکنید، از کلاس پیشفرض yiiwebUrlRule استفاده میکنه.
پارامترهای نامگذاری‌شده

یه قانون URL میتونه با تعدادی پارامتر نامگذاری‌شده GET هم مرتبط بشه که توی الگو با فرمت <ParamName:RegExp> مشخص‌شدن که ParamName مشخص‌کننده اسم پارامتر و RegExp قسمت اختیاری هست که با کمک عبارات باقاعده برای تطبیق مقادیر پارامترها بکار میره. اگه RegExp قید نشه، معناش اینه که مقدار پارامتر باید یه متن بدون کارکتر اسلش / باشه.

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

وقتی یه قانون برای تفسیر URL بکار میره، پارامترهای مشخص‌شده رو با مقادیری که توی بخش مربوطه در URL مطابقت داشتن، پر میکنه و این پارامترها بعداً ازطریق $_GET توسط کامپوننت Request قابل استفاده خواهد بود. وقتی که از این قانون برای تولید URL استفاده میشه، مقادیر پارامترهای مشخص‌شده رو میگیره و اونها رو در مکان تعیین‌شده بجای پارامتر قرار میده.

بگذارین چند مثال برای نمایش چگونگی کارکرد پارامترهای نامگذاری‌شده بزنیم. فرض کنید که سه قانون URL بصورت زیر تعریف کردیم:

[
    'posts/<year:d{4}>/<category>' => 'post/index',
    'posts' => 'post/index',
    'post/<id:d+>' => 'post/view',
]

وقتی این قوانین برای تفسیر URLها بکار برن:
  • /index.php/posts به مسیر post/index با کمک قانون دوم تبدیل میشه.
  • /index.php/posts/2014/php با کمک قانون اول به مسیر post/index تفسیر میشه و پارامتر year با مقدار 2014 و پارامتر category با مقدار php براش ارسال میشن.
  • /index.php/post/100 توسط قانون سوم به مسیر post/view تبدیل میشه و پارامتر id با مقدار 100 براش ارسال خواهد شد.
  • /index.php/posts/php موجب تولید خطای yiiwebNotFoundHttpException میشه اگه گزینه yiiwebUrlManager::$enableStrictParsing با مقدار true تنظیم شده باشه چون با هیچ الگویی مطابقت نداره. اگه این خاصیت با false تنظیم شده باشه (مقدار پیشفرض)، مسیر posts/php بعنوان مسیر نتیجه بازگشت داده میشه.

و وقتی که این قوانین برای ایجاد لینک‌ها بکار برن:
  • Url::to(['post/index']) آدرس /index.php/posts رو با استفاده از قانون دوم تولید میکنه.
    Url::to(['post/index', 'year' => 2014, 'category' => 'php']) آدرس /index.php/posts/2014/php رو با کمک قانون اول تولید میکنه.
  • Url::to(['post/view', 'id' => 100]) آدرس /index.php/post/100 رو توسط قانون سوم تولید میکنه
  • Url::to(['post/view', 'id' => 100, 'source' => 'ad']) آدرس /index.php/post/100?source=ad رو با استفاده از قانون سوم تولید میکنه. از اونجا که پارامتر source توی قانون تعریف نشده، بعنوان پارامتر GET به آدرس تولیدشده اضافه میشه.
  • Url::to(['post/index', 'category' => 'php']) آدرس /index.php/post/index?category=php رو تولید میکنه و از هیچ قانونی استفاده نمیشه. دقت کنید که چون هیچ قانونی اعمال نشده، URL تولیدشده به‌سادگی با اضافه‌کردن مسیر بعنوان بخش مسیر آدرس و تمام پارامترها بعنوان پارامتر GET تولید شده.
مسیرهای پارامتری

میتونین اسامی پارامترها رو داخل قسمت مسیر یه قانون URL بکار ببرنی. این کار به شما اجازه میده که یه قانون URL برای مطابقت با چند مسیر مختلف بکار بره. برای مثال، قوانین زیر از پارامترهای controller و action توی مسیر استفاده میکنن:

[
    '<controller:(post|comment)>/<id:d+>/<action:(create|update|delete)>' => '<controller>/<action>',
    '<controller:(post|comment)>/<id:d+>' => '<controller>/view',
    '<controller:(post|comment)>s' => '<controller>/index',
]

برای تفسیر یه URL مثل /index.php/comment/100/create قانون اول استفاده میشه که پارامتر controller رو comment و پارامتر action رو create میگذاره و درنتیجه مسیر <controller>/<action> بصورت comment/create تفسیر خواهد شد.

بطور مشابه برای تولید مسیر comment/index قانون سوم مورد استفاده قرار میگیره و آدرس /index.php/comments تولید خواهد شد.

نقل قول:توضیح: با کمک مسیرهای پارامتری، تعداد قوانین URL رو میشه به‌شدت کاهش داد، که به‌میزان قابل‌ملاحظه‌ای کارایی URL Manager رو افزایش میده.

بطور پیشفرض، تمام پارامترهایی که داخل یه rule تعریف‌شدن، اجباری هستن. اگه URL درخواستی شامل یه پارامتر خاص نباشه، یا اگه آدرسی که قراره تولید بشه، بدون پارامتر تعریف بشه، اون قانون اعمال نمیشه. برای اختیاری‌کردن برخی از پارامترها، میتونید از خاصیت defaults استفاده کنید. پارامترهایی که توی این خاصیت ذکر میشن، اختیاری هستن و اگه ارائه نشن، مقدار پیشفرضی که مشخص‌شده، براشون درنظر گرفته میشه.

توی قانون زیر، پارامترهای page و tag هردو اختیاری هستن و اگه اعلام نشده باشن، به‌ترتیب مقادیر 1 و رشته خالی رو میگیرن.

[
   // ...other rules...
   [
       'pattern' => 'posts/<page:d+>/<tag>',
       'route' => 'post/index',
       'defaults' => ['page' => 1, 'tag' => ''],
   ],
]

قانون بالا میتونه برای تفسیر یا تولید هرکدوم از URLهای زیر بکار بره:
  • /index.php/posts (پارامتر page مقدار 1 و tag رشته خالی خواهد بود)
  • /index.php/posts/2 (پارامتر page مقدار 2 و tag رشته خالی خواهد بود)
  • /index.php/posts/2/news (پارامتر page مقدار 2 و tag برابر با 'news' خواهد بود)
  • /index.php/posts/news (پارامتر page مقدار 1 و tag برابر با 'news' خواهد بود)

بدون پارامترهای اختیاری، باید چهار قانون برای رسیدن به نتیجه مشابه بنویسین.
قواعدی با کمک اسم سرور

استفاده از اسامی سرور وب در الگوهای قوانین URL امکان‌پذیره. این موضوع بطور خاص وقتی کاربرد داره که برنامه شما باید توی اسامی سرور مختلف عملکرد متفاوتی داشته باشه. برای مثال، قوانین زیر آدرس http://admin.example.com/login رو به مسیر admin/user/login و همچنین آدرس http://www.example.com/login رو به مسیر site/login تبدیل میکنن:

[
    'http://admin.example.com/login' => 'admin/user/login',
    'http://www.example.com/login' => 'site/login',
]

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

[
    'http://<language:w+>.example.com/posts' => 'post/index',
]

این قانون آدرس http://en.example.com/posts رو به مسیر post/index همراه با پارامتر language=en تبدیل میکنه.

نقل قول:نکته مهم: قوانینی که دارای اسامی سرور هستن نباید شامل پوشه‌های فرعی اسکریپت ورودی داخل خودشون باشن. برای مثال اگه برنامه در مسیر http://www.example.com/sandbox/blog باشه، شما باید از الگوی http://www.example.com/posts بجای اسم سرور استفاده کنید. این‌کار به شما اجازه میده که برنامه خودتون رو توی هر پوشه‌ای بدون نیاز به تغییر کد برنامه بکار ببرین.
پسوندهای URL

ممکنه بنا به دلایل مختلف بخواین پسوندهایی به URLهای خودتون اضافه کنین. برای مثال ممکنه بخواین یه پسوند .html به URLها اضافه کنید تا در ظاهر، صفحات ایستای HTML بنظر برسن. همچنین ممکنه بخواین پسوند .json رو به آدرس‌های خاصی اضافه کنید تا مشخص بشه که خروجی اونها چه نوعی داره. میتونید این کار رو با تنظیم خاصیت yiiwebUrlManager::$suffix مثل کد زیر توی تنظیمات برنامه انجام بدین:

[
   'components' => [
       'urlManager' => [
           'enablePrettyUrl' => true,
           'showScriptName' => false,
           'enableStrictParsing' => true,
           'suffix' => '.html',
           'rules' => [
                // ...
            ],
       ],
   ],
]

تنظیمات بالا به مدیر URL اجازه میده که URLهایی که پسوند .html دارن رو تشخیص و آدرس‌ها رو هم با همین پسوند تولید کنه.

نقل قول:راهنمایی: میتونید کارکتر اسلش / رو بعنوان پسوند تعریف کنید تا تمام آدرس‌هاتون به / ختم بشن.

نقل قول:نکته: وقتی که یه پسوند رو برای URL مشخص میکنید، اگه آدرس درخواست‌شده شامل اون پسوند نباشه، بعنوان یه آدرس تشخیص‌داده‌نشده درنظر گرفته میشه. این موضوع میتونه یه تمرین برای SEO باشه (بهینه‌سازی برای موتورهای جستجو یا Search Engine Optimization).

گاهی اوقات ممکنه بخواین برای URLهای مختلف، پسوندهای متفاوتی ایجاد کنید. این‌کار ازطریق تعریف خاصیت suffix قوانین بصورت جداگانه انجام میشه. وقتی که یه قانون URL این خاصیت رو تنظیم کرده باشه، پسوندی که در سطح URL Manager مشخص‌شده رو رونویسی میکنه. برای مثال توی تنظیمات زیر، یه URL اختصاصی با پسوند .json بجای پسوند عمومی .html تعریف شده:

[
   'components' => [
       'urlManager' => [
           'enablePrettyUrl' => true,
           'showScriptName' => false,
           'enableStrictParsing' => true,
           'suffix' => '.html',
           'rules' => [
               // ...
               [
                    'pattern' => 'posts',
                    'route' => 'post/index',
                    'suffix' => '.json',
                ],
           ],
       ],
   ],
]
متدهای HTTP

وقتی APIهای RESTful میسازین، معمولاً نیاز میشه که یه URL براساس متدهای مختلف HTTP که بکار رفته، به مسیرهای مختلف تفسیر بشه. این کار به‌سادگی با اضافه‌کردن متدهای HTTP که هر قانون پشتیبانی میکنه بعنوان پیشوند الگو امکان‌پذیره. اگه یه قانون قراره از متدهای HTTP مختلفی پشتیبانی کنه، باید اونها رو با کاما از هم جدا کنین. برای مثال، قوانین زیر الگوی مشابه post/<id:d+> رو با متدهای مختلف HTTP پشتیبانی میکنن. یه درخواست برای PUT post/100 به مسیر post/create و یه درخواست برای GET post/100 به مسیر post/view ارسال میشه:

[
    'PUT,POST post/<id:d+>' => 'post/create',
    'DELETE post/<id:d+>' => 'post/delete',
    'post/<id:d+>' => 'post/view',
]

نقل قول:نکته: اگه یه قانون URL شامل متدهای HTTP توی الگوی خودش باشه، اون قانون فقط برای تفسیر URL بکار میره و در مواقعی که مدیر URL رو برای تولید URL فراخوانی میکنیم، نادیده گرفته میشه.

نقل قول:راهنمایی: برای ساده‌سازی آدرس‌دهی APIهای RESTful، فریمورک Yii یه کلاس خاص قانون URL بنام yiirestUrlRule معرفی کرده که بسیار کارآمده و برخی قابلیت‌های جذاب مثل جمع‌بندی خودکار IDهای کنترلرها داره. برای جزئیات بیشتر، به بخش مسیریابی در آموزش توسعه APIهای RESTful مراجعه کنید.
سفارشی‌سازی قواعد

توی مثال‌های قبلی، قواعد URL اغلب بصورت زوج‌های الگو - مسیر تعریف‌شدن. این موضوع عموماً بعنوان فرمت میانبر بکار میره. در موارد خاصی ممکنه بخواین یه قاعده URL رو با تنظیم سایر خصوصیاتش مثل yiiwebUrlRule::$suffix سفارشی کنین. این‌کار با استفاده از یه آرایه کامل تنظیمات برای مشخص‌کردن یه قاعده انجام میشه. مثال زیر از بخش پسوندهای URL برداشته شده:

[
    // ...other url rules...
    
    [
        'pattern' => 'posts',
        'route' => 'post/index',
        'suffix' => '.json',
    ],
]

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

قواعد URL رو میشه بصورت پویا هم به مدیر URL اضافه‌کرد. این‌کار اغلب در ماژول‌هایی استفاده میشه که قراره توی چندین پروژه مورد استفاده قرار بگیرن تا وقتی به پروژه اضافه شدن، قواعد URL مخصوص به خودشون رو هم تعریف کنن. گاهی‌اوقات هم ممکنه بخواین قواعد ازطریق پنل مدیریت سایت قابل تغییر باشه و درنتیجه تصمیم می‌گیرین اونها رو توی دیتابیس ذخیره کنید. در چنین مواقعی برای اضافه‌کردن قواعد بصورت پویا و تأثیرگذاریشون درحین عملیات مسیریابی، باید اونها رو در بین عملیات بارگذاری اولیه برنامه که بهش میگن Bootstrapping اضافه کنید (این فرآیند رو با قالب نمایشی Bootstrap اشتباه نگیرین). برای ماژول‌ها، این به‌معنای اینه که کلاس ماژولشون باید رابط yiibaseBootstrapInterface رو پیاده‌سازی کنه و قواعد رو توی متد bootstrap() مشابه کد زیر اضافه کنید:

public function bootstrap($app)
{
    $app->getUrlManager()->addRules([
        // rule declarations here
    ], false);
}

نقل قول:نکته: دقت کنید که شما باید این ماژول‌ها رو توی تنظیمات برنامه تحت عنوان خاصیت yiiwebApplication::$bootstrap هم معرفی کنید تا بتونن توی فرآیند Bootstrapping مشارکت داشته باشن.
ایجاد کلاس‌های قواعد

با وجود اینکه کلاس پیشفرض yiiwebUrlRule به حد کافی برای بخش اعظم پروژه‌ها انعطاف‌پذیره، شرایطی هم وجود داره که ممکنه بخواین کلاس‌های اختصاصی قواعد خودتون رو داشته باشین. برای مثال، توی یه سایت فروش ماشین، ممکنه بخواین از قالب‌های URL نظیر /Manufacturer/Model پشتیبانی کنید که هر دو مورد Manufacturer و Model باید با برخی داده‌های ذخیره‌شده در جداول دیتابیس شما مطابقت داشته باشن. در چنین شرایطی کلاس قاعده پیشفرض کار نمیکنه چون بصورت ایستا برمبنای الگوهای تعریف‌شده کار میکنه.

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

namespace appcomponents;

use yiiwebUrlRuleInterface;
use yiibaseObject;

class CarUrlRule extends Object implements UrlRuleInterface
{

    public function createUrl($manager, $route, $params)
    {
        if ($route === 'car/index') {
            if (isset($params['manufacturer'], $params['model'])) {
                return $params['manufacturer'] . '/' . $params['model'];
            } elseif (isset($params['manufacturer'])) {
                return $params['manufacturer'];
            }
        }
        return false;  // this rule does not apply
    }

    public function parseRequest($manager, $request)
    {
        $pathInfo = $request->getPathInfo();
        if (preg_match('%^(w+)(/(w+))?$%', $pathInfo, $matches)) {
            // check $matches[1] and $matches[3] to see
            // if they match a manufacturer and a model in the database
            // If so, set $params['manufacturer'] and/or $params['model']
            // and return ['car/index', $params]
        }
        return false;  // this rule does not apply
    }
}

و از این کلاس قاعده جدید توی yiiwebUrlManager::$rules استفاده کنیم:

[
    // ...other rules...
    
    [
        'class' => 'appcomponentsCarUrlRule', 
        // ...configure other properties...
    ],
]
ملاحظات مربوط به کارآیی

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

با استفاده از مسیرهای پارامتری، میتونید تعداد قواعد URL رو کاهش بدین که به‌شدت باعث افزایش کارآیی میشه.

در زمان تفسیر و تولید URLها، مدیر URL قواعد URL رو به‌ترتیبی که نوشته‌شدن بررسی میکنه. بنابراین باید درمورد تنظیم ترتیب قواعد URL مراقب باشین تا قواعدی که عمومی‌تر هستن قبل‌از قواعد اختصاصی نوشته نشن. برای مثال توی قوانین زیر:

[
    'posts' => 'posts/index',
    'posts/<page:d+>', => 'posts/index',
],

هیچوقت قاعده دوم اعمال نمیشه چون همیشه قاعده اول در مواقعی که پارامتر GET به اسم page وجود داره هم صدق میکنه و دیگه نوبت به قانون دوم نمیرسه. در اینجا یا باید ترتیب دو قاعده رو جابجا کنید تا قاعده اختصاصی‌تر قبل از قاعده عمومی‌تر قرار بگیره و یا اینکه از مقدار پیشفرض استفاده کنید:

[
   [
       'pattern' => 'posts/<page:d+>',
       'route' => 'posts/index',
       'defaults' => ['page' => 1],
   ],
],

اگه برخی از قواعد URL توی پیشوند الگو یا مسیرشون مشترک باشن، میتونید از yiiwebGroupUrlRule برای گروه‌بندی اونها استفاده کنید تا به‌شکل کارآمدتری توسط مدیر URL بررسی بشن. این موضوع در اغلب مواقع توی ماژول‌ها پیش میاد چون همه آدرس‌های یک ماژول با پیشوند مشترکی که ID ماژول هست شروع میشن. با این کار، اگه پیشوند موردنظر وجود نداشته باشه دیگه هیچکدوم از قواعد اون گروه ارزیابی نمیشن ولی اگه جداگانه بنویسید، هرکدوم باید جداگانه ارزیابی بشن. مثال:

new yiiwebGroupUrlRule([
    'prefix' => 'admin',
    'rules' => [
        'login' => 'user/login',
        'logout' => 'user/logout',
        'dashboard' => 'default/dashboard',
    ],
])

// the above rule is equivalent to the following three rules:

[
    'admin/login' => 'admin/user/login',
    'admin/logout' => 'admin/user/logout',
    'admin/dashboard' => 'admin/default/dashboard',
]