School of Magic PHP

Apa itu sihir dalam PHP? Ini biasanya berarti metode seperti _construct() atau __get() . Metode ajaib dalam PHP adalah celah yang membantu pengembang melakukan hal-hal menakjubkan. Jaringan ini penuh dengan instruksi untuk menggunakannya, yang mungkin Anda kenal. Tetapi bagaimana jika kita mengatakan bahwa Anda bahkan belum melihat keajaiban yang sebenarnya? Lagi pula, semakin Anda tahu bahwa Anda tahu segalanya, semakin banyak sihir yang menghindar dari Anda.



Mari kita jatuhkan kerangka aturan OOP yang sudah ada dan buat yang tidak mungkin dilakukan di sekolah sihir PHP. Guru magis utama dan pertama sekolah adalah Alexander Lisachenko ( NightTiger ). Dia akan mengajarkan pemikiran sulap dan mungkin Anda akan menyukai metode sulap, cara non-standar mengakses properti, mengubah konteks, pemrograman berorientasi aspek, dan filter aliran.


Alexander Lisachenko adalah kepala departemen pengembangan web dan arsitektur di Alpari. Penulis dan pengembang utama kerangka kerja berorientasi aspek Go! Aop . Pembicara di konferensi internasional tentang PHP.

Dalam film bagus "The Illusion of Deception" ada ungkapan:
"Semakin dekat kamu, semakin sedikit kamu melihat."

Hal yang sama dapat dikatakan tentang PHP, sebagai trik sulap yang memungkinkan Anda melakukan hal-hal yang tidak biasa. Tapi pertama-tama, itu dibuat untuk menipu Anda: "... tindakan yang dimaksudkan untuk menipu, baik sebagai cara menipu seseorang, atau sebagai lelucon atau bentuk hiburan."

Jika kami menggabungkan PHP dan mencoba menulis sesuatu yang ajaib di dalamnya, kemungkinan besar saya akan menipu Anda. Saya akan melakukan beberapa trik, dan Anda akan lama bertanya-tanya mengapa ini terjadi. Itu karena PHP adalah bahasa pemrograman yang dikenal karena hal-hal yang tidak biasa.

Peralatan sulap


Apa yang kita butuhkan dari peralatan sulap? Metode yang sangat familiar.

__construct(), __destruct(), __clone(),
__call(), __callStatic(),
__get(), __set(), __isset(), __unset(),
__sleep(), __wakeup(),
__toString(), __invoke(), __set_state(),
__debugInfo()


Saya akan mencatat metode terakhir secara terpisah - dengan itu Anda dapat memutar hal-hal yang tidak biasa. Tapi itu belum semuanya.

  • declare(ticks=1) .
  • debug_backtrace() . Ini adalah teman kita untuk memahami di mana kita berada dalam kode saat ini, untuk melihat siapa yang memanggil kita dan mengapa, dengan argumen apa. Berguna untuk memutuskan untuk tidak mengikuti semua logika.
  • unset(), isset() . Tampaknya tidak ada yang istimewa, tetapi desain ini menyembunyikan banyak trik, yang akan kami pertimbangkan lebih lanjut.
  • by-reference passing . Ketika kami melewati beberapa objek atau variabel dengan referensi, kami harus berharap bahwa beberapa sihir pasti akan terjadi pada Anda.
  • bound closures . Pada penutupan dan fakta bahwa mereka dapat mengikat, Anda dapat membangun banyak trik.
  • API Refleksi membantu membawa refleksi ke tingkat yang baru.
  • API StreamWrapper.

Peralatan sudah siap - saya akan mengingatkan aturan sihir pertama.

Selalu menjadi pria terpintar di ruangan itu.

Trik # 1. Perbandingan yang tidak mungkin


Mari kita mulai dengan trik pertama, yang saya sebut Impossible Comparison.
Perhatikan kode ini dan lihat apakah ini bisa terjadi di PHP.



Ada variabel, kami menyatakan nilainya, dan kemudian tiba-tiba tidak sama dengan dirinya sendiri.

Bukan angka


Ada artefak magis seperti NaN - Bukan-nomor.



Fitur luar biasa adalah bahwa itu tidak sama dengan dirinya sendiri. Dan ini trik pertama kami: gunakan NaN untuk mengacaukan teman. Tetapi NaN bukan satu-satunya solusi untuk tugas ini.

Kami menggunakan konstanta




