ホームページ > バックエンド開発 > PHPチュートリアル > Joomla アートにおけるスマート検索の構造 プラグインの作成 I.

Joomla アートにおけるスマート検索の構造 プラグインの作成 I.

Barbara Streisand
リリース: 2024-12-04 22:29:11
オリジナル
363 人が閲覧しました

前の記事では、Joomla スマート検索コンポーネントの機能について説明し、CRON を使用したスケジュールされたインデックス作成のパラメーターと構成について説明しました。独自のプラグインのコードの作成を始めましょう。

リソースのリスト

技術的な部分を始める前に、主要なトピックに直接対処するいくつかの記事について言及します。 Joomla 4 / Joomla 5 の最新アーキテクチャ用のプラグインの作成および/または更新を一般的にカバーする記事と同様に、次に、読者がそれらを読んで、機能するプラグインを作成する方法について大体のアイデアを持っていると仮定します。 Joomla の場合:

  • スマート検索プラグインの作成 - Joomla の公式ドキュメント。これは Joomla 3 用ですが、ほとんどの規定は Joomla 4 / Joomla 5 にも当てはまります
  • 「スマート検索プラグインの開発」は、2012 年の Joomla Community Magazine の記事です。
  • Joomla! の開発について説明した、Nicholas Dionysopoulos 著の書籍『Joomla Extensions Development』 Joomla バージョン 4 および 5 の拡張機能。
  • 新しいドキュメント ポータル manual.joomla.org のデータベース セクション - Joomla 4 および Joomla 5 用。 ## 技術的な部分です。 Joomla 5 スマート検索プラグインの開発 スマート検索コンポーネントは、データ プロバイダー プラグインと連携して動作します。その主なタスクは、データを選択してインデックス付けのためにコンポーネントに渡すことです。しかし、時間の経過とともに、インデックスの再作成タスクもプラグインの責任範囲になりました。この記事では、管理パネルからコンテンツのインデックス作成を手動で実行すると仮定します。 CLI からの作業は視覚的に異なりますが、本質は同じです。

経験豊富な開発者のために、検索プラグインは JoomlaComponentFinderAdministratorIndexerAdapter クラスを拡張するものであると説明します。クラス ファイルは administrator/components/com_finder/src/Indexer/Adapter.php にあります。そうすれば、彼らは自分でそれを理解するでしょう。また、サンプルとして、plugins/finder フォルダー内の記事、カテゴリ、連絡先、タグなどの Joomla コア スマート検索プラグインを調べることができます。私は JoomShopping (Joomla e-commerce コンポーネント) および SW JProjects (更新サーバーを備えた独自の Joomla 拡張機能ディレクトリ コンポーネント) コンポーネントのスマート検索プラグインに取り組んだため、クラス名といくつかのニュアンスはそれらに関連付けられています。 JoomShopping の例を使用してそのほとんどを説明します。多言語使用の問題の解決策は、SW JProjects の例に基づいています。

スマート検索プラグインのファイル構造

Joomshopping のスマート検索プラグインのファイル構造は、一般的なものと変わりません。

The anatomy of smart search in Joomla art Creating a plugin I.
Joomla 5 スマート検索プラグインのファイル構造

ファイルサービス/provider.php

ファイル provider.php を使用すると、Joomla DI コンテナーにプラグインを登録でき、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;
            }
        );
    }
};
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

プラグインクラスファイル

これは、プラグインの主要な動作コードが含まれるファイルです。これは src/Extension フォルダーにあります。私の場合、プラグイン クラス JoomlaPluginFinderWtjoomshoppingfinderExtensionWtjoomshoppingfinder はファイル plugins/finder/wtjoomshoppingfinder/src/Extension/Wtjoomshoppingfinder.php にあります。プラグインの名前空間は JoomlaPluginFinderWtjoomshoppingfinderExtension.

です。

操作に必要なクラス プロパティとメソッドの最小限のセットがあります (親のアダプター クラスを含めてアクセスされます)。

