Tạo một plugin WordPress tùy chỉnh đơn giản

Thật dễ dàng để tiếp tục thêm các chức năng vào trang web WordPress của bạn bằng cách dán mã vào tệp functions.php của chủ đề con của bạn. Tuy nhiên, đôi khi, thật tốt khi tạo ra thứ gì đó lâu dài hơn một chút. Có thể thêm một tính năng vượt qua chủ đề và bạn cũng có thể triển khai cho các trang web WordPress khác của mình. Hướng dẫn này trình bày cách tạo một plugin WordPress tùy chỉnh đơn giản để hiển thị các bài đăng của chúng tôi dưới dạng lưới.

Mặc dù bạn chỉ có thể sao chép và dán các bit mã nếu muốn, nhưng chúng tôi cũng sẽ trình bày một chút về quy trình lập trình ở đây. Làm thế nào để bạn đi từ một ý tưởng và một bức tranh trống, đến việc có một số mã làm việc thực hiện những điều thú vị.

Bạn sẽ có quyền truy cập vào bản cài đặt WordPress có chủ đề con tùy chỉnh và trang web sẽ cần một phiên bản hậu trường PHP mới nhất.

Sổ tay Plugin WordPress cũng là người bạn của bạn.

Giữ nó đơn giản

Khi bạn bắt đầu tạo thứ gì đó giống như một plugin tùy chỉnh, bạn chỉ cần tiếp tục thêm các tính năng ở đây và ở đó bởi vì… bạn có thể. Tuy nhiên, hãy cẩn thận, vì rất dễ vô tình tạo ra một con quái vật mã spaghetti. Một điều gì đó thật lộn xộn để theo dõi và không thể hiểu được khi bạn quay lại xem xét nó trong thời gian một năm.

Vì vậy,… chúng tôi sẽ tạo một plugin đơn giản chỉ làm một việc và hoạt động tốt:

  • Chúng tôi sẽ tạo một shortcode mới để hiển thị Bài đăng trong bố cục lưới.
    • Các công cụ bố trí lưới sẽ đến từ Bootstrap 4 tiêu chuẩn công nghiệp.
    • Plugin của chúng tôi sẽ nhập nội dung Bootstrap từ CDN.
    • Nếu trang web / chủ đề của bạn đã bao gồm Bootstrap, thì chúng tôi sẽ có thể làm điều đó thay vì tìm nạp Bootstrap trong plugin của chúng tôi.
  • Mã ngắn tùy chỉnh của chúng tôi để hiển thị bài đăng trong lưới sẽ có thể nhận một số tham số như:
    • Có bao nhiêu cột
    • Số lượng bài đăng tối đa để hiển thị
    • Loại thư
    • Danh mục (hoặc các danh mục)
  • Chúng tôi sẽ có thể tùy chỉnh bố cục lưới bài đăng với các đoạn mã mẫu trong chủ đề con tùy chỉnh của chúng tôi.

Hãy viết một số mã

Cấu trúc tệp và thư mục plugin của chúng tôi sẽ khá đơn giản. Chúng ta sẽ chỉ sử dụng một số hàm và hook cơ bản - chúng ta sẽ không đi sâu vào Model-View-Controller hoặc thậm chí là cấu trúc hướng đối tượng cơ bản ở đây. Tạo cấu trúc sau trên máy tính để bàn / máy tính xách tay của bạn. Bạn chỉ có thể thực hiện việc này trên Máy tính để bàn của mình nếu bạn muốn.

Tệp plugin chính là simple-post-grid.php . Hai tệp còn lại chứa các hằng số và hàm có thể được truy cập bằng cả chủ đề con tùy chỉnh của bạn VÀ bằng plugin của chúng tôi.

Đây là nội dung ban đầu cho constants.phpfunctions.php . Chúng tôi sẽ bổ sung thêm vào những điều này sau.

/**
 * FILE: constants.php
 */
// Block direct access.
if (!defined('WPINC')) {
    exit('Do NOT access this file directly.');
}
// Bootstrap assets.
define(
    'SGP_BOOTSTRAP_CDN_CSS',
    'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css'
);
define(
    'SGP_BOOTSTRAP_CDN_JS',
    'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js'
);
/**
 * FILE: functions.php
 */
// Block direct access.
if (!defined('WPINC')) {
    exit('Do NOT access this file directly.');
}
// TODO...

Và đây là mã cho simple-post-grid.php , để giúp chúng tôi bắt đầu với plugin thực tế của mình.

/**
 * Plugin Name:  Simple Post Grid
 * Plugin URI:   https://headwall-hosting.com/
 * description:  Display post summaries in a simple responsive grid.
 * Version:      1.0.0
 * Author:       Paul
 * Author URI:   https://headwall-hosting.com/docs/
 * License:      MIT
 * Text Domain:  simple-post-grid
 */
/**
 * [[ Notes ]]
 *
 * Bootstrap: If your theme already includes Bootstrap, add this to your child
 * theme's functions.php :
 * add_filter( 'spg_is_bootstrap_required', '__return_false' );
 */
// If this file is called directly, abort.
if (!defined('WPINC')) {
   die;
}
define('SIMPLE_POST_GRID_VERSION', '1.0.0');
/**
 * Any local dependencies can go here.
 */
require_once 'constants.php';
require_once 'functions.php';
/**
 * Do we need to do anything special to do during activation?
 */
function spg_activate_plugin() {
   // ...
}
register_activation_hook(__FILE__, 'spg_activate_plugin');
/**
 * Do we need to do anything special to do during deactivation?
 */
function spg_deactivate_plugin() {
   // ...
}
register_deactivation_hook(__FILE__, 'spg_deactivate_plugin');
/**
 * Add the Bootstrap 4 assets.
 */
function spg_enqueue_bootstrap() {
   $is_bootstrap_required = apply_filters(
      'spg_is_bootstrap_required',
      SPG_IS_DEFAULT_BOOTSTRAP_REQUIRED
   );
   if ($is_bootstrap_required) {
      wp_enqueue_style('bootstrap-css', SGP_BOOTSTRAP_CDN_CSS);
      wp_enqueue_script('bootstrap-js', SGP_BOOTSTRAP_CDN_JS, array('jquery'));
   }
}
/**
 * This is our main entry-point, where we put all the logic that runs every
 * page-load. This is really for registering filters and hooks.
 */
function spg_run() {
   // Add requried CSS and JS.
   add_action('wp_enqueue_scripts', 'spg_enqueue_bootstrap');
}
/**
 * Call our plugin's main entry-point function.
 */
spg_run();

Bây giờ bạn chỉ cần nén thư mục chứa (lưới đơn giản) và tải nó lên trang web WordPress của bạn từ nút “Tải lên Plugin” trên trang Plugin, trong Khu vực quản trị. Khi hoàn thành việc đó, bạn sẽ thấy plugin mới của mình trong danh sách các plugin đã cài đặt, như thế này.

Bây giờ bạn có thể chỉ cần nhấp vào Kích hoạt, để bắt đầu và chạy plugin! Để thực hiện thay đổi mã đối với plugin, bạn có thể sử dụng trình chỉnh sửa plugin tích hợp sẵn của WordPress, trong menu Plugin.

Tạo một số giàn giáo

Chúng tôi sẽ tạo một shortcode tùy chỉnh trong plugin của mình và trình xử lý shortcode sẽ gọi một số hàm khác để hiển thị HTML có liên quan. Vì vậy, chúng ta cần phải tìm ra thứ tự để thực hiện các công việc. Đầu tiên, hãy tạo một trang trên trang WordPress của chúng tôi, nơi chúng tôi có thể thêm shortcode của mình. Bạn gọi nó là gì không thực sự quan trọng - chúng tôi chỉ cần một nơi nào đó để kiểm tra shortcode tùy chỉnh mới của chúng tôi.

Tôi đã gọi shortcode mới của chúng tôi là “ spg_posts ”, mã này chưa tồn tại, nhưng nó sẽ sớm ra mắt. Chúng tôi sẽ vượt qua số cột mà chúng tôi muốn xem và chúng tôi đã chỉ định “không có danh mục” ở đây. Chúng tôi cũng không thể chỉ định tham số danh mục, nhưng tôi đã đưa nó vào trang thử nghiệm để giúp chúng tôi dễ dàng quay lại và kiểm tra sau.

