Dalam artikel sebelum ini, kami telah berkenalan dengan keupayaan komponen carian pintar Joomla, bercakap tentang parameter dan konfigurasi pengindeksan berjadual menggunakan CRON. Mari mula mencipta kod untuk pemalam kita sendiri.
Sebelum memulakan bahagian teknikal, saya akan menyebut beberapa artikel yang secara langsung menyentuh topik utama. Serta artikel yang secara amnya merangkumi penciptaan dan/atau pengemaskinian pemalam untuk seni bina moden Joomla 4 / Joomla 5. Seterusnya, saya akan menganggap bahawa pembaca telah membacanya dan secara amnya mempunyai idea tentang cara membuat pemalam yang berfungsi untuk Joomla:
Untuk pembangun yang berpengalaman, saya akan mengatakan bahawa pemalam carian memanjangkan kelas JoomlaComponentFinderAdministratorIndexerAdapter, fail kelas terletak dalam administrator/components/com_finder/src/Indexer/Adapter.php. Nah, kemudian mereka akan memikirkannya sendiri. Selain itu, sebagai contoh, anda boleh mengkaji pemalam carian pintar teras Joomla - untuk artikel, kategori, kenalan, teg, dll. - dalam folder plugin/finder. Saya bekerja pada pemalam carian pintar untuk komponen JoomShopping (komponen e-dagang Joomla) dan SW JProjects (komponen direktori sambungan Joomla anda sendiri dengan pelayan kemas kini), jadi nama kelas dan beberapa nuansa akan dikaitkan dengannya. Saya akan menunjukkan kebanyakannya menggunakan contoh JoomShopping. Penyelesaian kepada isu multibahasa adalah berdasarkan contoh SW JProjects.
Struktur fail pemalam carian pintar untuk Joomshopping tidak berbeza daripada yang biasa:
Struktur fail pemalam searh pintar Joomla 5
Fail provider.php membolehkan anda mendaftarkan pemalam dalam bekas Joomla DI dan membolehkan anda mengakses kaedah pemalam dari luar menggunakan MVCFactory.
<?php /** * @package Joomla.Plugin * @subpackage Finder.Wtjoomshoppingfinder * * @copyright (C) 2023 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ \defined('_JEXEC') or die; use Joomla\CMS\Extension\PluginInterface; use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; use Joomla\Database\DatabaseInterface; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; use Joomla\Event\DispatcherInterface; use Joomla\Plugin\Finder\Wtjoomshoppingfinder\Extension\Wtjoomshoppingfinder; return new class () implements ServiceProviderInterface { /** * Registers the service provider with a DI container. * * @param Container $container The DI container. * * @return void * * @since 4.3.0 */ public function register(Container $container) { $container->set( PluginInterface::class, function (Container $container) { $plugin = new Wtjoomshoppingfinder( $container->get(DispatcherInterface::class), (array) PluginHelper::getPlugin('finder', 'wtjoomshoppingfinder') ); $plugin->setApplication(Factory::getApplication()); // Our plugin uses DatabaseTrait, so the setDatabase() method appeared // If it is not present, then we use only setApplication(). $plugin->setDatabase($container->get(DatabaseInterface::class)); return $plugin; } ); } };
Ini ialah fail yang mengandungi kod kerja utama pemalam anda. Ia sepatutnya terletak dalam folder src/Extension. Dalam kes saya, kelas pemalam JoomlaPluginFinderWtjoomshoppingfinderExtensionWtjoomshoppingfinder berada dalam fail plugins/finder/wtjoomshoppingfinder/src/Extension/Wtjoomshoppingfinder.php. Ruang nama pemalam ialah JoomlaPluginFinderWtjoomshoppingfinderExtension.
Terdapat set sifat kelas minimum dan kaedah yang diperlukan untuk operasi (ia diakses, termasuk oleh kelas Penyesuai induk).
<?php /** * @package Joomla.Plugin * @subpackage Finder.Wtjoomshoppingfinder * * @copyright (C) 2023 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ \defined('_JEXEC') or die; use Joomla\CMS\Extension\PluginInterface; use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; use Joomla\Database\DatabaseInterface; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; use Joomla\Event\DispatcherInterface; use Joomla\Plugin\Finder\Wtjoomshoppingfinder\Extension\Wtjoomshoppingfinder; return new class () implements ServiceProviderInterface { /** * Registers the service provider with a DI container. * * @param Container $container The DI container. * * @return void * * @since 4.3.0 */ public function register(Container $container) { $container->set( PluginInterface::class, function (Container $container) { $plugin = new Wtjoomshoppingfinder( $container->get(DispatcherInterface::class), (array) PluginHelper::getPlugin('finder', 'wtjoomshoppingfinder') ); $plugin->setApplication(Factory::getApplication()); // Our plugin uses DatabaseTrait, so the setDatabase() method appeared // If it is not present, then we use only setApplication(). $plugin->setDatabase($container->get(DatabaseInterface::class)); return $plugin; } ); } };
... dan di sini kita mula menyelami butirannya, kerana kaedah getListQuery() sebenarnya tidak wajib, walaupun pada hakikatnya kedua-dua dokumentasi dan kebanyakan artikel membincangkannya.
Sebarang gambar mengenai topik "skema kompleks" akan dilakukan di sini.
Sungguh menakjubkan berapa kali beberapa maklumat atau idea kadang-kadang melewati kita dalam bulatan sebelum kita perasan dan menyedarinya! Banyak perkara, berada di depan mata selama lebih daripada satu tahun, masih tidak mencapai kesedaran, dan perhatian kita tertumpu kepada mereka hanya selepas pengalaman bertahun-tahun.
Berkaitan dengan Joomla, atas sebab tertentu, penglihatan tidak serta-merta datang bahawa komponennya menganggap beberapa jenis ciri seni bina biasa Joomla (walaupun ini adalah fakta yang jelas). Termasuk pada tahap struktur jadual pangkalan data. Mari lihat beberapa medan jadual kandungan Joomla. Saya akan membuat tempahan bahawa nama lajur tertentu tidak begitu penting kepada kami (anda sentiasa boleh menanyakan SELECT nama AS tajuk), berapa banyak struktur data untuk satu elemen diindeks:
Jika kita membandingkan jadual #__kandungan (artikel Joomla), #__contact_details (komponen kenalan), #__tags (tag Joomla), #__categories (komponen kategori Joomla), maka kita akan menemui hampir semua jenis data yang disenaraikan di mana-mana sahaja.
Jika komponen yang pemalam carian pintar dicipta mengikut "cara Joomla" dan mewarisi seni binanya, maka anda boleh melakukannya dengan kaedah minimum dalam kelas pemalam. Jika pembangun memutuskan untuk tidak mencari cara mudah dan mengikut cara mereka sendiri, maka anda perlu melalui cara yang sukar, mentakrifkan semula hampir semua kaedah kelas Penyesuai.
Kaedah ini dipanggil dalam 3 kes:
Mari kita lihat contoh pelaksanaan dalam pemalam teras Joomla:
<?php /** * @package Joomla.Plugin * @subpackage Finder.Wtjoomshoppingfinder * * @copyright (C) 2023 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ \defined('_JEXEC') or die; use Joomla\CMS\Extension\PluginInterface; use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; use Joomla\Database\DatabaseInterface; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; use Joomla\Event\DispatcherInterface; use Joomla\Plugin\Finder\Wtjoomshoppingfinder\Extension\Wtjoomshoppingfinder; return new class () implements ServiceProviderInterface { /** * Registers the service provider with a DI container. * * @param Container $container The DI container. * * @return void * * @since 4.3.0 */ public function register(Container $container) { $container->set( PluginInterface::class, function (Container $container) { $plugin = new Wtjoomshoppingfinder( $container->get(DispatcherInterface::class), (array) PluginHelper::getPlugin('finder', 'wtjoomshoppingfinder') ); $plugin->setApplication(Factory::getApplication()); // Our plugin uses DatabaseTrait, so the setDatabase() method appeared // If it is not present, then we use only setApplication(). $plugin->setDatabase($container->get(DatabaseInterface::class)); return $plugin; } ); } };
Kaedah getListQuery() mengembalikan objek DatabaseQuery, objek pembina pertanyaan, di mana nama jadual dan medan untuk pemilihan sudah ditentukan. Bekerja dengannya teruskan dalam kaedah yang memanggilnya.
Jika getListQuery() dipanggil daripada getContentCount() dalam objek $query DatabaseQuery, nilai set untuk pilih digantikan dengan COUNT(*).
Jika getListQuery() dipanggil daripada getItem($id), syarat $query->where('a.id = ' . (int) $id) dan hanya elemen tertentu dipilih. Dan di sini kita melihat bahawa kelas Penyesuai induk mengandungi nama jadual dalam pertanyaan sebagai a.*. Ini bermakna kita juga harus menggunakan awalan ini dalam pelaksanaan kaedah getListQuery() kita.
Dalam kes memanggil getListQuery() daripada getItems(), $offset dan $limit ditambahkan pada pertanyaan yang telah kami bina untuk bergerak melalui senarai elemen untuk pengindeksan.
Ringkasan: getListQuery() - mesti mengandungi "bekas kerja" untuk tiga pertanyaan SQL yang berbeza. Dan tiada apa-apa yang amat sukar untuk melaksanakan Joomla di sini. Tetapi, jika perlu, anda boleh melaksanakan 3 kaedah sendiri tanpa membuat getListQuery().
Cara bukan Joomla: Dalam kes JoomShopping, saya mendapati fakta bahawa produk boleh mempunyai beberapa kategori dan mengikut sejarah komponen id kategori (catid) untuk produk itu disimpan dalam jadual berasingan. Pada masa yang sama, selama bertahun-tahun tidak mungkin untuk menentukan kategori utama produk. Setelah menerima kategori produk, pertanyaan telah dihantar ke jadual dengan kategori, di mana hanya hasil pertanyaan pertama diambil, diisih mengikut id kategori lalai - iaitu menaik. Jika kami menukar kategori semasa mengedit produk, maka kategori produk utama ialah kategori yang mempunyai nombor id yang lebih rendah. URL produk adalah berdasarkannya dan produk itu boleh melompat dari satu kategori ke kategori yang lain.
Tetapi, hampir 2 tahun yang lalu, tingkah laku JoomShopping ini telah diperbaiki. Memandangkan komponen itu mempunyai sejarah yang panjang, khalayak yang ramai dan tidak boleh mematahkan keserasian ke belakang sahaja, pembetulan itu dibuat sebagai pilihan. Keupayaan untuk menentukan kategori utama untuk produk mesti didayakan dalam tetapan komponen. Kemudian id_kategori_utama akan diisi dalam jadual dengan produk.
Tetapi fungsi ini dilumpuhkan secara lalai. Dan dalam pemalam carian pintar, kita perlu mendapatkan parameter komponen JoomShopping, lihat jika pilihan untuk menentukan kategori produk utama didayakan (dan ia mungkin didayakan baru-baru ini dan kategori utama untuk sesetengah produk tidak dinyatakan - juga nuansa...) dan menjana pertanyaan SQL untuk menerima produk berdasarkan parameter komponen: sama ada pertanyaan mudah di mana kami menambah medan utama_kategori_id, atau permintaan JOIN untuk mendapatkan id kategori dengan cara lama yang salah.
Segera, nuansa multibahasa muncul dalam permintaan ini. Mengikut cara Joomla, elemen berasingan dicipta untuk setiap bahasa tapak dan perkaitan disediakan di antara mereka. Jadi, untuk bahasa Rusia - satu artikel. Artikel yang sama dalam bahasa Inggeris sedang dibuat secara berasingan. Kemudian kami menyambungkannya antara satu sama lain menggunakan perkaitan bahasa dan apabila menukar bahasa pada bahagian hadapan Joomla, kami akan diubah hala dari satu artikel ke artikel yang lain.
Ini bukan cara ia dilakukan dalam JoomShopping: data untuk semua bahasa disimpan dalam jadual yang sama dengan produk (Ok). Menambah data untuk bahasa lain dilakukan dengan menambahkan lajur dengan akhiran bahasa ini (hmm...). Iaitu, kita tidak mempunyai hanya tajuk atau medan nama dalam pangkalan data. Tetapi terdapat medan name_ru-RU, name_en-GB, dsb.
serpihan struktur jadual produk Joomla JoomShopping
Pada masa yang sama, kita perlu mereka bentuk pertanyaan SQL universal supaya ia boleh diindeks daripada kedua-dua panel pentadbir dan CLI. Pada masa yang sama, memilih bahasa pengindeksan semasa melancarkan CLI menggunakan CRON juga merupakan satu tugas. Saya akui, semasa menulis artikel ini, saya telah menangguhkan penyelesaian sepenuhnya untuk masalah ini buat sementara waktu. Bahasa dipilih menggunakan kaedah getLangTag() kami sendiri, di mana kami sama ada mengambil bahasa utama daripada parameter JoomShopping atau bahasa lalai tapak. Maksudnya, setakat ini penyelesaian ini hanya untuk tapak ekabahasa. Carian dalam bahasa yang berbeza tidak akan berfungsi lagi.
Walau bagaimanapun, 3 bulan kemudian saya menyelesaikan masalah ini, tetapi sudah berada dalam pemalam carian pintar untuk komponen SW JProjects. Saya akan memberitahu anda tentang penyelesaiannya dengan lebih lanjut.
Sementara itu, mari lihat apa yang berlaku untuk JoomShopping
<?php /** * @package Joomla.Plugin * @subpackage Finder.Wtjoomshoppingfinder * * @copyright (C) 2023 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ \defined('_JEXEC') or die; use Joomla\CMS\Extension\PluginInterface; use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; use Joomla\Database\DatabaseInterface; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; use Joomla\Event\DispatcherInterface; use Joomla\Plugin\Finder\Wtjoomshoppingfinder\Extension\Wtjoomshoppingfinder; return new class () implements ServiceProviderInterface { /** * Registers the service provider with a DI container. * * @param Container $container The DI container. * * @return void * * @since 4.3.0 */ public function register(Container $container) { $container->set( PluginInterface::class, function (Container $container) { $plugin = new Wtjoomshoppingfinder( $container->get(DispatcherInterface::class), (array) PluginHelper::getPlugin('finder', 'wtjoomshoppingfinder') ); $plugin->setApplication(Factory::getApplication()); // Our plugin uses DatabaseTrait, so the setDatabase() method appeared // If it is not present, then we use only setApplication(). $plugin->setDatabase($container->get(DatabaseInterface::class)); return $plugin; } ); } };
Kami mencipta kaedah untuk menanyakan pangkalan data daripada Joomla dan belajar banyak tentang cara pemalam carian pintar berfungsi.
Dalam artikel seterusnya, kami akan mencipta kaedah untuk mengindeks kandungan dan melengkapkan penciptaan pemalam. Kami juga akan membiasakan diri dengan cara item yang diindeks disimpan dalam pangkalan data dan memahami mengapa ini penting dan menyelesaikan masalah mengindeks kandungan untuk komponen berbilang bahasa dengan pelaksanaan multibahasa yang tidak standard.
Atas ialah kandungan terperinci Anatomi carian pintar dalam seni Joomla Mencipta pemalam I.. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!