クラスに最低限必要なプロパティ

  • $extension - コンテンツのタイプを定義するコンポーネントの名前です。たとえば、com_content。私の場合、これは com_jshopping です。
  • $context - プラグインの一意の識別子であり、プラグインがアクセスされるインデックス作成のコンテキストを設定します。実際、これはプラグイン クラス (要素) の名前です。私たちの場合は、Wtjoomshoppingfinder.
  • $layout - 検索結果要素の出力レイアウトの名前です。このレイアウトは検索結果を表示するときに使用されます。たとえば、$layout パラメータがarticleに設定されている場合、このタイプの検索結果を表示する必要がある場合、デフォルトの表示モードは default_article.php という名前のレイアウト ファイルを検索します。そのようなファイルが見つからない場合は、default_result.php という名前のレイアウト ファイルが代わりに使用されます。 HTML レイアウトを含む出力レイアウトは、components/com_finder/tmpl/search にあります。ただし、レイアウトは HTML テンプレート フォルダー templates/YOUR_TEMPLATE/html/com_finder/search にオーバーライドとして配置する必要があります。私の場合、レイアウト製品に名前を付け、ファイルの名前は default_product.php です。 The anatomy of smart search in Joomla art Creating a plugin I.
  • $table - データを取得するためにアクセスするデータベース内のテーブルの名前です (例: #__content)。私の場合、JoomShopping 製品が含まれるメイン テーブルは #__jshopping_products と呼ばれます。
  • $state_field - インデックス付き要素が公開されるかどうかを決定するデータベース テーブル内のフィールドの名前です。デフォルトでは、このフィールドは状態と呼ばれます。ただし、JoomShopping の場合、このフィールドは product_publish と呼ばれます。
<?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;
            }
        );
    }
};
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

クラスに最低限必要なメソッド

  • setup() : bool - プラグインの事前設定、ライブラリの接続などのためのメソッドです。このメソッドは、再インデックス作成中 (reindex() メソッド)、onBeforeIndex イベントで呼び出されます。メソッドは true を返す必要があります。そうでない場合、インデックス作成は中断されます。
  • Index() : void - 自身のインデックス作成を開始するメソッドです。これは、生の SQL クエリ データから目的の構造のオブジェクトを収集し、インデックス作成のために JoomlaComponentFinderAdministratorIndexerIndexer クラスに渡します。このメソッドはインデックス付き要素ごとに実行されます。メソッドの引数は $item です。これはデータベースへのクエリの結果であり、JoomlaComponentFinderAdministratorIndexerResult クラスでフォーマットされます。
  • getListQuery() : JoomlaDatabaseDatabaseQuery - インデックス付きアイテムのリストを取得するメソッドです…

...ここで、詳細を調べ始めます。ドキュメントとほとんどの記事の両方で getListQuery() メソッドについて説明されているにもかかわらず、getListQuery() メソッドは実際には必須ではないためです。

The anatomy of smart search in Joomla art Creating a plugin I.
「複雑なスキーム」に関するあらゆる写真をここに投稿できます。

詳細を詳しく見てみましょう。インデックス付き要素のデータ構造。

私たちが気づく前に、情報やアイデアが何度もグルグルと私たちの前を通り過ぎてしまうのは驚くべきことです。多くの物事は、1 年以上私たちの目の前にあるにもかかわらず、まだ認識されておらず、私たちの注意がそれらに集中するのは、何年もの経験を経てからです。

