
Untuk debugging program PHP sering menggunakan Xdebug . Namun, fitur standar IDE dan Xdebug tidak selalu cukup. Beberapa masalah dapat diselesaikan dengan menggunakan proxy Xdebug - pydbgpproxy, tetapi masih belum semuanya. Oleh karena itu, saya mengimplementasikan proksi PHP Xdebug berdasarkan kerangka kerja asinkron amphp.
Di bawah potongan, saya akan memberi tahu Anda apa yang salah dengan pydbgpproxy, apa yang hilang di dalamnya dan mengapa saya tidak memodifikasinya. Saya juga akan menjelaskan bagaimana proksi PHP Xdebug bekerja dan menunjukkan cara memperpanjangnya menggunakan contoh.
Pydbgpproxy vs PHP Xdebug proxy
Proxy Xdebug adalah layanan perantara antara IDE dan Xdebug (permintaan proksi dari Xdebug ke IDE dan sebaliknya). Paling sering digunakan untuk debugging multi-pengguna . Ini adalah ketika Anda memiliki satu server web, dan beberapa pengembang.
Sebagai proxy, pydbgpxxy biasanya digunakan. Tetapi dia memiliki beberapa masalah:
- tidak ada halaman resmi;
- sulit menemukan tempat untuk mengunduhnya; ternyata ini dapat dilakukan di sini - tiba-tiba, Klien Debugging Jarak Jauh Python;
- Saya tidak menemukan repositori resmi;
- sebagai konsekuensi dari paragraf sebelumnya, tidak jelas kemana harus mengajukan permintaan tarik;
- proxy, seperti namanya, ditulis dalam Python, yang tidak semua pengembang PHP tahu, yang berarti memperluasnya adalah masalah;
- kelanjutan dari paragraf sebelumnya: jika ada kode dalam PHP, dan itu harus digunakan dalam proxy, maka harus porting ke Python, dan duplikasi kode selalu tidak baik.
Pencarian untuk proxy Xdebug yang ditulis dalam PHP di GitHub dan di Internet tidak membuahkan hasil. Jadi saya menulis proksi PHP Xdebug . Di bawah tenda, saya menggunakan kerangka asynchronous amphp .
Keuntungan utama proksi PHP Xdebug dibandingkan pydbgpproxy:
- Proxy PHP Xdebug ditulis dalam bahasa yang akrab bagi pengembang PHP, yang berarti:
- lebih mudah untuk memecahkan masalah di dalamnya;
- lebih mudah berkembang;
- Proxy PHP Xdebug memiliki repositori publik, yang berarti:
- Anda dapat melakukan fork dan menyelesaikannya sesuai kebutuhan Anda;
- Anda dapat mengirim permintaan tarik dengan fitur yang hilang atau solusi untuk masalah.
Cara bekerja dengan proksi PHP Xdebug
Instalasi
Proxy PHP Xdebug dapat diinstal sebagai dependensi dev melalui komposer :
composer.phar require mougrim/php-xdebug-proxy --dev
Tetapi jika Anda tidak ingin menyeret dependensi tambahan ke proyek Anda, maka proksi PHP Xdebug dapat diinstal sebagai proyek melalui komposer yang sama:
composer.phar create-project mougrim/php-xdebug-proxy cd php-xdebug-proxy
Proxy PHP Xdebug dapat dikembangkan, tetapi ext-dom diperlukan secara default (ekstensi diaktifkan secara default di PHP) untuk mem- parsing XML dan amphp / log untuk logging asinkron:
composer.phar require amphp/log '^1.0.0'
Luncurkan

