The problem here is order, the $post
variable isn’t available from the moment WordPress is loaded, it needs to process the request, put together a database query, and retrieve the post first. Time travel is necessary for your code to work as you expected.
Your themes functions.php
and plugins will be loaded before this happens to give them a chance to have a say in the process, so if you attempt to use $post
at that time, it will fail, we don’t know what the $post
is yet, that work hasn’t been done.
The reason it works in the add metabox call, is because that action happens after the post is retrieved. This action happens in the future at a time when $post
exists and is known, after the work needed was done.
I would suggest as a general rule of thumb that you do work inside actions and filters, and rely on common actions for this, such as the init
hook, or the admin_init
hook, etc
See here for information on when hooks and important events happen, and when things are possible