แพ็คเกจ 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 ' );