Proxy dimulai sebagai berikut:
bin/xdebug-proxy
Proxy akan mulai dengan pengaturan default:
Using config path /path/to/php-xdebug-proxy/config [2019-02-14 10:46:24] xdebug-proxy.NOTICE: Use default ide: 127.0.0.1:9000 array ( ) array ( ) [2019-02-14 10:46:24] xdebug-proxy.NOTICE: Use predefined ides array ( 'predefinedIdeList' => array ( 'idekey' => '127.0.0.1:9000', ), ) array ( ) [2019-02-14 10:46:24] xdebug-proxy.NOTICE: [Proxy][IdeRegistration] Listening for new connections on '127.0.0.1:9001'... array ( ) array ( ) [2019-02-14 10:46:24] xdebug-proxy.NOTICE: [Proxy][Xdebug] Listening for new connections on '127.0.0.1:9002'... array ( ) array ( )
Dari log Anda dapat melihat bahwa proxy default:
- mendengarkan
127.0.0.1:9001
untuk koneksi login IDE; - mendengarkan
127.0.0.1:9002
untuk koneksi Xdebug; - menggunakan
127.0.0.1:9000
sebagai IDE default dan IDE yang telah ditentukan sebelumnya dengan kunci idekey.
Konfigurasi
Jika Anda ingin mengonfigurasi port mendengarkan, dll., Anda dapat menentukan jalur ke folder pengaturan. Cukup salin folder konfigurasi :
cp -r /path/to/php-xdebug-proxy/config /your/custom/path
Ada tiga file di folder pengaturan:
Setelah menyalin file, Anda dapat mengedit dan menjalankan proxy:
bin/xdebug-proxy --configs=/your/custom/path/config
Debugging
Banyak artikel telah ditulis tentang cara men-debug kode menggunakan Xdebug. Saya akan perhatikan poin utama.
Di php.ini, pengaturan berikut harus di bagian [xdebug]
(koreksi jika berbeda dari yang standar):
- idekey = idekey
- remote_host = 127.0.0.1
- remote_port = 9002
- remote_enable = Aktif
- remote_autostart = Hidup
- remote_connect_back = Mati
Kemudian Anda dapat menjalankan kode PHP yang di-debug:
php /path/to/your/script.php
Jika Anda melakukan semuanya dengan benar, maka debugging akan dimulai dari breakpoint pertama di IDE. Debugging dalam mode php-fpm oleh beberapa pengembang berada di luar cakupan artikel ini, tetapi dijelaskan, misalnya, di sini .
Fitur proxy ekstensi
Segala sesuatu yang kami periksa di atas, pydbgpproksi juga dapat mencapai tingkat tertentu.
Sekarang mari kita bicara tentang proxy PHP Xdebug yang paling menarik. Proxy dapat diperluas menggunakan pabrik Anda sendiri (dibuat di konfigurasi factory.php
, lihat di atas). Pabrik harus mengimplementasikan antarmuka Factory\Factory
.
Yang paling kuat adalah yang disebut penyusun permintaan. Mereka dapat memodifikasi permintaan dari Xdebug ke IDE dan sebaliknya. Untuk menambahkan Factory\DefaultFactory::createRequestPreparers()
kueri, Anda harus mengganti metode Factory\DefaultFactory::createRequestPreparers()
. Metode mengembalikan array objek yang mengimplementasikan antarmuka RequestPreparer\RequestPreparer
. Ketika mem-proksi permintaan dari Xdebug ke IDE, mereka dieksekusi dalam urutan langsung, ketika memproksi permintaan dari IDE ke Xdebug, itu dibalik.
Penangan kueri dapat digunakan, misalnya, untuk mengubah jalur ke file (dalam breakpoints dan file yang dapat dieksekusi).
Debug menimpa file
Untuk memberikan contoh tentang persiapan, saya akan membuat sedikit penyimpangan. Dalam pengujian unit, kami menggunakan soft-mock ( GitHub ). Soft-mock memungkinkan Anda untuk mengganti fungsi, metode statis, konstanta, dll dalam pengujian, merupakan alternatif untuk runkit dan uopz . Ini berfungsi dengan menulis ulang file PHP dengan cepat. Demikian pula, AspectMock masih berfungsi.
Tetapi fitur standar Xdebug dan IDE memungkinkan Anda untuk men-debug ditulis ulang (memiliki jalur yang berbeda), daripada file aslinya.
Mari kita lihat lebih dekat masalah debugging menggunakan soft-mock dalam pengujian. Pertama, ambil kasus di mana kode PHP dieksekusi secara lokal.
Kesulitan pertama muncul pada tahap pengaturan breakpoints (breakpoints). Dalam IDE, mereka dipasang di file asli, bukan yang ditulis ulang. Untuk meletakkan breakpoint melalui IDE, Anda perlu menemukan file yang ditulis ulang yang sebenarnya. Masalahnya diperparah oleh fakta bahwa setiap kali file asli diubah, file yang ditulis ulang baru dibuat, yaitu, untuk setiap konten file yang unik akan ada file yang ditulis ulang yang unik.
Masalah ini dapat diselesaikan dengan memanggil fungsi xdebug_break()
, yang mirip dengan pengaturan breakpoint. Dalam hal ini, tidak perlu mencari file yang ditulis ulang.
Sekarang pertimbangkan situasinya lebih rumit: aplikasi berjalan pada mesin jarak jauh.
Dalam hal ini, Anda dapat memasang folder dengan file yang ditulis ulang, misalnya, melalui SSHFS. Jika jalur lokal dan jarak jauh ke folder berbeda, maka Anda masih perlu mendaftarkan pemetaan di IDE.
Dengan satu atau lain cara, metode ini sedikit berbeda dari yang biasa dan memungkinkan Anda untuk men-debug hanya file yang disalin, tetapi tidak yang asli. Tetapi saya masih ingin mengedit dan men-debug file asli yang sama.
AspectMock mengatasi masalah dengan mengaktifkan mode debug tanpa kemampuan untuk menonaktifkannya:
public function init(array $options = []) { if (!isset($options['excludePaths'])) { $options['excludePaths'] = []; } $options['debug'] = true; $options['excludePaths'][] = __DIR__; parent::init($options); }
Dalam contoh pengujian sederhana, mode debug lebih lambat 20 persen, tetapi saya tidak memiliki cukup tes AspectMock untuk memberikan perkiraan yang lebih akurat tentang seberapa lambatnya. Jika Anda memiliki banyak tes di AspectMock, saya akan senang jika Anda membagikan perbandingan di komentar.
Menggunakan Xdebug dengan soft-mock