Kuncinya adalah kita dapat mendeklarasikan false sebagai true untuk namespace dan membandingkan. Pengembang yang tidak beruntung akan bertanya-tanya untuk waktu lama mengapa ada yang true dan tidak false .

Handler


Trik berikutnya adalah artileri yang lebih kuat dari dua opsi sebelumnya. Mari kita lihat cara kerjanya.



Triknya didasarkan pada tick_function dan, seperti yang saya sebutkan, declare(ticks=1) .

Bagaimana semuanya bekerja di luar kotak? Pertama, kami mendeklarasikan beberapa fungsi, dan dengan referensi dibutuhkan parameter isMagic , dan kemudian mencoba mengubah nilai ini menjadi true . Setelah kami mendeklarasikan declare(ticks=1) , penerjemah PHP memanggil register_tick_function - callback setelah setiap operasi dasar. Dalam panggilan balik ini, kita dapat mengubah nilai yang sebelumnya false menjadi true . Keajaiban!

Trik # 2. Ekspresi ajaib


Ambil contoh di mana dua variabel dideklarasikan. Salah satunya false , yang lain true . Kami isBlack dan isWhite dan var_dump hasilnya. Menurut Anda apa hasilnya?



Operator prioritas . Jawaban yang benar false , karena dalam PHP ada yang namanya "operator didahulukan".



Anehnya, operator logis or prioritas kurang dari operasi penugasan. Oleh karena itu, hanya menetapkan false terjadi. Di isWhite bisa ada ekspresi lain yang akan dijalankan jika bagian pertama gagal.

Ekspresi ajaib


Lihatlah kode di bawah ini. Ada beberapa kelas yang berisi konstruktor, dan beberapa pabrik, kodenya akan lebih jauh.



Perhatikan baris terakhir.

 $value = new $factory->build(Foo::class); 

Ada beberapa opsi yang bisa terjadi.

  • $factory akan digunakan sebagai nama kelas yang new ;
  • akan ada kesalahan penguraian;
  • panggilan $factory->build() akan digunakan, nilai fungsi ini akan kembali, hasilnya akan new ;
  • nilai properti $factory->build akan digunakan untuk membangun kelas.

Mari kita periksa ide terakhir. Di kelas $factory , kami mendeklarasikan serangkaian fungsi ajaib. Mereka akan menulis apa yang kita lakukan: memanggil properti, memanggil metode, atau bahkan mencoba memanggil invoke pada objek.

 class Factory { public function _get($name) {echo "Getting property {$name}"; return Foo::class;} public function _call($name, $arg) {echo "Calling method {$name}"; return Foo::class;} public function _invoke($name) {echo "Invoking {$name}"; return Foo::class;} } 

Jawaban yang benar: kami tidak memanggil metode, tetapi properti. Setelah $factory->build ada parameter untuk konstruktor, yang akan kami sampaikan ke kelas ini.

Omong-omong, dalam kerangka ini saya telah menerapkan fitur yang disebut "mencegat penciptaan objek baru" - Anda dapat "mengunci" desain ini.

Celah Parser


Contoh berikut adalah untuk parser PHP itu sendiri. Pernahkah Anda mencoba fungsi panggilan atau menetapkan variabel di dalam kurung kurawal?



Saya mendapatkan trik ini di Twitter, ini berfungsi sangat tidak standar.

 $result = ${'_' . !$_=getCallback()}(); $_=getCallback(); // string(5) "hello" !$_=getCallback()}(); // bool(false) '_'.!$_=getCallback()}(); // string(1) "_" ${'_'.!$_=getCallback()}(); // string(5) "hello" 

Pertama, kami menetapkan nilai ekspresi ke variabel bernama _ (garis bawah). Kami sudah memiliki variabel, kami mencoba untuk membalikkan nilainya secara logis, dan kami mendapatkan false - garis dicor seolah-olah menjadi true . Kemudian kami merekatkan semuanya menjadi satu dalam nama variabel, yang kemudian kami masukkan ke dalam kurung keriting.

Apa itu sihir? Ini adalah hiburan yang memungkinkan kita untuk merasa terinspirasi, tidak biasa, katakan: β€œApa? Jadi itu mungkin?! ”

Trik # 3. Melanggar aturan


Yang saya sukai tentang PHP adalah Anda bisa melanggar aturan yang dibuat semua orang dalam upaya untuk menjadi super aman. Ada desain yang disebut "kelas tertutup" yang memiliki konstruktor pribadi. Tugas Anda sebagai murid pesulap adalah membuat instance kelas ini.



