How to access the WordPress DB from a plugin file

If you plan to share/sell your plugin I strongly suggest don’t load your plugin directly.

That because to load WordPress you need to load the bootstrap file, that is /wp-load.php so, you should put in your embed-video.php something like:

require '/wordpress/path/wp-load.php';

Do you notice the problem here? The /wordpress/path/ part is different for user to user, and, really, even if you use something like

require dirname( dirname( dirname( dirname( __FILE__ ) ) ) ) . '/wp-load.php';

It’s not enough, because wp_content folder and/or plugins folder can be moved from standard position, so you can never be sure where they are.

If you are writing a plugin only for yourself, you can do it, because you know where your files are, just be sure to use a flexible manner to define the path, because even youcan need to move your folders in future.

If you are writing plugin to share/sell you’ll need to use an alternative.

One is to send requests to admin-ajax.php and use the ajax api. I know that you are thinking that your request is not ajax, but that’s not a problem: any ajax request is just an http request, so it will work even if you send a “normal” GET request.

Example code:

add_action( 'plugins_loaded', function() {
  /*
  once we use ajax api we can check if DOING_AJAX is set
  even if we are not really doing ajax
  that will reduce the times we perform code, speeding up you others requests
  */
  if ( ! defined('DOING_AJAX') ) return;

  /*
  check if the url contain the GET argument 'action' set to 'embedvideo'
  and contain the video id in the argument 'video'
  if not do nothing
  */
  $action = filter_input( INPUT_GET, 'action', FILTER_SANITIZE_STRING );
  $embed = (int) filter_input( INPUT_GET, 'video', FILTER_SANITIZE_NUMBER_INT );
  if ( $action === 'embed_video' || ! $embed > 0 ) return; 

  /* add the ajax action for logged and not logged users */
  add_action( "wp_ajax_{$action}", 'video_request'  );
  add_action( "wp_ajax_nopriv_{$action}", 'video_request'  );
});

Previous code add the action only when needed, speeding up all others requests, because 'plugins_loaded' hooks is fired for every request.

Now add the action function, where you’ll put the logic:

function video_request() {
   /* 
   check if the url contain a video id in the GET argument 'video' if not do nothing
   */
   $video = (int) filter_input( INPUT_GET, 'video', FILTER_VALIDATE_NUMBER_INT );
   if ( ! $video > 0 ) return;

   /* your post ID is in $video variable and you have WordPress available */
   $post = get_post( $video );

   // do stuff

   /*
   must exit(), because even not sended via ajax, we use ajax api that require to exit
   */
   exit(); 
}

Adding previous code to your plugin, you can use a function to easily generate the right urls:

function get_video_embed_url( $videoid = NULL ) {
  if ( is_numeric( $videoid ) && (int) $postid > 0 ) {
    $args = array( 'action' => 'embed_video', 'video' => $postid );
    return add_query_arg( $args, admin_url( 'admin_ajax.php' );
  }
  return '#';
}

function video_embed_url( $videoid = NULL ) {
  echo get_video_embed_url( $videoid );
}

After that, wherever you need the url video_embed_url( $id ) will echo the url (e.g. in html markup) get_video_embed_url( $id ) will return the url to use in code.

The urls will be something like

mysite.com/wp-admin/admin_ajax.php?action=embed_video&video={$videoid}

This code can seems more than you need, but:

  • it uses best practice, and allow you to share/sell your plugin
  • it’s developed using ajax api, and even if now you aren’t using ajax, in future you can mind to use it, and in that case you have to do nothing: your plugin is ready

A trick: use it with caution, or not use it at all

As said, when write code only for yourself, you can think to directly load your plugin file. And I also said that is better use a flexible way to defined paths.
This is an example of how you can flexible define them: not define at all, but pass in the url:

/* in main plugin file, that I suppose to be in the same folder of embed-video.php */
function my_embed_url( $id ) {
  if ( is_numeric( $id ) && $id > 0 ) {
    $base = plugins_url( '/embed-video.php', __FILE__ );
    $path = urlencode( base64_encode( trailingslashit( ABSTPATH ) . 'wp-load.php' ) );
    return add_aquery_arg( array( 'path' => $path, 'video' => $id ), $base );
  }
}

Previous function will return something like mysite.com/wp-content/plugins/myplugin/embed-video.php?path=L3Zhci93d3cvd29yZHByZXNzL3dwLWxvYWQucGhw&video=123 use this function to output the embed video (if you need to use url in post content use a shortcode).

Doing so, in first lines of embed-video.php you can:

$raw = filter_input( INPUT_GET, 'path', FILTER_SANITIZE_STRING );
$videoid = (int) filter_input( INPUT_GET, 'video', FILTER_SANITIZE_NUMBER_INT );
if ( empty($raw) || empty($videoid) || ! $videoid > 0 ) exit();
$path =  urldecode( base64_decode( $raw ) );
if ( ! file_exists( $path ) ) exit();

define( 'SHORTINIT', 1 ); // this allow you to load only minimun WP environment
require_once $path;

/* WordPress is available */
$post = get_post( $videoid );