Models are one of the cool features of OffbeatWP. It makes "The Loop" obsolete and gives a much more intuitive way of getting data from a post or term like the title, content or url.
OffbeatWP has two types of models:
- Post models A post model represents a post in a specific post type
- Term Models A term model represents a term in a specific taxonomy
A post model represents a post of a specific post type. Below an example of a post model:
<?php
namespace App\Models;
use OffbeatWP\Content\Post\PostModel as OffbeatWpPostModel;
class PostModel extends OffbeatWpPostModel {
const POST_TYPE = 'post';
const ORDER_BY = 'menu_order';
const ORDER = 'ASC';
}
It is easy to extend the model so you can get the data of a post in a readable and intuitive way. If you have a post type for events
it would be great to have a getter just for this:
<?php
namespace App\Models;
use OffbeatWP\Content\Post\PostModel as OffbeatWpPostModel;
class EventModel extends OffbeatWpPostModel {
const POST_TYPE = 'event';
public function getEventDate()
{
return $this->getMeta('event_date');
}
}
Now you can can easy get the post' event date by doing $event->getEventDate();
. In twig it even shorter: {{ event.eventdate }}
To create a model you can use the CLI-command:
wp offbeatwp make-postmodel {name} --post_type="{post_type}"
If you want to create a model for a module you can do this by adding --module={module_name}
to the command like:
wp offbeatwp make-postmodel {name} --post_type={post_type}--module={module_name}
By default the PostModel comes with the following methods to get data from the post:
Get the id of the post
Get the title of the post
Get the content of the post
Get the post' post_name / slug
Get the post' url
Get the id of the post
Get the excerpt of the post
Get the author of the post
Get a meta value of the post. The first attribute is the key to the meta. The second parameter is if you desire a single or multiple responses. Single is the default.
Setting a meta to the post. The argument is the key, the second the value of the meta.
Get the terms of the post by taxonomy. The first argument is the taxonomy. With the second parameter, you can set some additional arguments. These arguments are equal to the WP_Term_Query::__construct method.
Check if the post has a featured image. Returns true or false.
Returns html (img-tag) of the post' featured image. With the first argument you can define the size, the second you send arguments which are equal to get_the_post_thumbnail
Get the post' featured image url
Get the post' featured image id. Returns false if the post has no featured image.
If some plugin or other implementation requires a post to be in "the loop" you can run this method.
Ends "The loop"
You can add the constant ORDER
and ORDER_BY
to a model. Now every time you are getting posts this ordering is applied.
You can extend any post model from outside the model itself. This is called a macro. We have a independent service to integrate [Advanded Custom Fields }(https://www.advancedcustomfields.com/pro/) with OffbeatWP. Within the post model, we want to be able to easily get an ACF field. The service contains the following macro
:
PostModel::macro('getField', function ($name, $format = true) {
return get_field($name, $this->getId(), $format);
});
Now we can easily access the post' ACF field be doing:
post.getField('key')
OffbeatWP maps posts to the related model. But to make this possible we have to register the models. When you register the post type within your theme you can do this all at once as explained here. But if the post_type is Building (like post and page), or is defined within a plugin you have to do this by:
offbeat('post-type')->registerPostModel('post', \App\Models\PostModel::class);
The first argument is the post_type and the second the PostModel.
You can get posts from the model just by doing the following:
PostModel::all();
This will get you the number of posts as configured in the WordPress settings (Settings > Reading).
PostModel::all();
This will get you all the posts.
PostModel::take(5);
This will get you the first 5 posts.
PostModel::first();
This will get you the first post.
PostModel::findbyId($id);
Find a post by id.
OffbeatWP comes with a variety of methods to filter your posts:
where($args)
The arguments are equal to WP_Query. But since this won't make your code very readable we do not recommend this filter.
whereTerm($taxonomy, $terms = [], $field = 'slug', $operator = 'IN')
Filter the posts by a term.
whereDate($args)
Filter the posts by date. Arguments are equal to WP_Query::data_query
whereMeta($key, $value = '', $compare = '=')
Filter the posts by meta.
Those filters can be chained like:
PostModel::whereTerm('tags', 'awesome')->whereMeta('great', 'NOT', '!=')->all();
This will get you all the posts having the tag "awesome" and where meta "great" is not equal to "NOT". The ->all()
could also be substitued by ->take(5)
, ->first()
or just ->get()
.
Ordering posts can be done by adding ->order($order_by, $order)
to the chain, like:
PostModel::whereTerm('tags', 'awesome')->order('id', 'ASC')->take(5);
This will get you the first 5 results of all posts the tag "awesome", ordered by id (ascending).
To order by meta give as first argument meta:{meta_key}
or to order as number meta_num:{meta_key}
The get
, take
and all
methods return a Collection. OffbeatWP uses the Laravel Collection which gives you an awesome toolset.
A collection is iterable, meaning that you can just loop over it in a foreach loop. This is really helpful within your template. Just can just send the collection to your view and loop over it with twig-like:
{% for event in events %}
<h3>{{ event.title }}</h3>
{% endfor %}
With a more advanced website, you often want to create relationships between posts. With OffbeatWP this is really simple.
First, we have to install a service, this to your config/services.php
file:
OffbeatWP\Content\Post\Relations\Service::class,
To make these queries run quickly we have to install an extra table in our database. This is done through WP-CLI, run from your terminal:
wp post-relations:install
In your model, you can define the relationship like this
<?php
namespace App\Models;
use OffbeatWP\Content\Post\PostModel as OffbeatWpPostModel;
class EventPostModel extends OffbeatWpPostModel {
const POST_TYPE = 'event';
public function locations()
{
$this->hasMany('{key}');
}
}
The key is something you make up yourself to identify the relationship. We recommend something declarative like the post type "event_location".
Besides ->hasMany
you can use ->hasOne()
, ->belongsTo()
or ->belongsToMany()
Now you can attach another post by doing:
$event->locations()->attach($id);
If you also use an array of ids to attach multiple posts at once. By default, the relations are appended to existing relationships. If you what to replace the existing relationships, you just have to add a second parameter with the value false
like:
$event->locations()->attach([1,2,3], false);
You can detach an relationship by doing:
$event->locations()->detach($id);
or to detach all relationships.
$event->locations()->detachAll();
Now you can associate another post by doing:
$location->events()->associate($id);
If you also use an array of ids to associate multiple posts at once. By default, the relations are appended to existing relationships. If you what to replace the existing relationships, you just have to add a second parameter with the value false
like:
$location->events()->associate([1,2,3], false);
You can dissociate an relationship by doing:
$event->locations()->dissociate($id);
or to dissociate all relationships.
$event->locations()->dissociateAll();
$event->locations()->get();