tacowordpress2 / addmany
AddMany 是一个 TacoWordPress 扩展,允许您在 WordPress 管理员中分配帖子关系并为自定义帖子创建任意数量的字段。
Requires
- php: >= 5.4
- tacowordpress2/frontend-loader: ^1.0
Requires (Dev)
- tacowordpress2/tacowordpress: ^1.0
- tacowordpress2/util: ^1.0
README
简单来说,允许帖子之间的关联。可视化界面使 WordPress 管理员能够分配一对多关系,子帖与没有其他父帖的帖子共享。您还可以允许多对多关系,其中子帖可能有多个父帖,反之亦然。您甚至可以在父帖和子帖之间创建共享字段,这对于可能在不同商店位置改变价格的商品等很重要。更多内容将在后面介绍。
类似于 ACF(高级自定义字段),AddMany 具有创建和重复字段集的能力。主要区别在于,它将控制权交回给开发者,并允许您在需要时编写自定义 MySQL 查询。
*需要 WordPress 4.8 及更高版本。
目录
用例
- 将帖子与其他帖子相关联
- 控制帖子顺序(自定义帖子类型)
- 将可定制的模块或面板分配给布局
- 重复任意数量的字段(类似于 ACF 重复器)
- 根据情况覆盖帖子字段,而不影响原始字段
- 通过允许您在同一页面上创建子帖子来保持上下文
工作原理
相关帖子
幕后发生了什么
为什么我的当前帖子与相关帖子之间有一个“子帖子”?什么是子帖子?
可能需要解释一下“子帖子”是什么。它是一种自定义帖子类型,位于帖子和相关帖子之间。它在 WordPress 管理菜单中是隐藏的,但您实际上在 UI 中添加相关帖子时可以看到它作为一行。
有许多重要原因说明为什么 AddMany 使用子帖子
- 它们允许在帖子和相关帖子之间分配一组唯一的字段
- 可以分配不同的关系类型,如一对一、多对多、一对一等。
- 可以通过 MySQL 查询
- 因为子帖子利用了现有的 WordPress 数据库结构,所以不需要创建额外的表。
要求
没有 TacoWordPress 框架 - 一个自定义帖子类型的 ORM,AddMany 是不可能实现的。这是一个要求。
其他要求
- PHP >= 5.4
- 了解通过 Composer 要求包
- 对 TacoWordpress 的了解
- 面向对象编程
使用 React 和 PHP 构建
安装
根据您将项目的 vendor 目录放在哪里,安装可能或可能不会正常工作。目前正在解决此问题。
在您的项目 composer.json 文件中,在 require 部分添加以下包
"require": {
"tacowordpress/tacowordpress": "dev-master",
"tacowordpress/addmany": "dev-master",
"tacowordpress/util": "dev-master"
}
在终端中运行 composer update 或 composer install
在您的主题功能文件中添加以下内容
// Add this so your project has access to Composer's autoloaded files. // Please replace "{path_to_autolaod}". require_once '{path_to_autoload}/autoload.php'; // Make sure to initialize the core dependency of AddMany, "TacoWordPress". \Taco\Loader::init(); // Initialize AddMany \Taco\AddMany\Loader::init();
示例用法
以下示例中,您应该对TacoWordPress的工作原理有所了解。如果没有,请参阅此处文档: https://github.com/tacowordpress/tacowordpress/wiki。
一对一
// Example configuration for a basic AddMany Field public function getFields() { return [ 'staff_members' => \Taco\AddMany\Factory::create( [ 'first_name' => ['type' => 'text'], 'last_name' => ['type' => 'text'], 'bio' => ['type' => 'textarea'] ], ['limit_range' => [2, 3]] // Enforce a minimum of 2 items, but no more than 3. )->toArray() ]; }
多对多(通过搜索添加)
// Example configuration for an AddMany field with AddBySearch // Adds a search field for querying posts via AJAX public function getFields() { return [ 'employees' => \Taco\AddMany\Factory::createWithAddBySearch('Employee')->toArray() ]; }
两个帖子之间具有唯一公共字段的多对多(如连接表)
在这个例子中,共享字段存在于“产品”的父帖子和子帖子之间。
// Example AddBySearch with shared fields class Store extends \Taco\Post { public function getFields() { return [ 'products' => \Taco\AddMany\Factory::createWithAddBySearch('Product',[ 'price' => ['type' => 'text'], 'tax' => ['type' => 'text'] ])->toArray() ]; } }
因为上述内容将引用外部的“产品”帖子,您可以在保持其原始值的同时扩展其值(“价格”和“税”是一个很好的用例)。这对于创建产品并允许它们在各个商店之间略有不同非常有用。
具有字段变体的多对一
字段变体允许管理员用户选择并添加不同字段组的组合。这允许对布局进行更多定制。一个例子可能是一个具有许多不同模块的侧边栏。每个模块都有一组不同的字段,用于控制内容、外观和感觉。另一个例子(如下所示)可能是一个包含每个人照片和信息网格的员工页面。而不是根据员工类型分隔布局,它们被混合在一起。您可以创建一个包含满足两种员工类型所需所有字段的字段组,但这可能会导致一些字段膨胀。使用字段变体,您可以为董事会成员和普通员工创建一个字段组,同时将它们保持在同一网格中。
// Example AddMany field with field variations – Adds a dropdown for users to select public function getFields() { return [ 'staff_members' => \Taco\AddMany\Factory::create( [ 'board_members' => [ 'first_name' => ['type' => 'text'], 'last_name' => ['type' => 'text'], 'bio' => ['type' => 'textarea'] ], 'general_staff' => [ 'first_name' => ['type' => 'text'], 'last_name' => ['type' => 'text'], 'department' => ['type' => 'select', 'options' => $this->getDepartments()] ], ] )->toArray() ]; }
一对一
// You can simulate a one-to-one relationship by limiting the number of items to 1 class Person extends \Taco\Post { public function getFields() { return [ 'spouse' => \Taco\AddMany\Factory::create( [ 'first_name' => ['type' => 'text'], 'phone' => ['type' => 'text'] ], ['limit_range' => [0, 1]] // Do not allow more than 1 item to be added )->toArray() ]; } }
获取帖子的关系
在模板中,您可以通过访问对象中的字段名来获取相关帖子,例如 $blog_post->related_posts 这将返回一个帖子对象集合。
为了利用上述功能,您必须在您的类中使用AddMany混入。
class Post extends \Taco\Post { use \Taco\AddMany\Mixins; ...
这将允许您做以下事情
// In your template (Example) $blog_post = \Taco\Post\Factory::create($post); ?> <?php foreach($blog_post->related_posts as $rp): ?> <?= $rp->post_title; ?> ... <?php endforeach; ?>
如果对象中不存在相关帖子怎么办?
换句话说,管理员没有手动选择它们。您可以定义一个回退方法。这将通过删除任何逻辑,使您的模板代码更加简洁。
以下示例显示了一个在Post类中定义的方法
public function getFallBackRelatedPosts($key) { global $post; $post_id = (is_object($post) && isset($post->ID)) ? $post->ID : null; if($key === 'related_posts') { return \Taco\Post::getWhere(['posts_per_page' => 3, 'exclude' => $post_id]); // The above actually just gets the 3 most recent posts, excluding the current one. // This is a poor example. Don't be this lazy! } }
排序 - 如果我只是想要这个呢?
您也可以这样做!
public function getFields() { return [ 'videos' => \Taco\AddMany\Factory::createAndGetWithAddBySearch('GalleryItem', null, [ 'uses_ordering' => true ]); ];
通过指定"uses_ordering => true"进行排序,将移除搜索帖子的能力,并添加该帖子类型的所有记录。这使管理员用户能够通过拖放进行排序。但请注意,AddMany将为数据库中的已发布帖子(该帖子类型)创建一个新的子帖子。在某些情况下,您最好使用此功能来对较小的数据子集进行排序。有关如何使用,请参阅 “自定义UI中返回的搜索结果”。
重要:您定义的方法必须命名为"getFallBackRelatedPosts"。如果允许,它可以处理多个字段。只需创建一个switch语句或某种逻辑来检查键,然后返回适当的帖子。
获取被覆盖的引用帖子的原始值
使用AddMany,您可以通过AddBySearch引用的帖子覆盖其值。如果您有某种模板或产品需要替换其值而不必重新创建它,这将非常有用。
假设有一系列商店,它们都携带相同的产品/,但价格因地点而异。以下代码将允许这样做
class Store extends \Taco\Post { use \Taco\AddMany\Mixins; public function getFields() { return [ 'products' => \Taco\AddMany\Factory::createWithAddBySearch('Product', [ 'price' => ['type' => 'text'] ])->toArray() ]; } ...
管理界面将允许您找到并添加产品到列表中。此列表将包含带有“价格”额外字段的产品。在字段中键入值将覆盖它,但不会替换原始值。
为了更好地理解这个概念,让我们创建显示一些基本产品信息的模板代码。
/* Single Store - single-store.php */ <?php $store = Store::find($post->ID); // load the store and iterate through the products foreach($store->products as $product): ?> Product title: <?= $product->getTheTitle(); ?><br> product price: $<?= $product->get('price'); ?><br> Original price: $<?= $product->original_fields->price; ?> <br> Savings: $<?= $product->original_fields->price - $product->get('price'); ?><br><br> <?php endforeach; ?>
通过访问 "original_fields" 属性,您将获取原始值,同时保留新值。$product->original_fields->price;
这也有助于显示价格降低后的产品节省。
自定义UI中搜索结果的返回方式
如果您正在使用 AddMany 的 AddbySearch 功能来查询和分配相关帖子,您可能需要进一步缩小结果。假设您想返回具有 "employee" 术语的自定义帖子类型 "person",但可供选择的人有数百个。您可以创建自己的方法来使结果更明确。默认情况下,AddMany 核心方法看起来像这样
public static function getPairsWithKeyWords($keywords, $post_type_class_name, $custom_args=[]) { $post_type = Str::machine(Str::camelToHuman($post_type_class_name), '-'); $query = new \WP_Query([ 'post_type' => $post_type, 's' => $keywords, 'posts_per_page' => -1 ]); $results = []; foreach ($query->posts as $post) { $results[$post->ID] = $post->post_title; } return $results; }
创建自己的方法
我们将使用上面的例子,其中UI需要返回具有 "person-type" (缩写)分类的 "employee" 术语的自定义帖子类型 "person" 的帖子。
public static function getPeopleByPersonTypeTerm($keywords, $post_type_class_name, $custom_args=['terms' => 'employee') { $post_type = Str::machine(Str::camelToHuman($post_type_class_name), '-'); $query = new \WP_Query([ 'post_type' => $post_type, 's' => $keywords, 'tax_query' => [ [ 'taxonomy' => 'person-type', 'field' => 'slug', 'terms' => $custom_args['terms'] ], ), 'posts_per_page' => -1 ]); $results = []; foreach ($query->posts as $post) { $results[$post->ID] = $post->post_title; } return $results; }
注意:保留文本查询("s" 属性)在 WP_Query 中很重要,这样用户管理员仍然可以用关键词搜索。此外,当返回数组时,键必须是帖子 ID,而值 "应该" 是帖子标题,但这并非绝对必要。
接下来,我们需要在 "getFields()" 中分配此方法。
public function getFields() { return [ 'products' => \Taco\AddMany\Factory::createWithAddBySearch('Person::getPeopleByPersonTypeTerm', null, [ 'args' => ['terms' => 'employee'] ]) ]; }
在上面的代码中,“Person”是帖子类型类名,“getEmployees”是我们刚刚创建的新方法。
UI - 定义折叠时显示的内容
通过拖放重新排序可能会变得繁琐,因为行的高度增加并占据了大部分屏幕。提供了一个折叠按钮来减小这些项的高度。当行的高度变短时,这就会产生一个问题,即要显示什么。默认情况下,AddMany 会显示来自行的截断字段值集合,以便管理员用户更容易识别它们。您也可以通过在数组的选项部分添加字段名作为 "show_on_collapsed" 的键来通过代码指定显示哪个字段值。
以下是一个例子。
public function getFields() { return [ 'right_column_images' => \Taco\AddMany\Factory::create([ 'image' => ['type' => 'image'] ], ['show_on_collapsed' => 'image'])->toArray() ]; )'
便捷方法
AddMany 的 Factory 类提供了一些便捷方法,可以使您的代码更加简洁。
基本的 AddMany \Taco\AddMany\createAndGet() 将返回数组,无需调用 ->toArray()
带有 AddBySearch 的 AddMany
\Taco\AddMany\createAndGetWithAddBySearch() 也会返回一个数组
贡献(即将推出)
变更日志
v0.2.4
- 添加了更好的子帖子排序方式
v0.2.3
- 添加了传递自定义方法参数的功能
v0.2.2
- 正确保存修订版本的 JSON 值
v0.2.1
- 使子帖子预览和修订版本正常工作
v0.2
- 向 WYSIWYG 添加视觉和文本选项卡
v0.1
- addmany 的初始分支