Pertimbangkan tiga opsi untuk bagaimana melakukan ini.

Penanganan masalah


Cara pertama adalah yang paling jelas. Itu harus akrab bagi setiap pengembang - ini adalah API standar yang ditawarkan oleh bahasa tersebut kepada kami.



Konstruk newInstanceWithoutConstructor memungkinkan Anda untuk melewati batasan bahasa bahwa konstruktor bersifat pribadi dan membuat turunan kelas dengan melewati semua deklarasi konstruktor pribadi kami.

Opsi ini berfungsi, sederhana, tidak memerlukan penjelasan apa pun.

Hubungan pendek


Opsi kedua membutuhkan lebih banyak perhatian dan keterampilan. Fungsi anonim dibuat, yang kemudian mengikat osprey kelas itu.



Di sini kita berada di dalam kelas dan dapat memanggil metode pribadi dengan aman. Kami menggunakan ini dengan memanggil new static dari konteks kelas kami.



Deserialisasi


Opsi ketiga adalah yang paling maju, menurut saya.



Jika Anda menulis baris tertentu dalam format tertentu, gantikan nilai-nilai tertentu di sana - kelas kami akan berubah.



Setelah deserialisasi, kita mendapatkan instance kita.

paket doktrin / instantiator


Sihir sering menjadi kerangka atau perpustakaan yang terdokumentasi - misalnya, dalam doktrin / instantiator semua ini diterapkan. Kita dapat membuat objek apa pun dengan kode apa pun.

 composer show doctrine/instantiator --all name : doctrine/instantiator descrip. : A small, lightweight utility to instantiate objects in PHP without invoking their constructors keywords : constructor, instantiate type : library license : MIT License (MIT) 

Trik # 4. Mencegah akses properti


Awan berkumpul: kelas adalah rahasia, properti dan konstruktor bersifat pribadi, dan juga callback.

 class Secret { private $secret = 42; private function _construct() { echo 'Secret is: ', $this->secret; } private function onPropAccess(string $name) { echo "Accessing property {$name}"; return 100500; } } // How to create a secret instance and intercept the secret value? 

Tugas kita, sebagai penyihir, entah bagaimana untuk memanggil panggilan balik.

Menambahkan keajaiban ... pengambil


Tambahkan sejumput sihir untuk membuatnya bekerja.



Sejumput sihir ini adalah getter sihir. Itu memanggil fungsi, dan sejauh ini tidak ada hal buruk yang terjadi. Tapi kita akan menggunakan trik sebelumnya dan membuat instance dari objek ini melewati konstruk pribadi.



Sekarang kita perlu entah bagaimana memanggil panggilan balik.

"Tidak disetel" di dalam sirkuit


Untuk melakukan ini, buat penutupan. Di dalam penutupan yang ada dalam ruang lingkup kelas, kami menghapus variabel ini dengan fungsi unset() .



unset memungkinkan Anda untuk sementara mengecualikan variabel, yang akan memungkinkan metode sulap kami dipanggil.

Kami memanggil konstruktor pribadi


Karena kami memiliki konstruktor pribadi yang menampilkan echo , Anda bisa mendapatkan konstruktor ini, membuatnya dapat diakses dengan memanggilnya.



Jadi kelas rahasia kami hancur berkeping-keping.



Kami menerima pesan bahwa kami:

  • dicegat;
  • mengembalikan sesuatu yang sama sekali berbeda.

paket leedavis / altr-ego


Banyak sihir sudah didokumentasikan. Paket altr-ego hanya berpura-pura menjadi komponen Anda.

 composer show leedavis81/altr-ego --all name : leedavis81/altr-ego descrip. : Access an objects protected / private properties and methods keywords : php, break scope versions : dev-master, v1.0.2, v1.0.1, v1.0.0 type : library license : MIT License (MIT) 

Anda dapat membuat salah satu objek dan menempelkannya sebentar. Ini akan memungkinkan perubahan pada fasilitas. Dia akan berubah dengan patuh dan memenuhi semua keinginan Anda.

Trik # 5. Objek tidak berubah dalam PHP


Apakah ada objek yang tidak dapat diubah dalam PHP? Ya, dan waktu yang sangat, sangat lama.

 namespace Magic { $object = (object) [ "\0Secret\0property" => 'test' ]; var_dump($object); } 

