anthonybudd / wp_model

该软件包最新版本(v1.1.4)没有可用的许可信息。

v1.1.4 2017-06-26 18:16 UTC

This package is auto-updated.

Last update: 2024-09-09 13:37:50 UTC


README

一个用于创建WordPress文章的主动记录模型的简单类。

WP_Model是专为WordPress设计的伪ORM,旨在提供一种使用简单OOP语法的更好方法来处理帖子。WP_Model已被专门设计,尽可能容易地供前端开发者(辅助方法、分类法)以及具备PHP入门级知识的开发者使用,但它足够强大(虚拟属性、关系、事件),对于希望制作复杂基于WordPress的项目后端开发者来说,实际上是有用的。

介绍:Medium文章

高级功能:Medium文章

Class Product extends WP_Model
{
    public $postType = 'product';
    public $attributes = [
        'color',
        'weight'
    ];
}

Product::register();

$book = new Product;
$book->title = 'WordPress for dummies';
$book->color = 'Yellow';
$book->weight = 100;
$book->save();

安装

使用composer要求WP_Model

$ composer require anthonybudd/WP_Model

或者

下载WP_Model类并在functions.php文件顶部引入。不推荐这样做。

设置

然后您需要创建一个扩展WP_Model的类。此类需要公共属性$postType和$attributes,这是一个字符串数组。

Class Product extends WP_Model
{
    public $postType = 'product';

    public $attributes = [
        'color',
        'weight'
    ];
    
    public $prefix = 'wp_model_'; // Optional
}

如果您需要在您的post_meta表中添加模型数据的表前缀,请添加一个公共属性$prefix。这将添加到post meta中,因此属性'color'将使用meta_key 'wp_model_color'在数据库中保存。

注册

在您能够创建帖子之前,您需要注册帖子类型。您可以通过在functions.php文件中调用静态方法register()来完成此操作。

Product::register();

Product::register([
    'singular_name' => 'Product'
]);

可选地,您还可以向此方法提供一个参数数组,此数组将直接发送到Wordpress的register_post_type()函数的第二个参数。

创建和保存

您可以使用以下方法创建模型。

$product = new Product();
$product->color = 'white';
$product->weight = 300;
$product->title = 'the post title';
$product->content = 'the post content';
$product->save();

$product = new Product([
    'color' => 'blue',
    'weight' => '250'
]);
$product->save();

$product = Product::insert([
    'color' => 'blue',
    'weight' => '250'
]);

检索模型

find()

如果数据库中存在具有指定ID的帖子,find()将返回一个实例化的模型。如果找不到帖子,它将返回NULL。

$product = Product::find(15);

findOrFail()

如果数据库中找不到正确类型的帖子,findOrFail()方法将抛出异常。

try {
    $product = Product::findorFail(15);
} catch (Exception $e) {
    echo "Product not found.";
}

all()

all()将返回所有帖子。请谨慎使用。

$allProducts = Product::all();

in()

要按ID查找多个帖子,可以使用in()方法。

$firstProducts = Product::in([1, 2, 3, 4]);

链式查找器

如果您更喜欢使用链式OOP语法查找模型,query()方法是对where()方法的包装。每个链式查找器方法meta()和tax可以接受不同数量的参数。您必须调用execute()方法来执行查询。

meta()

Product::query()
    ->meta('meta_key', 'meta_value')
    ->meta('meta_key', 'compare', 'meta_value')
    ->meta('meta_key', 'compare', 'meta_value', 'type')

tax()

Product::query()
    ->tax('taxonomy', 'terms')
    ->tax('taxonomy', 'field', 'terms')
    ->tax('taxonomy', 'field', 'operator', 'terms')

params()

用于WP_Query的附加参数数组。