Sekarang masalahnya sudah jelas, pertimbangkan bagaimana menyelesaikannya menggunakan proxy PHP Xdebug. Bagian utama adalah di kelas RequestPreparer\SoftMocksRequestPreparer
.
Di konstruktor kelas, tentukan path ke skrip inisialisasi soft-mock dan jalankan (diasumsikan bahwa soft-mock terhubung sebagai dependensi, tetapi setiap jalur dapat dilewati ke konstruktor):
public function __construct(LoggerInterface $logger, string $initScript = '') { $this->logger = $logger; if (!$initScript) { $possibleInitScriptPaths = [

Untuk menyiapkan permintaan dari Xdebug ke IDE, Anda perlu mengganti path ke file yang ditulis ulang dengan file asli:
public function prepareRequestToIde(XmlDocument $xmlRequest, string $rawRequest): void { $context = [ 'request' => $rawRequest, ]; $root = $xmlRequest->getRoot(); if (!$root) { return; } foreach ($root->getChildren() as $child) {

Untuk menyiapkan permintaan dari IDE ke Xdebug, Anda perlu mengganti path ke file asli dengan path ke yang ditulis ulang:
public function prepareRequestToXdebug(string $request, CommandToXdebugParser $commandToXdebugParser): string {
Agar Factory\DefaultFactory
kueri berfungsi, Anda perlu membuat kelas pabrik dan mewarisinya dari Factory\DefaultFactory
, atau mengimplementasikan antarmuka Factory\Factory
. Untuk soft- Factory\SoftMocksFactory
, Factory\SoftMocksFactory
terlihat seperti ini:
class SoftMocksFactory extends DefaultFactory { public function createConfig(array $config): Config {
Di sini Anda memerlukan kelas konfigurasi Anda sendiri sehingga Anda dapat menentukan jalur skrip init soft-mock. Apa itu, Anda bisa lihat di Config \ SoftMocksConfig .
Hanya sedikit yang tersisa: untuk membuat pabrik baru dan menunjukkan jalur ke skrip init soft-mock. Cara ini dilakukan dapat dilihat di softMocksConfig
.
API non-pemblokiran
Seperti yang saya tulis di atas, proksi PHP Xdebug menggunakan amphp di bawah tenda, yang berarti bahwa API non-pemblokiran harus digunakan untuk bekerja dengan I / O. Apmphp sudah memiliki banyak komponen yang mengimplementasikan API non-pemblokiran ini. Jika Anda akan memperpanjang proxy PHP Xdebug dan menggunakannya dalam mode multi-pengguna, maka pastikan untuk menggunakan API non-pemblokiran.
Kesimpulan
Proxy PHP Xdebug masih merupakan proyek yang cukup muda, tetapi di Badoo sudah aktif digunakan untuk men-debug tes menggunakan soft-mock.
Proxy PHP Xdebug:
- menggantikan pydbgpproxy dalam debugging multi-pengguna;
- dapat bekerja dengan soft-mock;
- dapat diperluas:
- Anda dapat mengganti jalur ke file yang berasal dari IDE dan dari Xdebug;
- statistik dapat dikumpulkan: dalam mode debug, setidaknya konteks yang dapat dieksekusi tersedia ketika debugging (nilai variabel dan baris kode yang dapat dieksekusi).
Jika Anda menggunakan proxy Xdebug untuk apa pun selain debugging multi-pengguna, maka bagikan kasus Anda dan proxy Xdebug yang Anda gunakan dalam komentar.
Jika Anda menggunakan pydbgpproksi atau proksi Xdebug lainnya, maka coba proksi PHP Xdebug, ceritakan masalah Anda, bagikan permintaan penarikan. Ayo kembangkan proyek bersama! :)
PS Terima kasih kepada kolega saya Yevgeny Makhrov alias eZH untuk gagasan proxy smdbgpproxy !
Tautan lagi
- PHP Xdebug proxy - proxy Xdebug, yang dibahas dalam artikel;
- pydbgpproxy dapat diunduh di sini - tiba-tiba, Klien Debugging Jarak Jauh Python;
- amphp - kerangka kerja PHP non-blocking asinkron;
- alat untuk mock-s:
Terima kasih atas perhatian anda!
Saya akan senang memberikan komentar dan saran.
Rinat Akhmadeev, Sr. Pengembang PHP
UPD : Terjemahan artikel yang dipublikasikan ke dalam bahasa Inggris.