Dapatkan mereka dengan cara yang menarik. Yang menarik adalah kita membuat array yang memiliki kunci khusus . Dimulai dengan konstruksi \0 - ini adalah karakter byte nol, dan setelah Secret kita juga melihat \0 .

Konstruk digunakan dalam PHP untuk mendeklarasikan properti pribadi di dalam kelas. Jika kita mencoba untuk melemparkan objek ke array, kita akan melihat kunci yang sama. Kami tidak memiliki apa-apa selain stdClass . Ini berisi properti pribadi dari kelas Secret , yang setara dengan test .

 object(stdClass) [1] private 'property' (Secret) => string 'test' (length=4) 

Satu-satunya masalah adalah - maka Anda tidak bisa mendapatkan properti ini dari sana. Itu dibuat, tetapi tidak tersedia.

Saya pikir itu agak merepotkan - kita memiliki benda yang tidak dapat diubah, tetapi Anda tidak dapat menggunakannya. Karena itu, saya memutuskan bahwa sudah waktunya untuk mengajukan keputusan saya. Saya menggunakan semua pengetahuan dan sihir saya yang tersedia di PHP untuk membuat konstruksi berdasarkan semua trik sulap kami.

Mari kita mulai dengan yang sederhana - buat DTO dan coba untuk mencegat semua properti di dalamnya (lihat trik sebelumnya).

Kami menyimpan di tempat yang aman nilai-nilai yang kami tangkap dari sana. Mereka tidak akan dapat diakses dengan metode apa pun: baik reflection , maupun penutupan, atau sihir lainnya. Tetapi ada ketidakpastian - apakah ada tempat seperti itu di PHP yang akan menjamin untuk menyimpan beberapa variabel sehingga tidak ada programmer muda yang licik bisa sampai di sana?

Kami menyediakan metode ajaib sehingga Anda dapat membaca nilai ini. Untuk melakukan ini, kami memiliki getters sihir, metode isset sihir yang memungkinkan kami untuk menyediakan API.

Mari kita kembali ke tempat yang dapat diandalkan dan mencoba mencari.

  • Global variables dibatalkan - siapa pun dapat mengubahnya.
  • Public properties juga tidak cocok.
  • Protected properties begitu-begitu saja, karena kelas anak akan melewati.
  • Private properties . Tidak ada kepercayaan, karena melalui penutupan atau melalui reflection dapat diubah.
  • Private static properties dapat dicoba, tetapi reflection juga pecah.

Tampaknya tidak ada tempat untuk menyembunyikan nilai-nilai variabel. Tapi ada hal ajaib - Static variables in functions - ini adalah variabel yang ada di dalam fungsi.

Penyimpanan nilai yang aman


Saya bertanya kepada Nikita Popov dan Jay Watkins tentang hal itu di saluran Stack Overflow khusus.



Ini adalah fungsi di mana variabel statis dideklarasikan. Apakah mungkin untuk keluar dari itu, mengubahnya? Jawabannya adalah tidak.

Kami telah menemukan celah kecil di dunia variabel terlindungi lainnya dan kami ingin menggunakannya.

Melewati Nilai oleh Tautan


Kami akan menggunakannya secara non-standar sebagai properti objek. Tetapi Anda tidak dapat melewati properti, jadi kami menggunakan transfer nilai klasik dengan referensi.



Ternyata ada kelas di mana ada metode callStatic ajaib, dan variabel Static dideklarasikan di dalamnya. Dalam setiap panggilan ke beberapa fungsi, kami meneruskan nilai variabel dari objek yang tidak dapat diubah dengan merujuk ke semua metode bersarang kami. Jadi kami menyediakan konteks.

Simpan status


Mari kita lihat bagaimana negara diselamatkan.



Sederhana saja. Untuk objek yang ditransfer, kami menggunakan fungsi spl_object_id , yang mengembalikan pengenal terpisah untuk setiap instance. State yang sudah kita dapatkan dari objek mencoba menyelamatkan di sana. Tidak ada yang istimewa.

Terapkan status objek


Di sini sekali lagi ada konstruksi untuk meneruskan nilai dengan referensi dan properti unset . Kami menghapus semua properti saat ini, setelah sebelumnya menyimpannya dalam variabel Status, dan mengatur konteks ini untuk objek. Objek tidak lagi berisi properti apa pun, tetapi hanya pengenalnya, yang dideklarasikan menggunakan spl_object_id dan dilampirkan ke objek ini saat masih hidup.



Dapatkan Negara


Maka semuanya sederhana.



