x-zolezzi/seo-filter

CakePHP 4 的分页标签过滤插件

安装: 15

依赖: 0

建议者: 0

安全性: 0

星标: 0

关注者: 1

分支: 0

开放问题: 5

类型:cakephp-plugin

dev-main 2023-02-03 15:15 UTC

This package is auto-updated.

Last update: 2024-09-15 14:17:23 UTC


README

CakePHP 4 的分页标签过滤插件

安装

将插件加载到文件 src/Application.php

php bin/cake.php plugin load SeoFilter

使用以下请求创建所需的表

CREATE TABLE IF NOT EXISTS `seofilter_filters` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(255) NOT NULL,
    `slug` varchar(255) NOT NULL,
    `controller` varchar(255) NOT NULL,
    `action` varchar(255) NOT NULL,
    `model` varchar(255) NOT NULL,
    `function_find` varchar(255) NOT NULL,
    `element` varchar(255) NOT NULL,
    `titre` varchar(255) DEFAULT NULL,
    `seo_titre` varchar(255) CHARACTER SET latin1 DEFAULT NULL,
    `seo_description` varchar(370) CHARACTER SET latin1 DEFAULT NULL,
    `is_active` tinyint(1) NOT NULL DEFAULT '1',
    `created` datetime NOT NULL,
    `modified` datetime NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `slug` (`slug`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `seofilter_filters_criteres` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `seofilter_filter_id` int(11) NOT NULL,
    `name` varchar(255) NOT NULL,
    `slug` varchar(255) NOT NULL,
    `model` varchar(255) NOT NULL,
    `colonne` varchar(255) NOT NULL,
    `colonne_label` varchar(255) NOT NULL,
    `function_find_values` varchar(255) NOT NULL,
    `ordre` tinyint(1) unsigned NOT NULL,
    `is_active` tinyint(1) NOT NULL DEFAULT '1',
    `created` datetime NOT NULL,
    `modified` datetime NOT NULL,
    PRIMARY KEY (`id`) USING BTREE,
    UNIQUE KEY `seofilter_filter_id_slug` (`seofilter_filter_id`,`slug`),
    CONSTRAINT `FK_seofilter_filters_criteres_seofilter_filters` FOREIGN KEY (`seofilter_filter_id`) REFERENCES `seofilter_filters` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

CREATE TABLE IF NOT EXISTS `seofilter_filters_orders` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `seofilter_filter_id` int(11) NOT NULL,
    `name` varchar(255) NOT NULL,
    `model` varchar(255) NOT NULL,
    `colonne` varchar(255) NOT NULL,
    `direction` enum('ASC','DESC') NOT NULL,
    `ordre` tinyint(1) unsigned NOT NULL,
    `is_active` tinyint(1) NOT NULL DEFAULT '1',
    `created` datetime NOT NULL,
    `modified` datetime NOT NULL,
    PRIMARY KEY (`id`) USING BTREE,
    KEY `seofilter_filter_id` (`seofilter_filter_id`),
    CONSTRAINT `FK_seofilter_filters_orders_seofilter_filters` FOREIGN KEY (`seofilter_filter_id`) REFERENCES `seofilter_filters` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

CREATE TABLE IF NOT EXISTS `seofilter_filters_urls` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `seofilter_filter_id` int(11) NOT NULL,
    `seo_url` varchar(255) NOT NULL,
    `seo_titre` varchar(255) NOT NULL,
    `seo_description` varchar(255) NOT NULL,
    `description` text,
    `created` datetime NOT NULL,
    `modified` datetime NOT NULL,
    PRIMARY KEY (`id`) USING BTREE,
    UNIQUE KEY `seofilter_filter_id_seo_url` (`seofilter_filter_id`,`seo_url`) USING BTREE,
    CONSTRAINT `FK_seofilter_filters_urls_seofilter_filters` FOREIGN KEY (`seofilter_filter_id`) REFERENCES `seofilter_filters` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

更新文件 config/app.php

[
    // ...
    'SeoFilter' => [
        'config' => [
            'paginate' => [
                'enabled' => true,
                'items_per_page' => 10
            ],
            'countResults' => true, // Si activé, renvoie le nombre de résultats après application du filtre
            'previewResults' => false // Si activé, affiche le nombre de résultats après application d'un critère après ceux-ci
        ]
    ]
]

创建过滤器

首先,需要创建一个插件能够工作的过滤器。访问表 seofilter_filters 并创建您的第一个过滤器。例如

INSERT INTO `seofilter_filters` (`name`, `slug`, `controller`, `action`, `model`, `function_find`, `element`, `titre`, `seo_titre`, `seo_description`, `is_active`, `created`, `modified`) VALUES ('Produits', 'categories', 'Categories', 'details', 'Produits', 'findItemsInParentCategory', 'carte_produit', 'Les produits', 'lorem', 'lorem', 1, NOW(), NOW());

这一行指示插件,在 /categories url 上可以有一个后续的过滤器。列 model 和列 function_find 指示用于获取过滤器数据的调用方法。

// src/Model/Table/ProduitsTable.php
public function findItemsInParentCategory(array $conditions = [], array $order = []): Query{
     // Récupération des données...
     // Penser à intégrer les paramètres $conditions et $order à votre requête.
}

在控制器中

// src/Controller/CategoriesController.php
public function details(){
    $this->loadComponent('SeoFilter.SeoFilter');

    // Récupérer les conditions passées dans l'URL
    $conditionsFilter = $this->SeoFilter->getConditions();

    // Récupération des données avec la méthode définie
    $results = $this->fetchTable('Produits')->findItemsInParentCategory($conditionsFilter);

    $this->set('items', $results->all());
}

在视图中,可以通过插入数据库中的相同元素来显示结果。

// Dans une vue
<?php foreach ($items as $i => $item): ?>
    <?= $this->element('carte_produit', ['item' => $item]) ?>
<?php endforeach; ?>

创建过滤条件

为了能够过滤我们的过滤器上的元素,需要向它提供条件。首先执行以下查询

INSERT INTO `seofilter_filters_criteres` (`seofilter_filter_id`, `name`, `slug`, `model`, `colonne`, `colonne_label`, `function_find_values`, `ordre`, `is_active`, `created`, `modified`) VALUES (1, 'Catégorie', 'categorie', 'Categories', 'slug', 'titre', 'findValuesForFilter', 1, 1, NOW(), NOW());

这一行指示为创建的过滤器添加一个 类别 条件。为了按此条件排序,需要传递一个 categorie- slug,后跟所需的参数。后续的参数将在 Categories 模型的 slug 字段中获取。(这些数据通过在控制器中调用 SeoFilter::getConditions() 返回的 URL 获取)

为了在视图中动态创建这些过滤器,可以在 function_find_values 列中传递模型的方法,在我们的例子中

// src/Model/Table/CategoriesTable.php
public function findValuesForFilter(): Query{
    return $this->find()->where(['Categories.is_active' => true])->order(['Categories.ordre' => 'ASC']);
}
// src/Controller/CategoriesController.php
public function details(){
    // ...

    // Construction des filtres
    $this->SeoFilter->getFilterData();
}

在视图中

foreach ($seo_filter->seofilter_filters_criteres as $seofilter_filters_criteres) {
    echo $seofilter_filters_criteres->name // Nom du critère
    $slug = $seofilter_filters_criteres->slug;
    if (isset($values_for_seofilter_filters_criteres[$seofilter_filters_criteres->id])) {
        $filtre_criteres = $values_for_seofilter_filters_criteres[$seofilter_filters_criteres->id];
        foreach ($filtre_criteres as $filtre_critere) {
            $value_input = $filtre_critere->{$seofilter_filters_criteres->colonne};
            $label_input = $filtre_critere->{$seofilter_filters_criteres->colonne_label};

            $checked = false;
            foreach ($seo_filter_criteres_values as $value) {
                if ($value['slug'] == $slug) {
                    if (!is_array($value['value'])) {
                        $value['value'] = [$value['value']];
                    }
                    foreach ($value['value'] as $value_selected) {
                        if ($value_selected == $value_input) {
                            $checked = true;
                            break;
                        }
                    }
                }
            }
            ?>
            <input <?= ($checked ? 'checked="checked"' : '') ?> class="" name="seofilter_filters_criteres[<?= $slug ?>][]" value="<?= $value_input ?>" type="checkbox" id="seofilter_filters_criteres-<?= $slug ?>-<?= $value_input ?>">
            <label for="seofilter_filters_criteres-<?= $slug ?>-<?= $value_input ?>"><?= $label_input ?></label>
        }
    }
}

Ajax 重新加载

为了简化 Ajax 处理,建议将所有条件和排序放入一个表单中

$(function() {
    $('#filtres input, #filtres select').on('change', function() {
        var data_filter = $('#filtres').serializeArray();
        $.post(
            '<?= $this->Url->build('/seo-filter/render/' . $seo_filter->slug) ?>',
            data_filter,
            function(data) {
                window.history.pushState("", "", data.url);
                $('#js-products-container').html(data.html);
            }
        );
    });
});

待办事项列表

  1. 与 CakePHP 的 Paginator 组件关联的分页系统
  2. 是否在应用过滤器后显示结果数量的括号
  3. 向渲染元素传递多个参数的选项