شاید شما هم بخواهید آدرس های خوانا و زیبایی برای سایتتان ایجاد کنید . و قطعا طی این جستجو ها با htaccess برخورد کردید ! آیا میدانید فریم ورک های بزرگ اصلا از htaccess برای این کار استفاده نمی کنند ؟ ( تنها شاید برای حذف index.php !) . در این آموزش ما با استفاده از regex می توانیم بدون هیچ زحتمی ، زیبا ترین آدرس های مد نظرمان را پیاده کنیم !
اساس کار ما چطور هست ؟ آدرس دهی seo friendly
ما میخواهیم ابتدا با استفاده از .htaccess فقط index.php رو از بین ببریم . تنها استفاده ما از htaccess فقط این است ! بقیه کار را با php انجام می دهیم .
ابتدا ما با استفاده از REQUEST_URI آدرس دریافتی را بدست می آوریم سپس با regex هایی که از قبل نوشته ایم مطابقت می دهیم . اگر با یکی از regex ها مطابقت داشت ، تابع مربوط به آن را صدا می زنیم .
توجه کنید که ما در این آموزش می توان گفت تا حدودی ساختار MVC را رعایت کرده ایم ولی شما خیلی راحت می توانید با ساختار MVC خودتان پیاده کنید .
بهتر است قبل از مطالعه این آموزش قسمت های قبلی شی گرایی را مطالعه کنید زیرا ما در این آموزش از شی گرایی استفاده می کنیم .
شروع برنامه نویسی …
ابتدا یک فولدر به نام مثلا mhrdev_routing بسازید و فایلی به نام index.php در آن بسازید .
در پوشه ی mhrdev_routing یک فایل دیگر نیز به نام .htaccess بسازید و کد زیر را در آن قرار دهید :
|
RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . index.php |
خوب حالا برای مثال آدرس زیر را باز کنید : ۱۲۷٫۰٫۰٫۱/mhrdev_routing/test
خوب باید با یک صفحه ی سفید بدون هیچ ارور یا پیامی مواجه بشوید .
دلیل این اتفاق این است که شما به آپاچی با استفاده از htaccess فهمونده اید که اگر آدرسی وارد شد ، فرض کند که اول آن یک index.php هم بوده و در اصل http://127.0.0.1/mhrdev_routing/index.php/test
است.
خوب حالا در فایل index.php
یک کلاس به نام Routing
بسازید و contructor
آن را به شکل زیر تعریف کنید .
|
<?php class Routing { private $request; function __construct() { $this->request = $_SERVER["REQUEST_URI"]; echo $this->request; } } $routing = new Routing(); |
همانطور که می دانید $_SERVER['REQUEST_URI']
به ما آدرس درخواستی بعد از نام دامین را بر میگرداند .
آدرس http://127.0.0.1/mhrdev_routing/test
را باز کنید . خروجی ما باید به شکل زیر باشد :
همانطور که می بینید نام mhrdev_routing در آدرس ما هم هست . ما با استفاده از script path می توانیم این بخش را حذف کنیم که باعث پیچیده تر شدن آموزش می شود . پس به صورت عادی با استفاده از str_replace می آییم و آدرس فولدر اسکریپت را از آدرس حذف می کنیم .
|
<?php class Routing { private $request; private $script_folder = "/mhrdev_routing"; function __construct() { $this->request = str_replace($this->script_folder,"",$_SERVER["REQUEST_URI"]); echo $this->request; } } $routing = new Routing(); |
خروجی باید به شکل /test
باشد . خوب حالا یک trim هم انجام میدیم که بهترین حالت را داشته باشیم !
|
$this->request = trim(str_replace($this->script_folder,"",$_SERVER["REQUEST_URI"]),"\n\r\t\\/"); |
خروجی جدید باید به شکل test
باشد .
خوب حالا یک متد جدید به نام getRoutes
تعریف میکنیم که قرار است یک آرایه به ما برگرداند که index آرایه ها regex و value آرایه ها یک تابع callable می باشد .
این جا است که شما میتوانید برای مثال یک controller یا … را تعریف کنید . برای سادگی آموزش من یک تابع ساده callable تعریف می کنم .
مدیریت آدرس ها استفاده از RegEx
من متد را به شکل زیر می سازم .
|
function getRoutes(){ return [ "/^\/?$/"=>function($params){ echo "صفحه ی اصلی"; }, "/^home$/"=>function($params){ echo "شما در آدرس home هستید"; }, "/^post(?P<post_url>.*)$/"=>function($params){ echo "شما در حال مشاهده ی ".urldecode($params["post_url"])." هستید"; } ]; } |
اولین داده مربوط به صفحه ی اصلی می باشد. این داده چک میکند اگر آدرس خالی بود یا / بود صفحه ی اصلی را نشان دهد .
دومین داده مربوط به مثلا یک صفحه ی یکتا به شکل home می باشد که فقط متن خانه را نمایش می دهد .
سومین داده مربوط به مثلا بخش پست ها می باشد که ما مثلا post_url را از کاربر میگیریم ( چیزی شبیه وردپرس ) .
ورودی $params مربوط به خروجی preg_match می باشد که مثلا در داده ی سوم به ما post_url را می دهد .
خوب حالا باید در __constructor
بیاییم و تک تک این regex ها را بررسی کنیم.
|
foreach($this->getRoutes() as $route=>$callable){ preg_match($route,$this->request,$matches); if(count($matches) > 0){ call_user_func_array($callable,[$matches]); return true; } } echo "یافت نشد"; |
خوب ما در این کد اول یک حلقه foreach
برای تک تک این regex ها انجام دادیم و در حلقه با استفاده از preg_match آمدیم آدرس را با regex ها مطابقت دادیم .
اگر طول آرایه خروجی $matches ما بیشتر از ۰ باشد یعنی مطابقت انجام شده و داده هایی مانند post_url هم در این آرایه قرار دارد . ما این مقادیر را با استفاده از call_user_fanc_array به callable خود می فرستیم .
آشنایی بیشتر با preg_match
آشنایی بیشتر با call_user_func_array
به همین راحتی حالا آدرس های مد نظرتان را چک کنید ویا با استفاده از Regex آدرس اضافه کنید !
کد نهایی :
index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
<?php class Routing { private $request; private $script_folder = "/mhrdev_routing"; function __construct() { $this->request = trim(str_replace($this->script_folder,"",$_SERVER["REQUEST_URI"]),"\n\r\t\\/"); foreach($this->getRoutes() as $route=>$callable){ preg_match($route,$this->request,$matches); if(count($matches) > 0){ call_user_func_array($callable,[$matches]); return true; } } echo "یافت نشد"; } function getRoutes(){ return [ "/^\/?$/"=>function($params){ echo "صفحه ی اصلی"; }, "/^home$/"=>function($params){ echo "شما در آدرس home هستید"; }, "/^post(?P<post_url>.*)$/"=>function($params){ echo "شما در حال مشاهده ی ".urldecode($params["post_url"])." هستید"; } ]; } } new Routing(); |
.htaccess:
|
RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . index.php |
عالی بود مرسی
سلام
عالی بود
لطفا یه مثال میزنید که چجوری Controller رو توی فایل bootsrap با استفاده از callable ست کنیم ؟!
کاری که من توی آموزش انجام دادم این بود که یک سری callable رو به یک سری regex مربوط کردم
ولی خب این کار ساده ترین کار حساب میشه .. اگه میخواید اصولی کار کنید بهتره یک سری رشته مثل user/panel رو به regex ها نسبت بدید طوری که خودتون بدونید ساختار این رشته ها به شکل controller/action هست ، حالا یک کلاس کنترلر بسازید که action یکی از متد های این کلاس هست و اون متد رو اجرا کنید .
امیدوارم که منظورتون رو از سوال درست متوجه شده باشم .
لطفا در مورد هدفمنی این سرویس بیشتر توضیح دهید
با تشکر از مطلب خوبتان