Kami mendapatkan konteks ini pada getter sihir dan memanggil properti kami darinya. Sekarang tidak ada seorang pun dan tidak ada yang dapat mengubah nilai setelah Trait terhubung.



Semua metode ajaib ditimpa dan menerapkan kekekalan objek.



lisachenko / objek-abadi


Seperti yang diharapkan, semuanya langsung diformalkan di perpustakaan dan siap digunakan.

 composer show /immutable-object --all name : /immutable-object descrip. : Immutable object library keywords : versions : * dev-master type : library license : MIT License (MIT) 

Perpustakaannya terlihat sangat sederhana. Kami menghubungkannya dan membuat kelas kami. Ini memiliki sifat yang berbeda: pribadi, dilindungi dan publik. Kami menghubungkan ImmutableTrait .



Setelah itu, Anda dapat memulai objek sekali - lihat nilainya. Itu benar-benar disimpan di sana dan bahkan terlihat seperti DTO nyata.

 object (MagicObject) [3] public 'value' => int 200 

Tetapi jika kita mencoba mengubahnya, misalnya, seperti ini ...



... maka segera dapatkan fatal exception . Kami tidak dapat mengubah properti karena properti itu tidak dapat diubah. Bagaimana bisa begitu?



Jika Anda terlibat dalam tantangan yang menarik dan mencoba merendahkannya, Anda mendapatkan yang berikut ini.



Ini hadiah saya. Segera setelah Anda mencoba untuk gagal di dalam PHPStorm di dalam kelas ini, itu akan langsung menghentikan eksekusi perintah Anda. Saya tidak ingin Anda mempelajari kode ini - terlalu berbahaya. Dia akan memperingatkan bahwa tidak ada yang bisa dilakukan.

Trik # 6. Pengolahan benang


Pertimbangkan desainnya.

 include 'php://filter/read=string.toupper/resource=magic.php'; 

Ada sesuatu yang ajaib: filter PHP, read , pada akhirnya semacam file magic.php terhubung . File ini terlihat sangat sederhana.

 <?php echo 'Hello, world!' 

Perhatikan bahwa kasingnya berbeda. Namun, jika kami "mengisi" file melalui desain kami, maka kami mendapatkan ini:

 HELLO, WORLD! 

Apa yang terjadi pada saat itu? Menggunakan konstruksi filter PHP di include memungkinkan Anda untuk menghubungkan filter apa pun, termasuk milik Anda, untuk menganalisis kode sumber. Anda mengelola semuanya dalam kode sumber ini. Anda dapat menghapus final dari kelas dan metode, membuat properti publik - apa pun yang Anda bisa crank melalui hal ini

Bagian dari kerangka aspek saya didasarkan pada ini. Ketika kelas Anda terhubung, itu menganalisis dan mengubahnya menjadi apa yang akan dieksekusi.

Di luar kotak di PHP sudah ada sejumlah filter siap pakai.

 var_dump(stream_get_filters()); array (size=10) 0 => string 'zlib.*' (length=6) 1 => string 'bzip2.*' (length=7) 2 => string 'convert.iconv.*' (length=15) 3 => string ' string.rotl3' (length=12) 4 => string 'string.toupper' (length=14) 5 => string 'string.tolower' (length=14) 6 => string 'string.strip_tags' (length=17) 7 => string 'convert.*' (length=9) 8 => string 'consumed' (length=8) 9 => string 'dechunk' (length=7) 

Mereka memungkinkan Anda untuk "zip" konten, menerjemahkannya ke huruf besar atau kecil.

Trik utama yang ingin saya tampilkan sudah berakhir. Sekarang mari kita beralih ke intisari dari semua yang bisa saya lakukan - pemrograman berorientasi aspek.

Trik # 7. Pemrograman Berorientasi Aspek


Lihatlah kode ini dan pikirkan apakah itu baik atau buruk dari sudut pandang Anda.



Kode tampaknya cukup memadai. Ia memeriksa hak akses, melakukan pencatatan, membuat pengguna, tetap ada, mencoba menangkap exception .

Jika Anda melihat semua mie ini, mie ini diulang dalam setiap metode kami, dan satu-satunya hal yang berharga di sini adalah mie itu ditandai dengan warna hijau.



Yang lainnya: "keprihatinan sekunder" atau "keprihatinan lintas sektoral" adalah fungsi lintas sektoral.

