در زبان پی اچ پی، callable یک نوع داده (data type) است که بیان می کند یک چیز می تواند مثل یک تابع (function) فراخوانی شود. شما می توانید مقدار این نوع داده را به روش های مختلفی تعریف کنید و از آن مثل یک تابع استفاده کنید. در PHP، انواع توابع شامل تابع های عادی، تابع های ناشناس (anonymous functions) و arrow function ها، یک متد از یک کلاس (خواه متد استاتیک باشد خواه داینامیک؛ البته با رعایت نکاتی که شرح داده خواهد شد) و کلاس های invokable به عنوان callable شناخته می شوند.
توابع به عنوان callable
همانطور که گفته شد یک تابع عادی در PHP می تواند مثل یک callable در نظر گرفته شود. در این روش اسم تابع به عنوان یک string می تواند برای اشاره به تابع، مورد استفاده قرار بگیرد. یک مثال از این کاربرد را می توانید در کد زیر مشاهده کنید.
// An example function
function my_function()
{
return 'hello world!';
}
// Calling the function
call_user_func('my_function');
تکه کد بالا تابع my_funciton را صدا می زند و نتیجه ی آن که ‘hello world!’ است را بر می گرداند.
فلسفه ی بالا برای توابع ناشناس و arrow function ها نیز برقرار است. تکه کد زیر این مسئله را نشان می دهد.
call_user_func(function () {
return 'hello world!';
});
call_user_func(fn() => 'hello world!');
متد یک کلاس به عنوان callable
متد های استاتیک یک کلاس نیز یک callable به حساب می آیند و می توان آن ها را با متد call_user_func در PHP صدا زد. برای صدا زدن یک متد از کلاس یک آرایه ایجاد می کنیم که در اندیس اول (index = 0) آن نام کلاس یا یک شیء از آن کلاس و در اندیس بعدی (index = 1) نام متدی که می خواهیم صدا زده شود را به صورت یک رشته (string) قرار می دهیم. یک نمونه از این طرز کار را در کد زیر می توانید مشاهده کنید.
ابتدا کلاس را تعریف می کنیم:
class MyClass
{
static function myCallableMethod()
{
return 'Hello World!';
}
}
در روش اول نام کلاس را به عنوان ورودی مشخص می کنیم.
call_user_func(['MyClass', 'myCallableMethod']);
در روش دوم یک شیء از کلاسمان را به عنوان ورودی می دهیم.
$object = new MyClass();
call_user_func([$object, 'myCallableMethod']);
همچنین ما می توانیم نام متد های استاتیک را همراه با نام کلاسشان به صورت ClassName::staticMethodName
برای اشاره به آن ها استفاده کنیم. یعنی متد استاتیک بالا را می توان به صورت زیر بدون تعریف آرایه صدا زد.
call_user_func('MyClass::myCallableMethod');
لازم به ذکر است که فقط متد های استاتیک از کلاس ما می توانند خارج از کلاس به عنوان یک callable استفاده شوند؛ اما این قابلیت درون خود کلاس به قوت خود باقی است. برای مثال در کد زیر داخل یک متد از کلاس، متد دیگری را به عنوان یک callable استفاده می کنیم.
class MyClass
{
function myCallableMethod()
{
return 'Hello World!';
}
function callerMethod()
{
$result = call_user_func(['MyClass', 'myCallableMethod']);
return $result;
}
}
$object = new MyClass();
$object->callerMethod();
همچنین در این مورد می توان به جای نام کلاس از this$ استفاده کنیم که به همان شیء ساخته شده از کلاس اشاره می کند.
class MyClass
{
function myCallableMethod()
{
return 'Hello World!';
}
function callerMethod()
{
$result = call_user_func([$this, 'myCallableMethod']);
return $result;
}
}
$object = new MyClass();
$object->callerMethod();
کلاس invokable به عنوان callable
در PHP این قابلیت وجود دارد که شما با یک کلاس مثل یک تابع رفتار کنید. تنها قدم برای اینکه یک کلاس callable باشد این است که متد invoke__
در آن تعریف شده باشد. در واقع زمانی که شما کلاس را به عنوان یک تابع فراخوانی می کنید، PHP متد invoke__
را صدا می زند و نتیجه ی آن را بر می گرداند. یک نمونه از کلاس invokable در کد زیر آورده شده است.
class MyClass
{
public function __invoke()
{
return 'Hello World!';
}
}
$object = new MyClass();
call_user_func($object);
مثالی از کاربرد callable
از PHP نسخه ی 5.4.0 به بعد شما می توانید نوع ورودی تابع خود را به عنوان callable تعیین کنید. یعنی شما انتظار دارید که بتوانید با ورودی تابعتان مثل یک تابع رفتار کنید. برای مثال کد زیر را در نظر بگیرید:
function my_function(callable $callable)
{
return call_user_func($callable);
}
my_function(function () {
return 'Hello World.';
});
در این کد ابتدا یک تابع تعریف می کنیم که ورودی آن باید از نوع callable باشد و درون آن این ورودی را صدا می زنیم و پاسخ آن را بر می گردانیم.
حال برای صدا زدن تابع my_function
به عنوان ورودی به آن یک تابع ناشناس داده ایم. نتیجه ی کد بالا رشته ی ‘Hello World.’ است.
در خود زبان PHP نیز توابعی وجود دارند که به عنوان ورودی خود یک callable می گیرند. یکی از این توابع array_filter است. در این تابع یک آرایه را، با توجه به یک callable که به عنوان ورودی به آن می دهیم، فیلتر می کنیم. در واقع این تابع بین تمام المان های آرایه می گردد و آن ها را به عنوان ورودی به callable می دهد و المان هایی که به ازای آن خرجی callable برابر با true می شود را بر می گرداند. تکه کد زیر را برای واضح شدن موضوع ببینید.
array_filter([1, 2, 3, 4, 5], function($value) {
return ($value % 2) === 0;
});
در این تکه کد المان های زوج آرایه فیلتر می شوند. این کار توسط تابع ناشناسی که به عنوان ورودی به array_filter
دادیم انجام می شود که برای اعداد زوج true و برای اعداد فرد false بر می گرداند.
امیدوارم این مقاله برای شما مفید بوده باشد و به شما کمک کند. در صورتی که سوال یا مشکلی در این باره دارید در قسمت نظرات مطرح کنید و من سعی می کنم در اسرع وقت پاسخ بدهم.