Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Develop Plugins Like a Pro

Develop Plugins Like a Pro

Maybe you’ve dabbled in writing WordPress plugins and themes before, or maybe you’ve been too intimidated to get started. Whatever your skill level, there’s always more to learn! In this workshop, I’ll cover the basics of plugin development and share some tips to have you writing plugins like a pro in no time.

Alison Barrett

May 04, 2014
Tweet

More Decks by Alison Barrett

Other Decks in Programming

Transcript

  1. Agenda 1. Make a plugin 2. Actions & filters 3.

    Scripts & styles 4. Make a plugin 5. Custom queries 6. Widgets API 7. Make a plugin
  2. You Should Have ‣ Local development environment ‣ IDE or

    text editor open to your plugins folder ‣ Browser open to the Plugins admin page
  3. <?php   /**    *  Plugin  Name:  Hello  WordPress  

     *  Plugin  URI:    http://example.com/hello-­‐wordpress    *  Description:  Shows  up  on  the  Plugins  page,  and  not  much  else.    *  Author:            Alison  Barrett    *  Author  URI:    http://alisothegeek.com/    *  Version:          1.0    */    
  4. function  my_other_function(  $content  )  {      …    

     return  $content;   }   add_filter(  'the_content',  'my_other_function'  );
  5. function  append_author_bio(  $content  )  {      $bio  =  get_the_author_meta(

     'description'  );      return  $content  .  $bio;   }   add_filter(  'the_content',  'append_author_bio'  );
  6. function  myplugin_scripts()  {     ?>     <script  src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>

        <script  src="/wp-­‐content/plugins/myplugin/stuff.js"></script>     <?php   }   add_action(  'wp_head',  'myplugin_scripts'  );
  7. <script  src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> ‣ another plugin might load jQuery ‣ this

    might conflict with the WordPress version of jQuery   <script  src="/wp-­‐content/plugins/myplugin/stuff.js"></script> ‣ that might not be where wp-content is
  8. function  myplugin_scripts()  {     wp_enqueue_script(  'jquery'  );    

    wp_enqueue_script(  'myplugin',  plugins_url(  'stuff.js',  __FILE__  )  );   }   add_action(  'wp_enqueue_scripts',  'myplugin_scripts'  );   !
  9. function  myplugin_scripts()  {     wp_enqueue_script(  'jquery'  );    

    wp_enqueue_script(  'myplugin',  plugins_url(  'stuff.js',  __FILE__  )  );   !   wp_enqueue_style(  'myplugin',  plugins_url(  'stuff.css',  __FILE__  )  );   }   add_action(  'wp_enqueue_scripts',  'myplugin_scripts'  );
  10. wp_enqueue_script(     'myplugin',     plugins_url(  'myplugin.js',  __FILE__  ),

        array(  'jquery'  ),     '1.0.0',     true   ); unique ID URL to file dependencies version load in footer unique ID
  11. wp_enqueue_style(     'myplugin',     plugins_url(  'myplugin.css',  __FILE__  ),

        array(),     '1.0.0',     'screen'   ); unique ID URL to file dependencies version media
  12. Benefits of wp_enqueue_script ‣ Each file is only loaded once

    ‣ Dependencies are always loaded first and in the right order ‣ CSS files are called next to each other so they can load in parallel
  13. Goals ‣ Add an author bio to the end of

    every post ‣ Use the author bio field from the user's profile ‣ Show the author's Gravatar
  14. <?php   /**    *  Plugin  Name:  Authorial    *

     Plugin  URI:    http://example.com/authorial    *  Description:  Append  an  author  bio  to  every  post.    *  Author:            Alison  Barrett    *  Author  URI:    http://alisothegeek.com/    *  Version:          1.0    */     authorial.php
  15. function  authorial_enqueue_style()  {       wp_enqueue_style(      

        'authorial',           plugins_url(  'authorial.css',  __FILE__  ),           array(),           '1.0.0'       );   }   add_action(  'wp_enqueue_scripts',  'authorial_enqueue_style'  );
  16. function  authorial_add_bio(  $content  )  {       $bio  =

     get_the_author_meta(  'description'  );       return  $content  .  $bio;   }   add_filter(  'the_content',  'authorial_add_bio'  );
  17. function  authorial_add_bio(  $content  )  {       $bio  =

     wpautop(  get_the_author_meta(  'description'  )  );       return  $content  .  $bio;   }   add_filter(  'the_content',  'authorial_add_bio'  );
  18. ob_start();   ?>   <div  class="authorial-­‐bio">      <h3>About  the

     Author</h3>      <?php  echo  $bio;  ?>   </div>   <?php   $html  =  ob_get_clean(); PHP PHP HTML
  19. function  authorial_add_bio(  $content  )  {       $bio  =

     wpautop(  get_the_author_meta(  'description'  )  );       ob_start();   ?>   <div  class="authorial-­‐bio">       <h3>About  the  Author</h3>       <?php  echo  $bio;  ?>   </div>   <?php       $html  =  ob_get_clean();       return  $content  .  $html;   }   add_filter(  'the_content',  'authorial_add_bio'  );
  20. $bio  =  wpautop(  get_the_author_meta(  'description'  )  );   $name  =

     get_the_author_meta(  'display_name'  );   ob_start();
  21. Goals ✓ Add an author bio to the end of

    every post ✓ Use the author bio field from the user's profile ‣ Show the author's Gravatar
  22. $bio  =  wpautop(  get_the_author_meta(  'description'  )  );   $name  =

     get_the_author_meta(  'display_name'  );   $avatar  =  get_avatar(  get_the_author_meta(  'ID'  ),  100  );   ! ob_start();
  23. <div  class="authorial-­‐bio">       <h3>About  <?php  echo  $name;  ?></h3>

          <?php  echo  $avatar;  ?>       <?php  echo  $bio;  ?>   </div>
  24. .authorial-­‐bio  {     padding:  20px;     margin:  20px

     0;     overflow:  hidden;     background:  #f5f5f5;     border:  3px  solid  #e5e5e5;   }   ! .authorial-­‐bio  .avatar  {     float:  left;     margin:  20px  20px  10px  0;   }   ! .authorial-­‐bio  h3  {     margin:  0;   }   ! .authorial-­‐bio  p  {     margin:  10px  0  0;   } authorial.css
  25. $my_query  =  new  WP_Query(  'orderby=title&order=ASC'  );   ! $my_query  =

     new  WP_Query(  array(    'orderby'  =>  'title',    'order'      =>  'ASC',   )  );
  26. class  My_Widget  extends  WP_Widget  {   !     public

     function  __construct()  {           //  widget  name,  ID,  etc.       }   !     public  function  widget(  $args,  $instance  )  {           //  outputs  the  content  of  the  widget       }   !     public  function  form(  $instance  )  {           //  outputs  the  options  form  on  admin       }   !     public  function  update(  $new_instance,  $old_instance  )  {           //  processes  widget  options  to  be  saved       }   ! }
  27. function  __construct()  {       parent::__construct(      

        'my_widget',           'My  Widget',           array(               'description'  =>  'A  Foo  Widget',           )       );   } unique ID title on Widgets page displays under title on Widgets page
  28. public  function  widget(  $args,  $instance  )  {      

    $title  =  apply_filters(  'widget_title',  $instance['title']  );   !     echo  $args['before_widget'];   !     if  (  !  empty(  $title  )  )  {           echo  $args['before_title']  .  $title  .  $args['after_title'];       }   !     //  Widget  content  here   !     echo  $args['after_widget'];   } $args is set when the sidebar is registered $instance is data from the widget form in the admin
  29. public  function  form(  $instance  )  {       if

     (  isset(  $instance[  'title'  ]  )  )  {           $title  =  $instance[  'title'  ];       }       else  {           $title  =  'New  title';       }       ?>       <p>         <label  for="<?php  echo  $this-­‐>get_field_id(  'title'  );  ?>">Title:</label>         <input  type="text"                      class="widefat"                      id="<?php  echo  $this-­‐>get_field_id(  'title'  );  ?>"                      name="<?php  echo  $this-­‐>get_field_name(  'title'  );  ?>"                      value="<?php  echo  esc_attr(  $title  );  ?>"  />       </p>       <?php     }
  30. public  function  update(  $new_instance,  $old_instance  )  {      

    $instance  =  array();             $instance['title']  =  strip_tags(  $new_instance['title']  );   !     return  $instance;   }
  31. function  register_my_widget()  {          register_widget(  'My_Widget'  );

      }   add_action(  'widgets_init',  'register_my_widget'  ); class name
  32. Goals ‣ Add a widget that lists popular posts ‣

    Use comment count to determine popularity ‣ Allow user to change the number of posts listed ‣ Allow user to choose whether to display comment count
  33. <?php   /**    *  Plugin  Name:  Hot  Topics  

     *  Plugin  URI:    http://example.com/hot-­‐topics    *  Description:  A  widget  that  lists  the  most  discussed  posts.    *  Author:            Alison  Barrett    *  Author  URI:    http://alisothegeek.com/    *  Version:          1.0    */     hot-topics.php
  34. function  hot_topics_register_widget()  {       require_once  __DIR__  .  '/class-­‐hot-­‐topics-­‐widget.php';

          register_widget(  'Hot_Topics_Widget'  );   }   add_action(  'widgets_init',  'hot_topics_register_widget'  );
  35. public  function  __construct()  {       parent::__construct(    

          'hot_topics',           'Hot  Topics',           array(  'description'  =>  'A  list  of  your  most  discussed  posts',  )       );   }
  36. public  function  widget(  $args,  $instance  )  {      

    $title  =  apply_filters(  'widget_title',  $instance['title']  );   !     echo  $args['before_widget'];   !     if  (  !  empty(  $title  )  )           echo  $args['before_title']  .  $title  .  $args['after_title'];   !     echo  $args['after_widget'];   }
  37. public  function  widget(  $args,  $instance  )  {      

    $title  =  apply_filters(  'widget_title',  $instance['title']  );       $hot_topics_query  =  new  WP_Query(  array(           'orderby'                          =>  'comment_count',   !     )  );       echo  $args['before_widget'];   !     if  (  !  empty(  $title  )  )           echo  $args['before_title']  .  $title  .  $args['after_title'];   !     echo  $args['after_widget'];   }
  38. public  function  widget(  $args,  $instance  )  {      

    $title  =  apply_filters(  'widget_title',  $instance['title']  );       $hot_topics_query  =  new  WP_Query(  array(           'orderby'                          =>  'comment_count',           'ignore_sticky_posts'  =>  true,       )  );       echo  $args['before_widget'];   !     if  (  !  empty(  $title  )  )           echo  $args['before_title']  .  $title  .  $args['after_title'];   !     echo  $args['after_widget'];   }
  39. public  function  widget(  $args,  $instance  )  {      

    $title  =  apply_filters(  'widget_title',  $instance['title']  );       $hot_topics_query  =  new  WP_Query(  array(           'orderby'                          =>  'comment_count',           'ignore_sticky_posts'  =>  true,       )  );       if  (  $hot_topics_query-­‐>have_posts()  )  :           echo  $args['before_widget'];   !         if  (  !  empty(  $title  )  )               echo  $args['before_title']  .  $title  .  $args['after_title'];   !         echo  $args['after_widget'];       endif;   }
  40.   if  (  $hot_topics_query-­‐>have_posts()  )  :        

      echo  $args['before_widget'];   !         if  (  !  empty(  $title  )  )               echo  $args['before_title']  .  $title  .  $args['after_title'];   !         echo  '<ul>';           while(  $hot_topics_query-­‐>have_posts()  )  :               $hot_topics_query-­‐>the_post();               $comments  =  get_comment_count(  get_the_ID()  );               ?>               <li><a  href="<?php  the_permalink();  ?>">               <?php  the_title();  ?>               <?php  echo  '  ('  .  $comments['approved']  .  ')';  ?>               </a></li>               <?php           endwhile;           echo  '</ul>';   !         echo  $args['after_widget'];       endif;
  41. public  function  form(  $instance  )  {       if

     (  isset(  $instance[  'title'  ]  )  )  {           $title  =  $instance[  'title'  ];       }       else  {           $title  =  'Hot  Topics';       }       ?>       <p>         <label  for="<?php  echo  $this-­‐>get_field_id(  'title'  );  ?>">Title:</label>         <input  type="text"                      class="widefat"                      id="<?php  echo  $this-­‐>get_field_id(  'title'  );  ?>"                      name="<?php  echo  $this-­‐>get_field_name(  'title'  );  ?>"                      value="<?php  echo  esc_attr(  $title  );  ?>"  />       </p>       <?php     }
  42. public  function  update(  $new_instance,  $old_instance  )  {      

    $instance  =  array();             $instance['title']  =  strip_tags(  $new_instance['title']  );   !     return  $instance;   }
  43. Goals ✓ Add a widget that lists popular posts ✓

    Use comment count to determine popularity ‣ Allow user to change the number of posts listed
  44.     if  (  isset(  $instance[  'title'  ]  )  )

     {           $title  =  $instance[  'title'  ];       }       else  {           $title  =  'Hot  Topics';       }   !     if  (  isset(  $instance['number_of_posts']  )  )  {           $number_of_posts  =  (int)  $instance['number_of_posts'];       }  else  {           $number_of_posts  =  5;       } form()
  45.     <p>         <label  for="<?php  echo

     $this-­‐>get_field_id(  'title'  );  ?>">Title:</label>         <input  type="text"                      class="widefat"                      id="<?php  echo  $this-­‐>get_field_id(  'title'  );  ?>"                      name="<?php  echo  $this-­‐>get_field_name(  'title'  );  ?>"                      value="<?php  echo  esc_attr(  $title  );  ?>"  />       </p>       <p>         <label  for="<?php  echo  $this-­‐>get_field_id(  'number_of_posts'  );  ?>">Number  of  posts  to  show:</label>         <input  type="text"                      id="<?php  echo  $this-­‐>get_field_id(  'number_of_posts'  );  ?>"                      name="<?php  echo  $this-­‐>get_field_name(  'number_of_posts'  );  ?>"                      value="<?php  echo  esc_attr(  $number_of_posts  );  ?>"                      size="3"  />       </p>
  46. public  function  update(  $new_instance,  $old_instance  )  {      

    $instance  =  array();             $instance['title']  =  strip_tags(  $new_instance['title']  );   !     if  (  !  empty(  $new_instance['number_of_posts']  )  )  {           $instance['number_of_posts']  =  (int)  $new_instance['number_of_posts'];       }  else  {           $instance['number_of_posts']  =  5;       }   !     return  $instance;   }
  47. public  function  widget(  $args,  $instance  )  {      

    $title  =  apply_filters(  'widget_title',  $instance['title']  );       $number_of_posts    =  (int)  $instance['number_of_posts'];   !     $hot_topics_query  =  new  WP_Query(  array(           'orderby'                          =>  'comment_count',           'ignore_sticky_posts'  =>  true,           'posts_per_page'            =>  $number_of_posts,       )  );
  48. Goals ✓ Add a widget that lists popular posts ✓

    Use comment count to determine popularity ✓ Allow user to change the number of posts listed ‣ Allow user to choose whether to display comment count
  49.     <p>         <label  for="<?php  echo

     $this-­‐>get_field_id(  'number_of_posts'  );  ?>">Number  of  posts  to  show:</label>         <input  type="text"                      id="<?php  echo  $this-­‐>get_field_id(  'number_of_posts'  );  ?>"                      name="<?php  echo  $this-­‐>get_field_name(  'number_of_posts'  );  ?>"                      value="<?php  echo  esc_attr(  $number_of_posts  );  ?>"                      size="3"  />       </p>       <p>         <input  type="checkbox"                      class="checkbox"                      id="<?php  echo  $this-­‐>get_field_id(  'show_comment_count'  );  ?>"                      name="<?php  echo  $this-­‐>get_field_name(  'show_comment_count'  );  ?>"                      <?php  checked(  $instance['show_comment_count']  );  ?>  />         <label  for="<?php  echo  $this-­‐>get_field_id(  'show_comment_count'  );  ?>">Display  comment  count?</label>       </p>
  50. public  function  update(  $new_instance,  $old_instance  )  {      

    $instance  =  array();             $instance['title']  =  strip_tags(  $new_instance['title']  );   !     if  (  !  empty(  $new_instance['number_of_posts']  )  )  {         $instance['number_of_posts']  =  (int)  $new_instance['number_of_posts'];       }  else  {         $instance['number_of_posts']  =  5;       }   !     if  (  !  empty(  $new_instance['show_comment_count']  )  )  {         $instance['show_comment_count']  =  true;       }  else  {         $instance['show_comment_count']  =  false;       }   !     return  $instance;   }
  51.   if  (  $hot_topics_query-­‐>have_posts()  )  :        

      if  (  !  empty(  $instance['show_comment_count']  )  )  {               $show_comment_count  =  true;           }  else  {               $show_comment_count  =  false;           }   !         echo  $args['before_widget']; widget()
  52.         echo  '<ul>';        

      while(  $hot_topics_query-­‐>have_posts()  )  :               $hot_topics_query-­‐>the_post();               $comments  =  get_comment_count(  get_the_ID()  );               ?>               <li><a  href="<?php  the_permalink();  ?>">               <?php  the_title();  ?>               <?php  if  (  $show_comment_count  )  echo  '  ('  .  $comments['approved']  .  ')';  ?>               </a></li>               <?php           endwhile;           echo  '</ul>';