Tiếp theo, mở tệp functions.php trong plugin simple-post-grid của bạn và thêm chức năng sẽ thực hiện hầu hết các công việc khó khăn trong plugin của chúng tôi.

/**
 * FILE: functions.php
 */
// Block direct access.
if (!defined('WPINC')) {
   exit('Do NOT access this file directly.');
}
/**
 * Return the HTML for our posts grid.
 */
function spg_get_posts_html($params) {
   $html = '';
   $html .= '

'; $html .= 'Hello World
'; $html .= '...'; $html .= '

'; return $html; }

Bây giờ hãy đăng ký shortcode tùy chỉnh của chúng tôi. Chỉnh sửa tệp simple-post-grid.php và thay đổi hàm spg_run (), như sau:

/**
 * This is our main entry-point, where we put all the logic that runs every
 * page-load. This is really for registering filters and hooks.
 */
function spg_run() {
   // Add requried CSS and JS.
   add_action('wp_enqueue_scripts', 'spg_enqueue_bootstrap');
   // Register the shortcode to render a simple post grid.
   add_shortcode('spg_posts', 'spg_get_posts_html');
}

Đảm bảo rằng tất cả các tệp của bạn đã được lưu, sau đó trỏ trình duyệt của bạn đến trang Kiểm tra lưới đăng của bạn. Bạn sẽ bắt đầu thấy những dấu hiệu của sự sống…

Thêm một số chất

Đã đến lúc bắt đầu sử dụng chức năng chính của plugin của chúng tôi và viết mã để truy cập vào spg_get_posts_html (). Tuy nhiên, trước tiên, hãy đặt một vài bit hữu ích vào constants.php - một số mặc định hữu ích, giá trị dự phòng và chuỗi ma thuật.
/**
 * FILE: constants.php
 */
// Block direct access.
if (!defined('WPINC')) {
   exit('Do NOT access this file directly.');
}
// Set this to true if you want to see useful diagnostics.
define('SPG_IS_DIAGNOSTIC_ENABLED', false);
// Bootstrap assets.
define('SGP_BOOTSTRAP_CDN_CSS', 'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css');
define('SGP_BOOTSTRAP_CDN_JS', 'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js');
// Bootstrap 4 supports a grid of up to 12 columns.
define('SPG_MIN_COLUMN_COUNT', 1);
define('SPG_MAX_COLUMN_COUNT', 12);
define('SPG_DEFAULT_CONTAINER_CLASS', 'container');
define('SPG_DEFAULT_COL_CLASS_PREFIX', 'col-sm-');
define('SPG_DEFAULT_ROW_CLASS', 'row');
define('SPG_GRID_ITEM_TEMPLATE_PARTS_DIR', 'template-parts');
define('SPG_GRID_ITEM_TEMPLATE_PART_PREFIX', 'post-grid');
define('SPG_IS_DEFAULT_BOOTSTRAP_REQUIRED', true);
// A nice default column count.
define('SPG_DEFAULT_COLUMN_COUNT', 3);
Nếu chúng tôi cố gắng sử dụng shortcode của mình mà không chuyển bất kỳ tham số nào thì nó vẫn sẽ hoạt động, chỉ cần sử dụng các giá trị mặc định trong constants.php.

Chúng tôi sẽ sử dụng Bootstrap 4 để bố trí các bài viết của chúng tôi trong một lưới. Điều này sẽ tự động làm cho HTML của chúng tôi đáp ứng với kích thước và hướng thiết bị, điều này thật tuyệt. Điều này có nghĩa là chúng ta cần xếp hàng các tài sản Bootstrap…

Chủ đề của bạn có thể đã có quyền truy cập vào Bootstrap 4, vì vậy chúng tôi sẽ bao gồm một bộ lọc cho phép bạn ghi đè mã của chúng tôi để bao gồm các nội dung này. Nó sẽ có ý nghĩa khi bạn nhìn thấy nó trong giây lát. Nếu bạn cần tắt tính năng tải Bootstrap tự động của chúng tôi, hãy thêm nó vào functions.php của chủ đề con tùy chỉnh của bạn.

// Stop the simple-post-grid plugin from loading Bootstrap.
add_filter( 'spg_is_bootstrap_required', '__return_false' );

Đây là tệp functions.php mới cho plugin WordPress tùy chỉnh của chúng tôi, với nội dung “Hello World” được thay thế bằng mã thực. Coi chừng … nó hơi lổn nhổn.

/**
 * FILE: functions.php
 */
// Block direct access.
if (!defined('WPINC')) {
   exit('Do NOT access this file directly.');
}
/**
 * Return the HTML for our posts grid, using the Bootstrap 4 Grid system.
 *
 * Best results are achieved with 1, 2, 3, 4 or 6 columns.
 *
 * [[ $params ]]
 *    'post_type'   => (string) Post Type slug to use. Default is 'post'.
 *    'cols'        => (int) The number of coumns to redner. Default is 3.
 *    'post_count'  => (int) Ignore the WordPress default number of posts to
 *                     fetch, and try to fetch this many posts instead.
 *    'category'    => (string) comma-separated list of category slugs for the
 *                     posts you want to show.
 *
 * [[ Returns ]]
 * HTML that you can either echo to the output, or do some extra processing if
 * you want.
 */
function spg_get_posts_html($params) {
   $html = '';
   // How many columns do we want?
   $column_count = 0;
   if (array_key_exists('cols', $params)) {
      $column_count = intval($params['cols']);
   }
   if (($column_count < SPG_MIN_COLUMN_COUNT) || ($column_count > SPG_MAX_COLUMN_COUNT)) {
      $column_count = SPG_DEFAULT_COLUMN_COUNT;
   }
   $column_span = intval(floor(SPG_MAX_COLUMN_COUNT / $column_count));
   if ($column_span < 1) {
      $column_span = 1;
   }
   $query_args = array();
   // Have we specified a Post Type?
   $post_type = null;
   if (array_key_exists('post_type', $params)) {
      $post_type = (string) $params['post_type'];
   }
   if (empty($post_type) || !is_string($post_type)) {
      $post_type = 'post';
   }
   $query_args['post_type'] = $post_type;
   // Are we override the default WordPress number of posts per page?
   $posts_per_page = 0;
   if (array_key_exists('post_count', $params)) {
      $posts_per_page = intval($params['post_count']);
   }
   if (!empty($posts_per_page)) {
      $query_args['posts_per_page'] = $posts_per_page;
   }
   // Do we have one or more category slugs in the 'category' paremeter?
   // If so, convert them into IDs so we can set the 'cat' query parameter.
   $category_ids = '';
   if (array_key_exists('category', $params) && is_string($params['category'])) {
      $category_slugs = explode(',', (string) $params['category']);
      foreach ($category_slugs as $category_slug) {
         if (!empty($category_slug) && (($category = get_category_by_slug($category_slug)) !== false)) {
            if (strlen($category_ids) > 0) {
               $category_ids .= ', ';
            }
            $category_ids .= $category->term_id;
         }
      }
   }
   if (!empty($category_ids)) {
      $query_args['cat'] = $category_ids;
   } else {
      // Don't apply a category filter.
   }
   $query_args = apply_filters(
      'spg_post_grid_query_args',
      $query_args
   );
   // TODO: Check that $query_args is a valid array for WP_Query.
   $query = new WP_Query($query_args);
   if ($query->have_posts()) {
      $template_file_name = null;
      $is_row_open = false;
      $column_index = 0;
      $container_classes = null;
      $container_classes_array = apply_filters(
         'spg_container_classes',
         array(SPG_DEFAULT_CONTAINER_CLASS)
      );
      if (!empty($container_classes_array) && is_array($container_classes_array)) {
         $container_classes = trim(implode(' ', $container_classes_array));
      }
      $row_classes = null;
      $row_classes_array = apply_filters(
         'spg_row_classes',
         array(SPG_DEFAULT_ROW_CLASS)
      );
      if (!empty($row_classes_array) && is_array($row_classes_array)) {
         $row_classes = trim(implode(' ', $row_classes_array));
      }
      // Sanitise the returned values from our filters.
      if (empty($container_classes)) {
         $container_classes = SPG_DEFAULT_CONTAINER_CLASS;
      }
      if (empty($container_classes)) {
         $row_classes = SPG_DEFAULT_ROW_CLASS;
      }
      $column_classes = SPG_DEFAULT_COL_CLASS_PREFIX . $column_span;
      $html .= sprintf('
', $container_classes); // // Our WordPress WP_Query loop. // while ($query->have_posts()) { $query->the_post(); $post_type = get_post_type(); // If SPG_IS_DIAGNOSTIC_ENABLED is true (in constants.php) then // echo the name of the template file name we're looking for. // A useful debugging tool. if ((bool) SPG_IS_DIAGNOSTIC_ENABLED && empty($template_file_name)) { $template_file_name = SPG_GRID_ITEM_TEMPLATE_PARTS_DIR . DIRECTORY_SEPARATOR . SPG_GRID_ITEM_TEMPLATE_PART_PREFIX . '-' . $post_type . '.php'; } if (!$is_row_open) { $html .= sprintf('
', $row_classes); $is_row_open = true; } $html .= sprintf('
', $column_classes); // Start capturing the output buffer. ob_start(); $is_template_found = get_template_part( SPG_GRID_ITEM_TEMPLATE_PARTS_DIR . DIRECTORY_SEPARATOR . SPG_GRID_ITEM_TEMPLATE_PART_PREFIX, $post_type ); $html .= ob_get_clean(); // Output buffer captured - back to normal. // If no template was found, make sure we output something. if ($is_template_found === false) { $html .= get_the_title(); } $html .= '
'; // .col-sm-X ++$column_index; if ($column_index >= $column_count) { $html .= '
'; // .row $is_row_open = false; $column_index = 0; } } if (!$is_row_open) { $html .= '
'; // .row $is_row_open = false; } $html .= ''; // .container if (SPG_IS_DIAGNOSTIC_ENABLED) { $html .= '

'; $html .= 'Template: ' . $template_file_name . ''; $html .= '

'; } wp_reset_postdata(); } else { $html .= sprintf( '

%s

', __('No posts found', 'simple-post-grid') ); } return $html; }

Giống như hầu hết các hàm shortcode, luồng logic hoạt động như sau:

  • Phân tích cú pháp mảng $ params để xem liệu chúng ta có được chuyển bất kỳ tham số nào mà chúng ta có thể sử dụng hay không.
    • Sanity-kiểm tra các thông số trước khi sử dụng chúng.
  • Tạo một mảng args cho WP_Query của chúng tôi.
  • Bắt đầu Vòng lặp.
    • Xử lý tất cả các bài đăng từ WP_Query của chúng tôi.
  • Thu dọn.
  • Trả lại HTML trong một chuỗi.
Bây giờ chúng tôi đã có đủ mã để kiểm tra shortcode. Trong trang web thử nghiệm của mình, tôi đã tạo 3 Bài đăng trong một danh mục có tên là “Đánh giá sách”. Điều này có nghĩa là mã ngắn của tôi trông như thế này:
[spg_posts cols = "3" post_count = "12" category = "book-reviews"]
… Và đây là giao diện của nó trong trình duyệt.

Chúng tôi đang tiến bộ ở đây và chúng tôi có thể đưa ra một số đánh giá sách, nhưng nó không đẹp… vì vậy…

Thêm một số kiểu

Nếu bạn lướt qua hàm spg_get_posts_html () của chúng tôi , bạn sẽ thấy chúng tôi thực hiện lệnh gọi hàm get_template_part () của WordPress. Điều này có nghĩa là chúng tôi có thể thêm một số phong cách trong bất kỳ chủ đề nào chúng tôi đang sử dụng. Nếu chúng tôi không thể tìm thấy một phần mẫu thì chúng tôi quay lại chỉ xuất ra tiêu đề của bài đăng.

Trong chủ đề con tùy chỉnh của bạn, hãy đảm bảo rằng bạn có một thư mục được gọi là “phần mẫu ”. Tại đây, tạo một tệp mới có tên “ post-grid-post.php “. “Bit“ -post ”ở cuối tên tệp là vì các bài viết Đánh giá Sách của tôi thuộc loại bài đăng ‘Đăng’. Nếu bạn muốn xuất một lưới các Trang thì bạn sẽ cần một tệp mẫu có tên là ‘post-grid-page.php’. Có một thủ thuật chẩn đoán gọn gàng ở đây… Nếu bạn vào constants.php và đặt SPG_IS_DIAGNOSTIC_ENABLED thành true , shortcode của chúng tôi sẽ xuất ra tên tệp phần mẫu mà nó đang tìm kiếm 😎

Đây là template-part / post-grid-post.php từ chủ đề con tùy chỉnh của tôi. Đó chỉ là một ví dụ nhanh chóng và đơn giản để cho thấy rằng bạn có thể đưa tất cả các loại vào phần mẫu của mình - logic PHP, HTML đơn giản, bất cứ thứ gì bạn muốn.

// Block direct access.
if (!defined('WPINC')) {
   exit('Do NOT access this file directly.');
}
$title = get_the_title();
echo '
'; printf('', esc_url(get_the_permalink()), esc_attr($title)); if (has_post_thumbnail() && !empty($thumbnail = get_the_post_thumbnail_url(null, 'medium'))) { printf('%s', esc_attr($title), esc_url($thumbnail)); } echo '

'; echo esc_html($title); echo '

'; echo '
'; echo '
'; // .post-grid-tile

Và đây là một chút kiểu dáng để làm cho nó trông đẹp mắt. Bạn có thể đặt tệp này vào tệp style.css trong chủ đề con tùy chỉnh của mình. Plugin sẽ hoạt động tốt mà không có chút CSS này, nhưng nó sẽ trông chưa hoàn thiện trên màn hình.

/**
 * Simple Post Grid
 */
.post-grid-tile {
   border: 1px dotted grey;
   position: relative;
   border-radius: 0.5em;
   overflow: hidden;
   box-shadow: 0 0 0.5em lightgrey;
}
.post-grid-tile:hover {
   box-shadow: 0 0 0.5em grey;
}
.post-grid-tile img {
   width: 100%;
   object-fit: cover;
}
@media (min-width: 576px) {
   .post-grid-tile img {
      height: 10em;
   }
}
.post-grid-tile h2 {
   position: absolute;
   bottom: 0;
   font-size: 11pt;
   background: rgba( 255, 255, 255, 0.75 );
   transition: 0.3s;
   margin: 0;
   height: 3.5em;
   text-align: center;
   color: black;
   padding-top: 0.5em;
   border-top: 1px dotted grey;
}
.post-grid-tile a:hover h2 {
   background: rgba( 255, 255, 255, 1.00 );
}
Và đây là kết quả đã hoàn thành, được bổ sung thêm một số bài đánh giá sách để chứng minh rằng lưới của chúng tôi có thể trải dài nhiều hàng đúng cách.

Kết thúc

Tôi sẽ đề cập đến các plugin tùy chỉnh nâng cao hơn trong một bài đăng khác, với những thứ như jQuery & JavaScript, Cron job và các tính năng bổ sung khác. Nhưng điều này sẽ đủ để cung cấp cho bạn một số ý tưởng cho plugin của riêng bạn… hoặc thậm chí có thể làm điều gì đó thú vị với plugin này. Bạn có thể dễ dàng đặt post_type thành 'product' và bắt đầu hiển thị nội dung cửa hàng WooCommerce ở định dạng lưới trong các bài đăng của mình. Hoặc có thể bạn muốn thêm Khối Gutenburg để bổ sung cho mã ngắn?

Nếu bạn cần tạo một số mã ngắn, thêm một số chức năng phổ biến và sử dụng lại mã trên nhiều trang web WordPress, thì việc biết cách tạo một plugin tùy chỉnh là một công cụ tuyệt vời cho bất kỳ nhà phát triển nào!