Skip to content

Anatomy of a Post

Daniel Pimley edited this page Oct 3, 2020 · 14 revisions

Posts are the building blocks of a typical blog page, and also the most complex object type in the engine. Let's take a look at the structure of a post. This is what you'll see if you var_export() a Post object:

Post::__set_state(array(
   'belongs_to' => 
  array (
    0 => 'user',
  ),
   'has_many' => 
  array (
    0 => 'comments',
    1 => 'likes',
    2 => 'pingbacks',
    3 => 'views',
  ),
   'has_one' => 
  array (
  ),
   'no_results' => false,
   'id' => '1',
   'feather' => 'text',
   'clean' => 'my-first-post',
   'url' => 'my-first-post',
   'pinned' => '0',
   'status' => 'public',
   'user_id' => '1',
   'created_at' => '2018-08-20 19:41:54',
   'updated_at' => '0000-00-00 00:00:00',
   'attribute_names' => 
  array (
    0 => 'body',
    1 => 'tags',
    2 => 'title',
  ),
   'attribute_values' => 
  array (
    0 => 'This is the body text of my first post.',
    1 => '{"foo":"foo","bar":"bar"}',
    2 => 'My first post',
  ),
   'queryString' => '
SELECT "posts".*,
       "post_attributes".name AS attribute_names,
       "post_attributes".value AS attribute_values
FROM "posts"
LEFT JOIN "post_attributes" ON ("post_attributes".post_id = "posts".id)
WHERE ("posts".feather IN (\'text\', \'photo\', \'audio\', \'uploader\', \'video\', \'link\', \'quote\'))
  AND (("posts".status IN (\'public\', \'draft\', \'registered\_only\', \'private\', \'scheduled\') OR "posts".status LIKE \'%{1}%\') OR ("posts".status LIKE \'%{%\' AND "posts".user_id = 1) OR ("posts".status = \'draft\' AND "posts".user_id = 1))
  AND ("posts".url = \'my-first-post\')
ORDER BY "posts".id DESC
',
   'updated' => false,
   'slug' => 'my-first-post',
   'filtered' => true,
   'attributes' => 
  array (
    'body' => 'This is the body text of my first post.',
    'tags' => '{"foo":"foo","bar":"bar"}',
    'title' => 'My first post',
  ),
   'body' => '<p>This is the body text of my first post.</p>
',
   'tags' => 
  array (
    'bar' => 'bar',
    'foo' => 'foo',
  ),
   'title' => 'My first post',
   'title_unfiltered' => 'My first post',
   'body_unfiltered' => 'This is the body text of my first post.',
))

A post is constructed by amalgamating data from two database tables: posts and post_attributes. The posts table provides the core attributes that every post has, for example id, user_id, and created_at, whilst the post_attributes table provides the attributes that are specific to a particular feather or added to the post by an enabled module. The exact SQL statement that was used to construct a post is saved in the post->queryString attribute.

By taking a look at the query, we can see that a post's permission system is built-in to the model. When a post is instantiated, the visitor ID and associated permissions will determine whether or not the post can be returned for this visitor. This is in contrast to the permission system for pages, which is much simpler and handled by MainController. If you are instantiating a post and you want to disable the built-in permissions system, you can supply the option 'skip_where' => true to the constructor.

Clone this wiki locally