Joomla に関連して、何らかの理由で、そのコンポーネントが Joomla に特徴的なある種の共通アーキテクチャを想定しているというビジョンがすぐには浮かびません (これは明白な事実ですが)。データベースのテーブル構造のレベルにも含まれます。 Joomla コンテンツ テーブルのいくつかのフィールドを見てみましょう。特定の列名は私たちにとってそれほど重要ではないことを留保します (いつでもタイトルとして SELECT 名をクエリできます)。1 つのインデックス付き要素のデータ構造はどれくらいですか:

  • id - 自動インクリメント
  • asset_id - #__assets テーブル内のエントリの ID。ここには、記事、製品、メニュー、モジュール、プラグインなど、サイトの各要素に対するグループとユーザーのアクセス権が保存されます。 Joomla はアクセス制御リスト (ACL) パターンを使用します。
  • title - 要素タイトル
  • language - 要素言語
  • introtext - 要素の紹介テキストまたは目に見える簡単な説明
  • fulltext - アイテムの全文、製品の完全な説明など
  • state - 公開ステータス (アイテムが公開されているかどうか) を担当する論理フラグ。
  • catid - 項目カテゴリの ID。 Joomla には、他の CMS のように「サイト ページ」だけがありません。いくつかのカテゴリに属さなければならないコンテンツ エンティティ (記事、連絡先、製品など) があります。
  • created- アイテムが作成された日付。
  • access - アクセス権グループID (不正サイトユーザー(ゲスト)、全員、登録済みなど)
  • metakey - 要素のメタ キーワード。はい、2009 年以降、Google では使用されていません。しかし、Joomla では、このフィールドは指定されたキーワードを使用して実際に類似した記事を検索するために類似記事モジュールで使用されるため、歴史的に残っています。
  • metadesc - 要素のメタ説明
  • public_up およびpublish_down - 要素の公開および非公開の開始日。これはオプションのようなものですが、多くのコンポーネントに含まれています。

テーブル #__content (Joomla 記事)、#__contact_details (連絡先コンポーネント)、#__tags (Joomla タグ)、#__categories (Joomla カテゴリ コンポーネント) を比較すると、リストされているほぼすべてのデータ型がどこでも見つかります。

スマート検索プラグインが作成されるコンポーネントが「Joomla 方式」に従っており、そのアーキテクチャを継承している場合は、プラグイン クラス内の最小限のメソッドで実行できます。開発者が簡単な方法を探さずに独自の道を進むことに決めた場合、Adapter クラスのほぼすべてのメソッドを再定義するという困難な方法を選択する必要があります。

getListQuery() メソッド

このメソッドは 3 つの場合に呼び出されます:

  1. Adapter クラスの getContentCount() メソッドは、インデックスされたアイテムの数 (記事の合計数、商品の合計数など) を取得します。 The anatomy of smart search in Joomla art Creating a plugin I. Joomla スマート検索インデックス作成プロセス デバッグ モードでインデックス付けされたアイテムの数を確認できます。
  2. Adapter クラスの getItem($id) メソッドは、ID によってインデックス付きの特定の要素を取得します。 getItem() メソッドは、再インデックス作成中に、reindex($id) メソッドで呼び出されます。
  3. AdapterクラスのgetItems($offset, $limit, $query = null)メソッドは、インデックス付き要素のリストを取得するメソッドです。オフセットと制限はコンポーネント設定、つまり「バンドル」に含めるインデックス付き要素の数に基づいて設定されます。 The anatomy of smart search in Joomla art Creating a plugin I. Joomla 5 スマート検索設定インデクサーのバッチ サイズ

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;
            }
        );
    }
};
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

getListQuery() メソッドは、クエリ コンストラクターのオブジェクトである DatabaseQuery オブジェクトを返します。このオブジェクトには、テーブルの名前と選択対象のフィールドがすでに指定されています。これを呼び出すメソッドでの作業が続行されます。

DatabaseQuery $query オブジェクトの getContentCount() から getListQuery() が呼び出された場合、select の設定値は COUNT(*) に置き換えられます。

getItem($id) から getListQuery() が呼び出された場合、条件 $query->where('a.id = ' . (int) $id) および特定の要素のみが選択されます。そして、すでにここで、親のアダプター クラスにクエリ内のテーブル名が a.* として含まれていることがわかります。これは、getListQuery() メソッドの実装でもこれらのプレフィックスを使用する必要があることを意味します。

getItems() から getListQuery() を呼び出す場合、インデックス付けのための要素のリスト内を移動するために、作成したクエリに $offset と $limit が追加されます。
概要: getListQuery() - 3 つの異なる SQL クエリの「ワークピース」が含まれている必要があります。 そして、ここでの Joomla の実装に関して特に難しいことは何もありません。ただし、必要に応じて、getListQuery() を作成せずに 3 つのメソッドを自分で実装することもできます。

