anthonybudd / wp_model
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()方法之前,对模型的分类法所做的任何更改都不会写入数据库。