آموزش

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

بازدید102.6kپست ها5آخرین فعالیت9 سال پیش
8
0

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

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

**[color=#FF8C00]نکته: [/color]**نوشتن یک برنامه افزونه پذیر کامل نیاز به انجام اعمال یکرسی محدودیت ها و تامین امنیت کافی داره چون به توسعه دهنده ها اجازه میده تا برنامه شما رو دستکاری کنن . پس نمیتونید  فقط از کدی که من در این آموزش اختیارتون میذارم برای برنامه ها تون استفاده کنید.

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

[size=x-large]شروع کد نویسی[/size]
ما متغیری داریم به نام $action_events این متغیر آرایه ای هست که لیست توابع برای اجرا رو در خودش نگه داری میکنه و بعد توابع درون متغیر توسط نامی که براشون هنگام ثبت در نظر گرفته شده قابل دسترسی هستن:

Array
(
    [initialize] => Array
        (
            [0] => ban
            [1] => closed
            [2] => checkip
            [3] => stats
        )

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

)

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

$action_events = array();

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

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استفاده میشه که توسط نویسنده پلاگین و در خود فایل پلاگین استفاده میشه.

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
//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
//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
//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>irDevs</title>
	<meta charset="utf-8" />
</head>
<body>
<h1>Welcome to irDevs.com!</h1>
</body>
</html>

حالا برنامه رو اجرا کنید. اگر ip شما در لیست $deny باشه پیام Sorry! You can not visit this website  و در غیر اینصورت Welcome to irdevs نمایش داده میشه. برای اینکه مطمئن بشید برنامه درست کار میکنه ip خودتون رو به لیست اضافه کنید:

$deny = array("111.111.111", "222.222.222",$_SERVER['REMOTE_ADDR']);

همچنین برای غیر فعال کردن افزونه فقط کافیه اون رو از فولدر plugins حذف کنید و هیچ نیازی به تغییر کدها نیست.

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

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

آخرین ویرایش: 09-04-2018 ???? 22:21، توسط رضا رمضانپور
2

عالی بود ممنون

1

سلام
بسیار عالی و بدرد بخور بود واقعا ممنون
شدیدا منتظر Filter hook :smile13:

2

سلام خیلی عالی بود ادامش نمیاد؟

3

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

FILTER HOOK

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

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

Action Hook:
call_user_func($func);

Filter Hook:

$content = call_user_func($func,$content);
 ...
 return $content;

همونطور که میبینید در کد اول که در تابع hook_action مربوط به Action hook داشتیم ما تابع تعریف شده توسط کاربر رو فراخوانی میکنیم بدون اینکه نتیجه رو برگردونیم. اما در کد دوم نتیجه اجرای توابع برگشت داده میشه.

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

تابع hook_filter هم مثل hook_action هست با دو تغییر کوچک که در بالا گفته شد + یک پارامتر برای دریافت نام متغیری که محتوای اون باید توسط توابع ما تغییر کنه . یعنی متغیری رو به عنوان ورودی به این تابع ارسال میکنیم بعد از انجام تغییرات، محتوای جدید به عنوان خروجی به ما تحویل داده میشه :

<?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
function register_filter($event, $func)
{
	global $filter_events;
	$filter_events[$event][] = $func;
}
?>

حالا تصور کنید ما در حال توسعه یک CMS هستیم و در برنامه خودمون تابعی به نام show_content برای نمایش محتویات پست داریم. در حالت عادی اگر گاربر بخواد در تمامی پست ها تغییری ایجاد کنه انجام این کار حتما خیلی سخت خواهد بود اما با استفاده از Filter hook این کار براحتی انجام میشه:

<?php
function show_content($content) {
	$content = hook_filter('the_content',$content);
	echo $content;
}
?>

در فایل پلاگین(افزونه) کدی شبیه به این مینویسیم:

<?php
register_filter('the_content','hotstuff');

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

حالا اگر تابع show_content رو به این شکل اجرا کنیم:

show_content('Hello. I like ice cream.');

نتیجه Hello. I like hot cream خواهد بود چون ما در فایل پلاگین تمام کلمات "ice"رو با "hot" جایگزین کردیم.

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

آخرین ویرایش: 09-04-2018 ???? 15:51، توسط رضا رمضانپور
2

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

سوال برنامه نویسی دارید؟

ندونستن عیب نیست، نپرسیدن چرا!

خوش آمدید

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