Product::query()
    ->params(['orderby' => 'meta_value', 'order' => 'ASC])

示例

$products = Product::query()
    ->meta('color', 'blue')
    ->execute();
$products = Product::query()
    ->meta('color', 'red')
    ->meta('weight', '>', 2000, 'NUMERIC')
    ->tax('type', 'small')
    ->tax('category', ['office', 'home'])
    ->tax('quality', 'slug', 'high')
    ->tax('county', 'term_id', 'NOT IN', [1, 5])
    ->params(['orderby' => 'meta_value menu_order title'])
    ->execute();

删除

delete()

delete()将帖子移动到回收站。

$product = Product::find(15);
$product->delete();

restore()

restore()将帖子从回收站中取出并恢复模型。您不能恢复已硬删除的模型。

$product = Product::restore(15);

hardDelete()

hardDelete()将删除帖子并将所有元数据(在数据库中和在对象中)设置为NULL。

$product->hardDelete();

辅助属性

$new属性将返回true,如果模型尚未保存到数据库中。

$dirty属性将返回true,如果模型中的数据与数据库中当前存储的数据不同。

$product = new Product;
$product->new; // Returns (bool) true

$product = Product::find(15);
$product->new; // Returns (bool) false

$product->color = 'red';
$product->dirty; // Returns (bool) true
$product->save();
$product->dirty; // Returns (bool) false

$product->title; // Returns the post's title

$product->content; // Returns the post's content

$product->the_content; // Returns the post's content via the 'the_content' filter

辅助方法

Product::single(); // Returns the current model if on a single page or in the loop

Product::exists(15); // Returns (bool) true or false

Product::mostRecent($limit = 1); // Returns the most recent post

Product::mostRecent(10); // Returns the most recent 10 posts [Product, Product, Product, Product]

Product::count($postStatus = 'publish'); // Efficient way to get the number of models (Don't use count(WP_Model::all()))

$product->postDate($format = 'd-m-Y'); // Returns the post date based on the format supplied

$product->get($attribute, $default) // Get attribute from the model

$product->set($attribute, $value) // Set attribute of the model

$product->post() // Returns the WP_Post object (This will be the post at load, any updates to the post (title, content, etc) will not be reflected)

$product->permalink() // Returns the post permalink

$product->hasFeaturedImage() // Returns TRUE if a featured image has been set or FALSE if not

$product->featuredImage($defaultURL) // Returns the featured image URL

$product->toArray() // Returns an array representation of the model

Product::asList() // Returns array of posts keyed by the post's ID
[
    15 => Product,
    16 => Product,
    17 => Product
]

// You can also specify the value of each element in the array to be meta from the model.
Product::asList('post_title')
[
    15 => "Product 1",
    16 => "Product 2",
    17 => "Product 3"
]

虚拟属性

如果您想为模型添加虚拟属性,可以通过添加一个名为虚拟属性名称前缀为'_get'的方法来实现。

Class Product extends WP_Model
{
    ...

    public $virtual = [
        'humanWeight'
    ];

    public function _getHumanWeight()
    {  
        return $this->weight . 'Kg';
    }
}

$product = Product::find(15);
echo $product->humanWeight;

默认属性

要在您的模型中设置属性的默认值,请使用 $default 属性。此数组的键将是您希望设置默认值的属性,值将是默认值。

Class Product extends WP_Model
{
    ...

    public $default = [
        'color' => 'black'
    ];
}

$product = new Product;
echo $product->color; // black

过滤属性

如果您需要在返回之前解析一个属性,可以使用过滤方法。您必须将属性名称添加到名为 $filter 的数组中,并创建一个以‘_filter’开头的方法,此方法必须接受一个参数,这将是属性值。

或者,如果您想通过现有的函数(如 intval()、number_format()、your_function() 等)发送值,可以通过使用关联数组语法命名所需的函数作为值来完成此操作。注意:正如示例代码所示,您可以同时使用两种过滤方法。

当您将一个对象(该对象是 WP_Model 的实例)的属性值设置为对象,或者当您保存一个 WP_Model 数组时,都会导致模型(或多个模型)被单独保存。父模型将只存储子模型的 ID(或 ID 数组)。要将这些属性值作为实例化的模型检索,请将过滤属性值设置为所需模型的类。

Class Product extends WP_Model
{
    ...

    public $filter = [
        'weight'
        'stock' => 'number_format',
        'seller' => Seller::class,
        'related' => Product::class,
    ];

    public function _filterWeight($value){
        return intval($value);
    }
}

$product = Product::insert([
    'weight' => 250,
    'stock' => '3450',
    'seller' => Seller::find(3),
    'related' => [
        new Product,
        new Product,
        new Product,
    ]
]);

$product->weight;  // (int) 250
$product->stock;   // (string) 3,450
$product->seller;  // (object) Seller
$product->related; // (array) [Product, Product, Product]

注意:WP_Model 会根据需要动态加载子模型。如果您在没有显式请求子模型的情况下转储模型(例如,$product->seller),则父模型将只存储子模型的 ID。

序列化

如果您想 JSON 编码一个模型并保留虚拟属性,可以通过将 $serialize 属性添加到模型中来实现。相反,如果您想隐藏一个属性,可以通过将 $protected 添加到模型中来实现。

序列化将触发序列化事件。

Class Product extends WP_Model
{
    ...

    public $serialize = [
        'humanWeight',
    ];

    public $protected = [
        'weight',
    ];

    public function _getHumanWeight()
    {  
        return $this->weight . 'Kg';
    }
}

$product = Product::find(15);
echo json_encode($product);

结果

{
    "ID":           15,
    "title":        "The post title",
    "content":      "The post content",
    "color":        "blue",
    "HumanWeight":  "250Kg"
}

高级查找

Where(String $metaKey, String $metaValue) Where(Array $WPQuery)

where() 是 WP_Query 的简单接口,该方法可以接受两个字符串参数 meta_value 和 meta_key。

对于复杂查询,将单个数组作为参数提供给方法。该数组将被自动分解为分类查询和元查询,然后执行 WP_Query,并将返回一个模型数组。

$greenProducts = Product::where('color', 'green');

$otherProducts = Product::where([
    [
        'key' => 'color',
        'value' => 'green',
        'compare' => '!='
    ],[
        'taxonomy' => 'category',
        'terms' => ['home', 'garden']
    ]
]);

finder()

finder() 方法允许您创建自定义查找方法,这是在您的模型类中包含常用 WP_Query 的最佳方法。要创建自定义查找,首先在您的模型中创建一个名为您的查找名称的方法,并以前缀 '_finder' 开头,此方法必须返回一个数组。该数组将直接传递给 WP_Query 的构造函数。finder() 方法的返回值将是 WP_Query 的结果。您可以通过向 finder() 方法的第二个参数提供一个数组来提供额外的查找方法参数,如下所示('heavyWithArgs')。

如果您想后处理自定义查找的结果,可以添加一个 '_postFinder' 方法。此方法必须接受一个参数,该参数将是找到的帖子数组。

Class Product extends WP_Model
{
    ...

    public function _finderHeavy($args)
    {  
        return [
            'meta_query' => [
                [
                    'key' => 'weight',
                    'compare' => '>',
                    'type' => 'NUMERIC',
                    'value' => '1000'
                ]
            ]
        ];
    }

    // Optional
    public function _postFinderHeavy($results)
    {  
        return array_map(function($model){
            if($model->color == 'green'){
                return $model->color;
            }
        }, $results);
    }


    // Finder with optional args
    public function _finderHeavyWithArgs($args)
    {  
        return [
            'paged'      => $args['page'], // 3
            'meta_query' => [
                [
                    'key' => 'weight',
                    'compare' => '>',
                    'type' => 'NUMERIC',
                    'value' => '1000'
                ]
            ]
        ];
    }
}

$heavyProducts = Product::finder('heavy');

// Finder with optional args
$heavyProducts = Product::finder('heavyWithArgs', ['page' => 3]); 

事件

WP_Model 有一个事件系统,这是挂钩 WP_Model 核心功能的最有效方式。所有带有 -ing 后缀的事件都会在方法被调用时立即触发。所有带有 -ed 后缀的事件都将在方法的最后触发。以下是一个可用事件的列表。所有事件都将提供触发事件的模型。

您还可以从 WordPress 的管理部分触发保存、插入和删除事件。

  • booting
  • booted
  • saving
  • inserting
  • inserted
  • saved
  • deleting
  • deleted
  • hardDeleting
  • hardDeleted
  • serializing

在保存新模型时,保存、插入、插入和保存事件(按此顺序)都会被触发。

Class Product extends WP_Model
{
    ...
    
    public function saving(){
        echo "The save method has been called, but nothing has been written to the database yet.";
    }
    
    public function saved($model){
        echo "The save method has completed and the post and it's meta data have been updated in the database.";
        echo "The Model's ID is". $model->ID;
    }
}

分类法

如果您希望将任何分类法加载到模型中,请将可选的公共属性 $taxonomies(分类法 slugs 的数组)添加到类中。

Class Product extends WP_Model
{
    ...
    public $taxonomies = [
        'category',
    ];
}

您可以在实例化模型时通过数组提供它来设置模型的分类法,这个数组可以是术语缩略名或术语_id的组合。可以通过获取以分类法名称命名的属性来访问模型的术语。

$product = Product::insert([
    'title' => 'product',
    'color' => 'blue',
    'weight' => '250',
    'category' => ['home', 3]
]);

$product->category; // ['Home', 'Office'];

如果您想直接访问分类法对象,可以使用getTaxonomy()方法。第一个参数是分类法名称,第二个参数是可选的,表示要从术语对象中提取的属性。如果不提供第二个参数,将返回WP_Term对象。

$product->getTaxonomy('category'); // [WP_Term, WP_Term];
$product->getTaxonomy('category', 'term_id'); // [2, 3];
$product->getTaxonomy('category', 'name'); // ['Home', 'Office'];

您可以使用addTaxonomy()方法添加分类法。第一个参数是分类法名称,第二个参数可以是term_id(必须是整数)或term slug(必须作为字符串提供)。如果找不到术语,该方法将返回FALSE。

如果您想向模型添加多个术语,可以使用addTaxonomies()方法。第二个参数必须是一个术语缩略名和/或term_ids的数组。

$product->addTaxonomy('category', 'home');
$product->addTaxonomy('category', 3);

$product->addTaxonomies('category', ['home', 'office']);
$product->addTaxonomies('category', ['home', 3]);
$product->addTaxonomies('category', [2, 3]);

要从未绑定的模型中删除术语,可以使用removeTaxonomy()和removeTaxonomies()方法。这些方法的工作方式与上述addTaxonomy()和addTaxonomies()方法相同。

$product->removeTaxonomy('category', 'home');
$product->removeTaxonomy('category', 3);

$product->removeTaxonomies('category', ['home', 'office']);
$product->removeTaxonomies('category', [2, 3]);

要删除与指定分类法绑定的所有术语,请使用clearTaxonomy()。

$product->clearTaxonomy('category');
$product->getTaxonomy('category'); // [];

在调用save()方法之前,对模型的分类法所做的任何更改都不会写入数据库。