v24 – Rendera WordPress inlägg programmatiskt i en plugin

Nu när du har skapat en egen router som kan skicka användare till en custom template när de besöker din plugins URL behöver du ett sätt att enkelt rendera alla inlägg som en URL ska visa upp. I våra exempel skickar vi användare till samma template oavsett om de har bett att få se alla portfölj ”items” eller bara ett, vilket betyder att vi måste utrusta våran router med logik för att känna av om en användare vill se en eller flera inlägg. Dessutom måste vi utrusta våran model med en metod som låter den rendera alla posts den för nuvarande håller i. Vår model måste även göra ett smart val av template beroende på om den håller i en eller flera inlägg.

Utrusta vår router med rätt data för ett request

  // classes/Router.class.php
  // add_filter('template_include') callback
  public function include_template($template) {
    // try and get the query var we registered in our 
    // $this->rewrite_rules() function
    $portfolio_page_id = get_query_var( $this->route_query_var );

    // if not on a portfolio page (no query var exists), do nothing
    if (!$portfolio_page_id) { return $template; }

    // if the query var has data, we must be on the right page
    // return our custom template
    $template = $this->template_path . 'portfolio.php';

    // NEW CODE: detects and gets correct data for a request by
    // passing an id, or nothing, to the model __construct
    if ( $portfolio_page_id != "all" ) {
      // get single model
      $this->model = new Model($portfolio_page_id);
    } else {
      // get all models
      $this->model = new Model();
    }

    return $template;
  }

Det nya i metoden ovan är att vår router nu instantierar vår Model och skickar in antingen ett ID (om vi ska visa ett inlägg), eller ingenting (om vi ska visa alla inlägg).

Utöka routern så att den kan en metod som kan rendera nuvarande model

// classes/Router.class.php
public function render_model() {
    // tell model to use these templates to render data
    $model_templates = $this->template_path . 'model/';
    $this->model->render($model_templates);
}

Koden ovan bestämmer var modellens templates finns, och skickar vidare sökvägen till modellens renderingsmetod.

Utöka modellen med en renderingsmetod

Vi behöver nu få våran modell att kunna rendera all data den håller i. Då vår modell kan bestå av en eller flera inlägg måste renderingsmetoden även förstå när den ska välja en ”single” template och när den ska välja en ”multiple” template.

  // classes/Model.class.php
  // renders all models using the appropriate template
  public function render($template_dir) {
    $type = count($this->instances) > 1 ? 'multiple' : 'single';

    foreach ($this->instances as $model) {
      // setup wordpress post data
      // so we can use the_title() and the_content()
      $GLOBALS['post'] = &$model->post;
      setup_postdata($GLOBALS['post']);

      // this will print HTML from included PHP file
      // with our extracted properties from above
      include($template_dir.$type.'.php');
    }

    // reset WP post data once we are done
    wp_reset_postdata();
  }

Koden ovan går igenom alla instances i en model, och beroende på om det är en eller flera, inkluderar rätt template fil. Genom att anropa setup_postdata() precis innan vi inkluderar var template kan vi använda WordPress inbyggda templating funktioner såsom the_title() och the_content() i template filen. Då vi inkluderar templatefiler som innehåller HTML kommer de direkt att skriva ut sitt innehåll som output. Med andra ord måste vi anropa Model->render() först där vi vill att dens HTML ska synas. Detta görs via Router->render_model(), då endast routern finns tillgänglig globalt i PHP.

Anropa routerns renderingsmetod vid rätt tillfälle

Se först till att routern finns tillgänglig globalt i PHP genom att lägga den i en variabel i plugin filen.

// my-portfolio.php
/*
  Plugin Name: My Portfolio
*/

[ ... ]

$instances = array();

foreach($classes as $class) {
  include_once(__DIR__ . "/classes/".$class.".class.php");
  // do not instantiate models now,
  // let controllers do that
  if (stripos($class, "model") !== FALSE) { continue; }
  // add namespace to class name
  $class_namespaced = __NAMESPACE__ . '\\'.$class;
  // instantiate class
  $instances[$class] = new $class_namespaced();
}

// NEW: make router globally accessible (for templates)
$router = $instances['Router'];

$router finns nu tillgängligt globalt i PHP.

Du kan nu nå routern i dina template filer.

<!-- templates/portfolio.php -->
<?php namespace MP;
  get_header();
?>
<div class="container">
  <div class="row">
    <?php
      // using $router declared in MP_PLUGIN_FILE
      $router->render_model();
    ?>
  </div>
</div>
<?php get_footer(); ?>

Inuti din template fil kan du nu kalla på Router->render_moder() var som helst i din HTML struktur där du vill att modellen ska skriva ut all sin HTML.

Ladda ner Model klassen som en .zip

0 votes