Joomla 以外の方法: JoomShopping の場合、製品には複数のカテゴリを含めることができ、歴史的に製品のカテゴリ ID (catid) コンポーネントは別のテーブルに保存されているという事実に遭遇しました。同時に、長年にわたり、製品の主要カテゴリを指定することはできませんでした。製品カテゴリを受信すると、カテゴリを含むテーブルにクエリが送信され、最初のクエリ結果だけが取得され、デフォルトのカテゴリ ID (つまり昇順) で並べ替えられました。製品の編集時にカテゴリを変更した場合、メインの製品カテゴリは ID 番号が小さいカテゴリになります。製品の URL はそれに基づいており、製品はあるカテゴリから別のカテゴリにジャンプできました。

しかし、ほぼ 2 年前、この JoomShopping の動作は修正されました。このコンポーネントには長い歴史があり、利用者が多く、下位互換性を単に破ることはできないため、修正はオプションになりました。製品のメイン カテゴリを指定する機能は、コンポーネント設定で有効にする必要があります。次に、main_category_id が製品とともにテーブルに入力されます。

ただし、この機能はデフォルトで無効になっています。 そして、スマート検索プラグインでは、JoomShopping コンポーネントのパラメータを取得する必要があります。メインの製品カテゴリを指定するオプションが有効になっているかどうかを確認します (そして、最近有効になっている可能性があり、一部の製品のメイン カテゴリが指定されていない - これもニュアンス...) を作成し、コンポーネント パラメータに基づいて製品を受け取るための SQL クエリを生成します。main_category_id フィールドを追加する単純なクエリのいずれかです。 、 または古い間違った方法でカテゴリ ID を取得するための JOIN リクエスト。

このリクエストではすぐに、多言語使用のニュアンスが前面に出てきます。 Joomla の方法によれば、サイトの言語ごとに個別の要素が作成され、それらの間に関連付けが設定されます。それで、ロシア語については、1つの記事です。同じ英語記事を別途作成中です。次に、言語の関連付けを使用してそれらを相互に接続し、Joomla フロントエンドで言語を切り替えると、ある記事から別の記事にリダイレクトされます。

これは JoomShopping では行われません。 すべての言語のデータは商品と同じテーブルに保存されます (OK)。他の言語のデータを追加するには、これらの言語の接尾辞 (うーん...) が付いている列を追加します。つまり、データベースにはタイトルや名前のフィールドだけが存在するわけではありません。ただし、name_ru-RU、name_en-GB などのフィールドがあります。
The anatomy of smart search in Joomla art Creating a plugin I.
Joomla JoomShopping 製品テーブル構造フラグメント
同時に、管理パネルと CLI の両方からインデックスを作成できるように、ユニバーサル SQL クエリを設計する必要があります。同時に、CRON を使用して CLI を起動するときにインデックス言語を選択することも作業です。この記事を書いている時点では、当分の間、この問題の本格的な解決策を延期していたことを認めます。言語は独自の getLangTag() メソッドを使用して選択されます。このメソッドでは、JoomShopping パラメータからメイン言語を取得するか、サイトのデフォルト言語を取得します。つまり、これまでのところ、このソリューションは単一言語サイトのみを対象としています。別の言語での検索はまだ機能しません。

しかし、3 か月後、私はこの問題を解決しました。しかし、すでに SW JProjects コンポーネントのスマート検索プラグインに含まれていました。解決策についてはまた改めてお伝えします。

それまでの間、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;
            }
        );
    }
};
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

チェックポイント

私たちは Joomla からデータベースにクエリを実行するメソッドを作成し、スマート検索プラグインがどのように機能するかについて多くのことを学びました。

次の記事では、コンテンツのインデックスを作成するメソッドを作成し、プラグインの作成を完了します。また、インデックス付きアイテムがデータベースにどのように保存されるのかを知り、これが重要である理由を理解し、多言語の非標準実装による多言語コンポーネントのコンテンツのインデックス付けの問題を解決します。

Joomla コミュニティ リソース

  • https://joomla.org/
  • Joomla コミュニティ マガジンのこの記事
  • Mattermost の Joomla コミュニティ チャット (続きを読む)

以上がJoomla アートにおけるスマート検索の構造 プラグインの作成 I.の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート