AddMany 是一个 TacoWordPress 扩展,允许您在 WordPress 管理员中分配帖子关系并为自定义帖子创建任意数量的字段。

安装次数: 60

依赖者: 0

建议者: 0

安全: 0

星标: 0

关注者: 2

分支: 1

语言:JavaScript

0.2.5 2018-12-04 22:58 UTC

This package is auto-updated.

Last update: 2024-09-09 14:09:12 UTC


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 updatecomposer 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 的初始分支