OOP konvensional membuat tidak mungkin untuk menyalin semua struktur ini dengan copy-paste, menghapusnya, dan mengeluarkannya di suatu tempat. Ini buruk karena Anda harus mengulanginya. Saya berharap kode selalu terlihat bersih dan rapi.



Sehingga tidak mengandung logging (biarkan diterapkan entah bagaimana) dan tidak mengandung security .



Jadi itu saja, termasuk masuk ...



... dan pemeriksaan keamanan, ...



... dilakukan dengan sendirinya.

Dan itu mungkin.

Glosarium "Aspek"


Ada hal yang disebut Aspect. Ini adalah contoh sederhana yang memeriksa izin. Berkat dia, Anda dapat melihat beberapa anotasi, yang juga disorot oleh plugin untuk PhpStorm. "Aspect" menyatakan ekspresi SQL yang menunjukkan kode untuk menerapkan kondisi ini. Di bawah, misalnya, kami ingin menerapkan penutupan untuk semua metode publik dari kelas UserService .



Kami mendapatkan penutupan menggunakan metode $invocation .



Ini adalah semacam pembungkus di atas metode reflection , yang berisi lebih banyak argumen.

Lebih lanjut dalam panggilan balik ini untuk setiap metode, Anda dapat memeriksa hak akses yang diperlukan, ini disebut "Saran".



Kami agak mengatakan bahasanya: "PHP yang terhormat, mohon terapkan metode ini sebelum setiap panggilan ke metode publik dari kelas UserService " Hanya satu baris, tetapi banyak yang bermanfaat.

Aspek vs Pendengar Acara


Untuk membuatnya lebih jelas, saya membuat perbandingan Aspect dengan Event Listener. Banyak yang bekerja di Symfony dan tahu apa itu Event Dispatcher.



Mereka serupa di mana kita melewati semacam ketergantungan, misalnya, AutorizationChecker , dan menyatakan di mana harus diterapkan dalam kasus ini. Dalam kasus Listener, ini adalah SubscrabingEvent disebut UserCreate , dan dalam kasus Aspect kami berlangganan semua panggilan ke metode publik dari UserService .Pada saat yang sama, isi dari penangan panggilan balik itu sendiri kira-kira sama: kami hanya memeriksa sesuatu dan bereaksi sesuai.

Pertimbangkan cara kerjanya di bawah tenda.

Langkah pertama yang membutuhkan kerangka aspek adalah pendaftaran Aspects .



Tahap kedua . Untuk menangani ini, trik sebelumnya dengan filter PHP digunakan lagi .



Ini adalah komponen khusus yang mengubah kode sumber. Dia melakukan ini secara diam-diam, tetapi dia akan bekerja dengan baik dalam produksi, karena dia terintegrasi dengan OPcache.

Tahap ketiga . Semuanya terintegrasi pada level Composer. Setelah Go diinstal! AOP, dia mulai berkomunikasi dengan dekatComposer , .



Aspects , Aspects . .

.

PHP-Parser . , , . , , PHP-Parser . .



. , goaop/parser-reflection .



AST- , . , , , .

.



, , Aspect .



, .



, , . β€” , - , .



, . , .

Aspect MOCK. «», , . .

β€” joinPoint . - joinPoint : , , .

Apa selanjutnya


.

OPcache preloading for AOP Core . AOP- . 10 . Bootstrapping , PHP.

FFI integration to modify binary opcodes . , , . PHP-opcodes, .bin . FFI .

Modifying PHP engine internal callbacks PHP- userland. PHP . FFI PHP userland, , , . .

, .

#8. goaop/framework


, GitHub .

 composer show goaop/framework --all name : goaop/framework descrip. : Framework for aspect-oriented programming in PHP. keywords : php, aop, library, aspect versions : dev-master, 3.0.x-dev, 2.x-dev, 2.3.1, … type : library license : MIT License 

, PhpStorm.



, Pointcuts. , , . β€” , , .

Trick #9.


. , .

: , - . fastcgi_finish_request . , , , - callback β€” .

?

, Deffered , , .



Aspect , , , Deffered , .



Aspect : , , , callback, , callback. .

React , promise . , - , - , .

, .



shutdown_function Aspect . , callback, , , , callback onPhpTerminate . fastcgi_finish_request : Β«, , , , Β». .

, sendPushNotification .



, - β€” 2 .



, , , 2 .

, Deferred .



, . - , , .

Itu saja. , - . , .

PHP Russia 2020 . β€” . telegram- , PHP Russia 2020.

Source: https://habr.com/ru/post/id478618/


All Articles