نوشتن یک برنامه افزونه پذیر در PHP
#1
Note 
به نام خدا
یکی از ویژگیهایی که یک برنامه خوب باید داشته باشه قابلیت توسعه پذیریه. خیلی از برنامه هایی که درطول روز با اونها سروکار دارید امکانی دارند به نام "افزونه پذیری" یعنی شما میتونید افزونه ای رو روی برنامه نصب کرده و قابلیت های اون رو بیشتر کنید. در این آموزش من نحوه کلی نوشتن یه برنامه افزونه پذیر رو به شما میگم.

Hook چیست؟
Hook ها به ما این اجازه رو میدن تا بتونیم در زمان اجرا توابعی رو در زمان خاصی صدا بزنیم. برای مثال شاید کاربر بخواد در هنگام نمایش یک محتوا ابتدا تو اون تغییری ایجاد کنه و بعد نمایشش بده. ما دو نوع hook داریم، action hook و  filter hook.
Action hook به ما اجازه میده تا بتونیم تابعی رو در جایی خاص از برنامه صدا بزنیم در حالی که filter hook اجازه تغییر محتوای یک متغیر رو قبل از استفاده میده که هر دوی اینها به طریقی باعث میشن تا بتونیم در محتوایی که باید در نهایت نمایش پیدا کنه تغییر ایجاد کنیم.

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


ACTION HOOK
همونطور که گفتیم Action hook فقط تابع مورد نظر مون رو در جای مشخصی از برنامه برامون اجرا میکنه. برای مثال شما میخواید موقتا سایت رو ببندید و پیامی به کاربرا نشون بدید، اینجاست که در ابتدای فایل تابعی رو اجرا میکنید که اینکارو انجام بده.

شروع کد نویسی
ما متغیری داریم به نام action_events$. این متغیر آرایه ای هست که لیست توابع برای اجرا رو در خودش نگه داری میکنه و بعد توابع درون متغیر توسط نامی که براشون هنگام ثبت در نظر گرفته شده قابل دسترسی هستن:
کد:
Array
(
   [initialize] => Array
       (
           [0] => ban
           [1] => closed
           [2] => checkip
           [3] => stats
       )

   [editor] => Array
       (
           [0] => addbutton
           [1] => removebutton
       )

)
در مثال بالا initialize و editor نامیه که برای گروه توابع در نظر گرفته شده.

کد php:
   $action_events = array(); 

تابع hook_action برای اجرای توابع ثبت شده در متغیر action_events$ استفاده میشه; به این صورت که با گرفتن نام گروه توابع به عنوان پارامتر توابع موجود رو به ترتیب اجرا میکنه.

