When creating meta boxes, in each meta box function it seems a reference to the global $post is passed as a parameter ($event). I prefer this as it seems consistent and less likely to fudge the $post var by declaring it explicitly as I have read elsewhere.

add_action('admin_init', 'events_admin');
function events_admin() 
{
     add_meta_box('display_events_date_meta_box',
        'Dates',
        'display_events_date_meta_box',
        'events', 'normal', 'high'
    );

}

function display_events_date_meta_box($event) // Referenced
{
     //$event in this case is the $post global
}

I have created a filter and various other functions which currently just use the global $post variable.

add_action( 'admin_head-post-new.php', 'test' );
add_action( 'admin_head-post.php', 'test' );
function test()
{
    global $post; // Declared explicitly
}

Is there a standard / recommended way to pass the global $post variable as a parameter to these functions?

3 s
3

When I need to deal with $post variable on admin, I usually use a class to early catch and wrap global $post variable, obtaining an universal way to access to it, without repetitely relying on the global variable.

class MyAdminPost 
{

   private static $post;

   public static function init()
   {
     $p_get = filter_input(INPUT_GET, 'post', FILTER_SANITIZE_NUMBER_INT);
     $p_post = filter_input(INPUT_POST, 'post', FILTER_SANITIZE_NUMBER_INT);
     if ($p_get > 0 || $p_post > 0) {
       self::$post = $p_get > 0 ? get_post($p_get) : get_post($p_post);
     } elseif ($GLOBALS['pagenow'] === 'post-new.php') {
       add_action('new_to_auto-draft', function(\WP_Post $post) {
         if (is_null(MyAdminPost::$post)) {
           MyAdminPost::$post = $post;
         }
       }, 0);
     }
   }

   public function get()
   {
     return self::$post;
   }
}

add_action('admin_init', array('MyAdminPost', 'init'));

On early stage of admin loading, that is 'admin_init' hook, 'MyAdminPost' class looks for post ID variable sent with request and store related post object.

That works on post.php page, but not on post-new.php, because on that page post ID is not sent with request because it does’t exist yet. In that case I add a callback to 'new_to_auto-draft' that is one the "{old_status}_to_{new_status}" hooks to store the post immediately after it is created on post-new.php page.

In this way, in both pages, post object is stored in a class property very early.

Usage Example (Procedural)

function get_my_admin_post()
{
   static $post = null;
   if (is_null($post) && did_action('admin_init')) {
     $map = new MyAdminPost();
     $post = $map->get(); 
   }

   return $post;
}

add_action('admin_head-post.php', 'test');

function test()
{
    $post = get_my_admin_post();
}

Usage Example (OOP)

class ClassThatUsesPostObject
{

  private $post_provider;

  function __construct(MyAdminPost $map)
  {
     $this->post_provider = $map;
  }

  function doSomethingWithPost()
  {
    $post = $this->post_provider->get();
  }
}

Benefits

  • you can obtain post object very early in a way that is compatible to both post.php and post-new.php pages, so in all the hooks fired in those pages you have access to post object with no effort

  • you remove any global $post variable reference in your code

  • your code becomes testable in isolation

Leave a Reply

Your email address will not be published. Required fields are marked *