توفر حزمة PHP Macro حقن التبعية القائم على الإغلاق (وظيفة مجهولة) من خلال توفير سمة يمكن تضمينها في أي فئة.
composer req aimeos/macro
هذه الحزمة مخصصة لمطوري التطبيقات وإطار العمل والمكتبات الذين يرغبون في السماح لمستخدميهم بتخصيص سلوك التعليمات البرمجية الخاصة بهم.
في التطبيقات أو الأطر أو المكتبات التي تم إنشاؤها للتخصيص، من الضروري السماح بالكتابة فوق الوظائف الموجودة لتتمكن من تخصيص سلوكها. هذا هو المكان الذي تكون فيه وحدات الماكرو مفيدة جدًا لأنها يمكنها إضافة تعليمات برمجية مخصصة باستخدام عمليات الإغلاق.
باستخدام حزمة PHP Macro، يمكنك أيضًا السماح للمستخدمين بالكتابة فوق الأساليب في الفئات الأساسية دون إجبار المستخدمين على توسيع هذه الفئات. لا تستخدم حزمة PHP Macro أي انعكاس أو اختراقات أخرى، بل تستخدم فقط أساليب PHP خالصة .
هناك بعض الإيجابيات والسلبيات عند مقارنتها بحقن التبعية على أساس الفصل:
برو:
يخدع:
وبالتالي، فهو ليس بديلاً لحقن التبعية على أساس الفصل ولكنه إضافة خفيفة الوزن لنقاط الامتداد الصغيرة حيث يتطلب حقن التبعية الكامل باستخدام واجهات تنفيذ الفئات الكثير من العمل.
يمكن تعديل نتيجة الطرق الموجودة إذا كانت الطريقة الأصلية تتحقق من وجود ماكرو موجود وتستخدم ذلك بدلاً من التنفيذ الخاص بها:
// original code
class Order
{
use Aimeos Macro Macroable;
private $ id = ' 123 ' ;
public function getOrderNumber ()
{
$ fcn = static :: macro ( ' orderNumber ' );
return $ fcn ? $ fcn ( $ this -> id ) : $ this -> id ;
}
};
الآن، يمكنك إضافة ماكرو orderNumber
المخصص الخاص بك والذي سيتم استخدامه بدلاً من ذلك:
// user code
Order:: macro ( ' orderNumber ' , function ( string $ id ) {
return date ( ' Y ' ) . ' - ' . $ id ;
} );
( new Order )-> getOrderNumber (); // now returns '2020-123'
وبالتالي، يمكنك إنشاء مخرجات خاصة بك أو تمرير نتيجة مختلفة إلى الأساليب اللاحقة داخل التطبيق.
عندما يتم استدعاء وحدات الماكرو في سياق كائن، يمكنها أيضًا الوصول إلى خصائص الفئة:
// original code
class A
{
use Aimeos Macro Macroable;
private $ name = ' A ' ;
};
هنا، الخاصية الخاصة $name
متاحة في الماكرو:
// user code
A:: macro ( ' concat ' , function ( array $ values ) {
return $ this -> name . ' : ' . implode ( ' - ' , $ values );
} );
( new A )-> concat ( [ ' 1 ' , ' 2 ' , ' 3 ' ] ); // returns 'A:1-2-3'
يمكن للماكرو استخدام الخاصية كمدخل لإنشاء القيمة التي تم إرجاعها.
تسمح حزمة الماكرو PHP أيضًا بوراثة وحدات الماكرو من الفئات الأصلية. بعد ذلك، يمكنهم الوصول إلى خصائص فئة الفصل الفرعي تمامًا مثل طرق الفصل العادية:
// original code
class A
{
use Aimeos Macro Macroable;
private $ name = ' A ' ;
};
class B extends A
{
private $ name = ' B ' ;
};
ستكون وحدات الماكرو المضافة إلى الفصل الأصلي متاحة في الفصول الفرعية أيضًا:
// user code
A:: macro ( ' concat ' , function ( array $ values ) {
return $ this -> name . ' : ' . implode ( ' - ' , $ values );
} );
( new B )-> concat ( [ ' 1 ' , ' 2 ' , ' 3 ' ] ); // returns 'B:1-2-3'
تمتد الفئة B
من الفئة A
ولكنها توفر خاصية $name
مختلفة. سيستخدم الماكرو الموروث من الفئة A
الآن خاصية الفئة B
من الممكن أيضًا الكتابة فوق وحدات الماكرو الموروثة من الفئات الأصلية كما هو ممكن باستخدام طرق الفئات العادية:
// original code
class A
{
use Aimeos Macro Macroable;
public function do () {
return static :: macro ( ' concat ' )( [ 1 , 2 , 3 ] );
}
};
class B extends A {};
class C extends A {};
يمكنك الآن إضافة وحدات ماكرو إلى الفصل الأصلي وأحد الفئات التابعة:
// user code
A:: macro ( ' concat ' , function ( array $ values ) {
return implode ( ' , ' , $ values );
} );
C:: macro ( ' concat ' , function ( array $ values ) {
return implode ( ' - ' , $ values );
} );
( new B )-> do (); // returns '1,2,3'
( new C )-> do (); // returns '1-2-3'
يمكّنك هذا من إضافة معالجة خاصة للفئات الفردية حتى إذا كانت كافة الفئات الأخرى لا تزال تستخدم الماكرو المضاف إلى الفئة A
غالبًا ما تقدم الفئات الأساسية مجموعة من الأساليب التي تستخدمها الفئات الفرعية. في PHP، يعد استبدال أساليب الفئة الأساسية أمرًا مستحيلًا، وبالتالي، يتعين عليك الكتابة فوق كل فئة فرعية بتطبيقك الخاص.
لتجنب ذلك، يمكن للطريقة الأصلية استخدام طريقة call()
بدلاً من استدعاء طريقة الفئة الأصلية مباشرة:
// original code
class A
{
use Aimeos Macro Macroable;
protected function getName ( $ prefix )
{
return $ prefix . ' A ' ;
}
};
class B extends A
{
public function do ()
{
return $ this -> call ( ' getName ' , ' B- ' );
}
};
سيتحقق هذا مما إذا كان هناك ماكرو getName
متاحًا وسيستدعي ذلك بدلاً من طريقة getName()
:
// user code
( new B )-> do (); // returns 'B-A'
A:: macro ( ' getName ' , function ( $ prefix ) {
return $ this -> getName ( $ prefix ) . ' -123 ' ;
} );
( new B )-> do (); // returns 'B-A-123'
لا يزال من الممكن استخدام طريقة getName()
الأصلية في الماكرو.
في بعض الأحيان، قد يكون من الضروري إزالة وحدات الماكرو من الكائنات، خاصة عند تشغيل الاختبارات الآلية. يمكنك إلغاء تعيين ماكرو باستخدام:
class A
{
use Aimeos Macro Macroable;
};
// add macro
A:: macro ( ' test ' , function () {
return ' test ' ;
} );
// remove macro
A:: unmacro ( ' test ' );