کد php:
function hook_action($event)
{
    global 
$action_events;
    
    if(isset(
$action_events[$event]))
    {
        foreach(
$action_events[$event] as $func)
        {
            if(!
function_exists($func)) {
                die(
'Unknown function: '.$func);
            }
            
call_user_func($func);
        }
    }
    


برای مثال وقتی ('hook_action('initialize اجرا میشه توابع ban,closed,checkip,stats  فراخوانی میشن.

تابع register_action برای ثبت یک تابع در متغیر action_events$ استفاده میشه که توسط نویسنده پلاگین و در خود فایل پلاگین استفاده میشه.

کد php:
   function register_action($event$func)
 
   {
 
   global $action_events;
 
   $action_events[$event][] = $func;
 
   


ساخت اولین برنامه افزونه پذیر


برای شروع ابتدا این ساختار رو ایجاد کنید:
کد:
●/pluggableAPP
 ○ includes/
     ■ pluggable.php

 ○ plugins/
     ■ ipban.php
 ○ index.php

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

فایل ipban.php:
کد php:
<?PHP
//Rgister the action using the 'initialize' action hook we defined earlier.
register_action('initialize','ban');


function 
ban() {
    
//Array of banned ip adresses
    
$deny = array("111.111.111""222.222.222""333.333.333");
    
//Check if user is banned, if so, give them a nice message.
    
if (in_array ($_SERVER['REMOTE_ADDR'], $deny)) {
        die(
'Sorry! You can not visit this website.');
    }
}

?>

فایل pluggable.php:
کد php:
<?php
//Arrays to store user-registered events and functions.
$action_events = array();

//Functions for Action Hooks
function hook_action($event)
{
    global 
$action_events;
    
    if(isset(
$action_events[$event]))
    {
        foreach(
$action_events[$event] as $func)
        {
            if(!
function_exists($func)) {
                die(
'Unknown function: '.$func);
            }
            
call_user_func($func);
        }
    }
    
}

function 
register_action($event$func)
{
    global 
$action_events;
    
$action_events[$event][] = $func;
}

?>

فایل index.php:
کد php:
<?php
//include files for adding plugin functionality
require_once "includes/pluggable.php";

//Load Plugins
foreach( glob("plugins/*.php") as $plugin) {
    require_once(
$plugin);
}

hook_action('initialize');

?>
<!DOCTYPE html>
<html>
<head>
    <title>Softafzar</title>
    <meta charset="utf-8" />
</head>
<body>
<h1>Welcome to softafzar.net!</h1>
</body>
</html> 

حالا برنامه رو اجرا کنید. اگر ip شما در لیست deny$ باشه پیام Sorry! You can not visit this website  و در غیر اینصورت Welcome to softafzar.net نمایش داده میشه. برای اینکه مطمئن بشید برنامه درست کار میکنه ip خودتون رو به لیست اضافه کنید:
کد php:
    $deny = array("111.111.111""222.222.222",$_SERVER['REMOTE_ADDR']); 
همچنین برای غیر فعال کردن افزونه فقط کافیه اون رو از فولدر plugins حذف کنید و هیچ نیازی به تغییر کدها نیست.

تبریک! شما یک برنامه افزونه پذیر نوشتید!

دانلود برنامه

در ادامه به filter hook ها میپردازیم... با ما باشید :winksmiley02:

پاسخ
#2
Note 
عالی بود ممنون

پاسخ
#3
Note 
سلام
بسیار عالی و بدرد بخور بود واقعا ممنون
شدیدا منتظر Filter hook Confusedmile13:

توان آدمیان را، با آرزوهایشان می شود سنجید . حکیم ارد بزرگ
پاسخ
#4
Note 
سلام خیلی عالی بود ادامش نمیاد؟

پاسخ
#5
Note 
سلام
در ادامه بحث افزونه پذیر کردن برنامه ها بعد از Action hooks حالا به Filter Hooks میرسیم.

FILTER HOOK
Filter hook ها بسیار شبیه Action hook ها هستن با این تفاوت که Filter hook ها محتوای متغیرها رو با استفاده از تابعی که توسط توسعه دهنده افزونه نوشته شده، قبل از استفاده تغییر میدن.
تمام کدهای ما در Filter hook شبیه Action hook هستن و بیشترشون هیچ تغیییری نمیکنن، برای پیاده سازی این نوع ما فقط به چند تغییر خیلی کوچیک در کدها نیاز داریم. همونطور که دیدید ما در تابع hook_action مستقیما توابع رو اجرا میکردیم و نیازی به بازگشت نتیجه نبود اما در اینجا باید نتیجه اجرای تابع رو برگردونیم تا بتونیم متغیر اصلی رو تغییر بدیم.

برای درک بهتر به این تکه کدها توجه کنید:

Action Hook:
کد php:
call_user_func($func); 

Filter Hook:
کد php:
$content call_user_func($func,$content);
 ...
 return 
$content
همونطور که میبینید در کد اول که در تابع hook_action مربوط به Action hook داشتیم ما تابع تعریف شده توسط کاربر رو فراخوانی میکنیم بدون اینکه نتیجه رو برگردونیم. اما در کد دوم نتیجه اجرای توابع برگشت داده میشه.


شروع کدنویسی
اینجا هم ما به متغیری برای ذخیره نام توابعی که باید اجرا بشن نیاز داریم درست مثل Action hook.
کد php:
$filter_events = array(); 

تابع hook_filter هم مثل hook_action هست با دو تغییر کوچک که در بالا گفته شد + یک پارامتر برای دریافت نام متغیری که محتوای اون باید توسط توابع ما تغییر کنه . یعنی متغیری رو به عنوان ورودی به این تابع ارسال میکنیم بعد از انجام تغییرات، محتوای جدید به عنوان خروجی به ما تحویل داده میشه :
کد php:
<?php
function hook_filter($event,$content) {
    
    global 
$filter_events;
    
    if(isset(
$filter_events[$event]))
    {
        foreach(
$filter_events[$event] as $func) {
            if(!
function_exists($func)) {
                die(
'Unknown function: '.$func);
            }
            
$content call_user_func($func,$content);
        }
    }
    return 
$content;
}
?>

همچنین تابع register_filter داریم که برای ثبت توابع جدید هست که در فایل پلاگین استفاده میشه:
کد php:
<?php
function register_filter($event$func)
{
    global 
$filter_events;
    
$filter_events[$event][] = $func;
}
?>

حالا تصور کنید ما در حال توسعه یک CMS هستیم و در برنامه خودمون تابعی به نام Show_content برای نمایش محتویات پست داریم. در حالت عادی اگر گاربر بخواد در تمامی پست ها تغییری ایجاد کنه انجام این کار حتما خیلی سخت خواهد بود اما با استفاده از Filter hook این کار براحتی انجام میشه:
کد php:
<?php
function show_content($content) {
    
$content hook_filter('the_content',$content);
    echo 
$content;
}
?>

در فایل پلاگین(افزونه) کدی شبیه به این مینویسیم:
کد php:
<?php
register_filter
('the_content','hotstuff');

function 
hotstuff($var) {
    
$var str_replace('ice','hot',$var);
    return 
$var;
}
?>

حالا اگر تابع show_content رو به این شکل اجرا کنیم:
کد php:
show_content('Hello. I like ice cream.'); 
نتیجه Hello. I like hot cream خواهد بود چون ما در فایل پلاگین تمام کلمات "ice" رو با "hot" جایگزین کردیم.

برای دانلود پروژه کامل همراه با مثالهای بیشتر کلیک کنید.

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

پاسخ
#6
با سلام
من خیلی دنبال این آموزش بودم بسیار مطلب خوبی بود از شما تشکر میکنم

پاسخ
ایجاد موضوع جدید   پاسخ به موضوع  

کاربرانِ درحال بازدید از این موضوع:   1 مهمان