Học Wordpress

Dịch ngôn ngữ trong WordPress trên website với Loco Translate

75



Vấn đề dịch thuật trong WordPress như dịch plugin và theme quả thực là một cơn ác mộng, đúng không chứ? Hầu hết các sản phẩm của WordPress bao gồm theme và plugin đều là tiếng Anh, mà nếu website bạn phục vụ cho đối tượng người Việt Nam hay một quốc gia nào đó thì dĩ nhiên phải cần dịch lại cho tương xứng, ít nhất là dịch các đoạn chữ hiển thị ra ngoài website.

Mặc dù ở blog mình đã có hướng dẫn sử dụng PoEdit để dịch thuật theme và plugin của WordPress nhưng nhiều người mới tham gia vẫn còn bỡ ngỡ, và đối với người làm chuyên nghiệp rồi thì hơi bất tiện vì phải tải gói ngôn ngữ về mà dịch.

Vậy có cách nào để có thể tạo gói ngôn ngữ nhanh cho một plugin hay theme và dịch trực tiếp trên website mà không cần tải về không? Dĩ nhiên có, trước đây mình có giới thiệu Codestyling Localization nhưng plugin đó lại dễ bị xung đột với một số plugin và theme, và chuối nhất là một số ngôn ngữ khi tạo ra lại có mã ngôn ngữ không đúng, ví dụ như ngôn ngữ tiếng Việt thì hiện nay WordPress sử dụng là vi.mo nhưng plugin đó lại sinh ra file tên là vi_VN.mo thành ra không làm việc được nếu bạn sử dụng WordPress tiếng Việt.

Nhưng thay vào đó, mình giới thiệu đến bạn một plugin khác có chức năng tương tự đó là hỗ trợ dịch file .po nhanh cho plugin/theme, hoặc tạo mới một file .po hoàn toàn tự động và bao gồm chức năng dịch và chuyển sang định dạng .mo, đó là plugin Loco Translate.

loco-translate-cover

Loco Translate là một plugin mới nhưng được đánh giá rất cao trong vấn đề hỗ trợ dịch thuật trên website WordPress. Với giao diện mang tính tương đồng với PoEdit, hỗ trợ dịch các form số nhiều y hệt như PoEdit và tự động đồng bộ các đoạn text trong theme/plugin là một ưu thế rất mạnh của Loco Translate.

Tại Loco Translate, bạn có thể dễ dàng tạo ra một gói ngôn ngữ nhanh nhất và nó sẽ tự động lưu trong thư mục ngôn ngữ thích hợp của plugin hoặc theme đó, hoặc bạn có thể sử dụng cấu trúc thư mục ngôn ngữ chung của WordPress ở /wp-content/languages/, mình khuyến khích bạn sử dụng tùy chọn global languages directory nếu dùng cho mục đích cá nhân để dễ quản lý gói ngôn ngữ.

Tạo một file PO nhanh cho plugin/theme trong Loco Translate

Tạo một file PO nhanh cho plugin/theme trong Loco Translate

Ở phần chỉnh sửa, giao diện rất trực quan, hỗ trợ tải file PO hoặc MO về máy và dĩ nhiên là tự động chuyển đổi từ PO sang MO để cho WordPress đọc mỗi khi bạn ấn nút Save.

loco-translate-edit

Và nó có làm việc được không? Chắc chắn là có, xem này.

loco-translate-after

Chỉ đơn giản vậy thôi.

Hướng dẫn sử dụng Loco Translate

Để sử dụng Loco Translate tốt và có thể xem ngay những thay đổi sau khi dịch, bạn hãy tiến hành đổi ngôn ngữ của website WordPress tại Settings -> General -> Site Language. Nếu bạn muốn dịch thành tiếng Việt thì trước tiên phải cài ngôn ngữ tiếng Việt vào WordPress và tiến hành sử dụng Loco Translate sau.

wordpress-site-language

Sau đó bạn cài plugin Loco Translate vào và truy cập vào Loco Translate -> Manage translations để quản lý các gói ngôn ngữ của plugin và theme.

loco-translation-manage-translations

Bạn tìm đến sản phẩm mà bạn cần tạo ngôn ngữ hoặc cần dịch và ấn New Language (để tạo gói ngôn ngữ) hoặc click thẳng vào tên ngôn ngữ để bắt đầu dịch.

loco-translate-createnew

Và chọn ngôn ngữ trên danh sách ngôn ngữ, nó sẽ tự động điền mã ngôn ngữ cho bạn. Bạn có thể chọn kiểu lưu gói ngôn ngữ bất kỳ.

Tạo một file PO nhanh cho plugin/theme trong Loco Translate

Tạo một file PO nhanh cho plugin/theme trong Loco Translate

Và cuối cùng là nó sẽ tự động nhập dữ liệu từ file template dạng .po có trong sản phẩm đó và bạn có thể bắt đầu dịch và ấn Save lại. Trường hợp nếu nó không xuất hiện chữ thì hãy ấn nút Sync để nó tự nhập text thủ công từ mã nguồn.

loco-translate-edit

Một số lưu ý khi dùng Loco Translate

Để tránh nhiều bạn thắc mắc khi gặp vấn đề thì mình xin nêu ra một số lưu ý khi sử dụng.

  • Theme/Plugin cần dịch phải có file template hiển thị là .po hoặc .pot. Nếu nó hiển thị kiểu “default.mo” thì bạn nên vào host, tìm file default.po và đổi tên thành [mã-ngôn-ngữ].po thủ công rồi dịch sau.
  • Tránh sử dụng trên host yếu vì nó có thể làm đơ host của bạn.
  • Hãy chắc chắn thư mục /wp-content/ và các thư mục bên trong nó đang được CHMOD 644 để có quyền ghi dữ liệu vào. Trường hợp khi dịch mà báo lỗi permission thì hãy liên hệ với nhà cung cấp host chứ không nên CHMOD thành 777 như giang hồ đồn đại.
  • Nếu dịch xong mà ngôn ngữ không được kích hoạt thì hãy kiểm tra lại ngôn ngữ của website bạn có trùng khớp không, và thử tạo lại file ngôn ngữ với kiểu tùy chọn lưu file khác.
  • Đây là plugin hỗ trợ bạn dịch thủ công plugin và theme chứ không phải plugin tự động dịch nội dung.
  • Code trong plugin/ theme chắc chắn phải được viết theo chuẩn gettext, xem thêm.
  • Xem FAQ của Loco Translate trước nếu gặp vấn đề.
  • Tên mã ngôn ngữ phải trùng khớp với mã ngôn ngữ của website đang sử dụng. Để kiểm tra chắc chắn thì bạn cứ ấn Ctrl + U lên để xem mã nguồn và xem ở dòng <html>.

Lời kết

Loco Translate mình đã sử dụng trong khoảng hơn 1 tuần qua trong việc phục vụ dịch một số từ quan trọng trong dịch vụ cài WordPress của mình và thấy nó hoạt động rất tốt nên mình cũng hy vọng rằng nó có sẽ có ích đối với bạn. Hãy nhớ một điều rằng đôi khi có một số theme bạn sẽ gặp tình trạng một số từ dịch nó sẽ ra, một số từ dịch nó sẽ không ra là vì có thể theme đó sử dụng nhiều textdomain khác nhau (kiểu như họ chắp vá nhiều code của nhiều tác giả vào) nên lúc đó bạn có thể sử dụng kèm thêm PoEdit để kiểm tra.

Học Wordpress

Cấu trúc Template trong theme và Template Tag

68

Bài này thuộc phần 4 của 10 phần trong serie WordPress nâng cao


Để có thể dễ dàng hiểu được các phần sau của serie WordPress nâng cao, hoặc để bạn có thể tuỳ biến lại giao diện của WordPress thì chắc chắn bạn cần phải nắm được cấu trúc template của theme trong WordPress và làm quen với các hàm sử dụng trong template (gọi là Template Tags).

Trước tiên bạn cần phải hiểu, một theme được hình thành bởi các template. Các template trong theme sẽ bao gồm các tập tin như header.php, index.php, footer.php, sidebar.php, single.php,…Nhưng sẽ có một tập tin bắt buộc nhưng không phải là template đó là functions.php.

Template ở đây bạn có thể hiểu nó như là một cái khuôn mẫu được định dạng sẵn nhằm mục đích hiển thị nội dung trên website. Ví dụ bạn muốn tuỳ biến lại cách hiển thị nội dung của Post thì sẽ sửa template single.php.

Template và Template Tag hoạt động thế nào?

Template thì bạn đã biết rồi, nó là tập tin để khai báo khuôn mẫu để hiển thị nội dung, và các template tag được sử dụng trong template là những hàm hiển thị nội dung. Ví dụ dưới đây là một đoạn code ngắn thường thấy trong template single.php:

<h1 class="entry-title"><?php the_title(); ?></h1>

Ở trên là mình đã cố định thẻ <h1> để hiển thị nội dung của hàm the_title() (đây là template tag) nhằm hiển thị tiêu đề bài viết của truy vấn hiện tại (hay còn gọi là post hiện tại bạn đang xem). Khi xuất ra trình duyệt nó sẽ có dạng như thế này:

[html]<h1 class=”entry-title”>Cấu trúc Template và Template Tag</h1>[/html]

Như vậy bạn có thể hiểu, việc tuỳ biến theme chỉ đơn giản là sửa cấu trúc HTML và khai báo các template tag cần sử dụng cho nó hiển thị ra mà thôi.

Ví dụ, template single.php sử dụng cho post nào?

Mặc định trong WordPress, sau khi nó phân tích truy vấn dựa vào đường dẫn hiện tại mà bạn đang truy cập, nó sẽ phân tích template phù hợp cần hiển thị. Tất cả các template trong theme có thể sử dụng cho tất cả các phần tử con trong một đối tượng nào đó, ví dụ template single.php sẽ sử dụng cho toàn bộ Post trong WordPress, category.php sẽ áp dụng cho toàn bộ category,…Nhưng bạn cũng có thể tạo tempate riêng cho một phần tử nào đó, ví dụ template single-123.php sẽ áp dụng cho Post mang ID là 123, hay single-gioi-thieu.php sẽ áp dụng cho Post mang slug là gioi-thieu.

Cấu trúc template trong một theme

Hiện nay các theme, ngoài việc họ sử dụng các template bắt buộc của WordPress thì họ còn sử dụng thêm các template thêm vào. Nên nếu bạn muốn hiểu cấu trúc template chuẩn của WordPress thì hãy xem template của theme Twenty Fifteen. Bạn có thể xem nó trong thư mục /wp-content/themes/twentyfifteen/.

Cấu trúc template của theme Twenty Fifteen

Cấu trúc template của theme Twenty Fifteen

Template của WordPress chỉ là các tập tin .php và style.css thôi nên các thư mục bên trong theme đều không thuộc template mà tác giả đã tạo ra để dễ quản lý hoặc chứa các thành phần đặc biệt.

Tips: Cách tốt nhất để nhớ template tags và cấu trúc template là hãy thực hành tuỳ chỉnh theme thật nhiều. Hoặc hãy tham gia serie Lập trình theme WordPress để biết cách tự code một theme từ A tới Z.

style.css – Trái tim của theme

Tất cả các theme trong WordPress đều phải có tập tin style.css. Tập tin này không chỉ là chứa các CSS trong theme mà nó còn có chức năng khai báo thông tin của theme như tên theme, tên tác giả, số phiên bản,…nhằm có thể hiển thị trong khu vực Themes của WordPress. Nếu theme bạn không có tập tin này thì theme của bạn không hợp lệ.

Bạn hãy thử mở tập tin style.css của theme Twenty Fifteen lên, bạn sẽ thấy ở các dòng đầu tiên họ có comment một số đoạn thông tin sau:


/*
Theme Name: Twenty Fifteen
Theme URI: https://wordpress.org/themes/twentyfifteen/
Author: the WordPress team
Author URI: https://wordpress.org/
Description: Our 2015 default theme is clean, blog-focused, and designed for clarity. Twenty Fifteen’s simple, straightforward typography is readable on a wide variety of screen sizes, and suitable for multiple languages. We designed it using a mobile-first approach, meaning your content takes center-stage, regardless of whether your visitors arrive by smartphone, tablet, laptop, or desktop computer.
Version: 1.2
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Tags: black, blue, gray, pink, purple, white, yellow, dark, light, two-columns, left-sidebar, fixed-layout, responsive-layout, accessibility-ready, custom-background, custom-colors, custom-header, custom-menu, editor-style, featured-images, microformats, post-formats, rtl-language-support, sticky-post, threaded-comments, translation-ready
Text Domain: twentyfifteen

This theme, like WordPress, is licensed under the GPL.
Use it to make something cool, have fun, and share what you’ve learned with others.
*/

Các thông tin đó là những thông tin phải được khai báo ở theme, và nó sẽ hiển thị trong khu vực Appearance -> Themes.

functions.php – Bộ não của theme

Tập tin này tuy không thuộc template của theme nhưng nó sẽ có vai trò chứa những đoạn mã PHP để khai báo các tính năng đặc biệt, hoặc sử dụng hàm add_theme_support() để khai báo các tính năng trong theme. Bạn hãy nhớ một điều rằng, functions.php không phải là template nên nó sẽ không hiển thị ra bên ngoài nhưng mà nó sẽ được thực thi, và tất cả code PHP trong đây sẽ được thực thi khi website được tải ra.

index.php – Template gốc của theme

Tập tin index.php không chỉ là template để sử dụng cho trang chủ, mà nó còn là template gốc của website nếu như các template khác chưa được khai báo. Ví dụ nếu theme của bạn không có tập tin single.php để làm template cho trang nội dung của Post, thì nó sẽ sử dụng tập tin index.php để hiển thị. Các template khác cũng vậy.

header.php – Phần đầu của theme

Template này không bắt buộc nhưng nên sử dụng để khai báo phần header của trang, bao gồm các thẻ như <html>, <head>, <body>,…Và sau đó ở các template khác, chúng ta sẽ gọi nó ra bằng template tag get_header().

footer.php – Phần chân trang của theme

Nó cũng giống như header.php đó là được sử dụng để khai báo phần chân trang của theme. Rồi sau đó ở các template khác ta sẽ gọi nó ra bằng get_footer().

sidebar.php – Phần hiển thị sidebar

Bạn có thể khai báo sidebar trực tiếp vào các template khác với hàm dynamic_sidebar() nhưng nếu bạn sử dụng sidebar ở nhiều template khác nhau thì bạn nên viết code hiển thị sidebar vào tập ti sidebar.php. Rồi sau đó sẽ dùng hàm get_sidebar() để gọi template này ra.

Các template khác trong theme

Các template dưới đây nó sẽ không bắt buộc bạn phải tạo ra như 3 tập tin ở trên, nhưng nó sẽ được sử dụng nếu bạn có khai báo. Template nào không khai báo thì nó sẽ sử dụng template cấp cao hơn. Ví dụ nếu single-123.php không khai báo thì nó sẽ sử dụng single.php.

Template hiển thị trang lưu trữ

Template này sẽ sử dụng cho tất cả các trang lưu trữ trên website. Trang lưu trữ là các trang phân loại bài viết như category, tag, custom taxonomy,…

  • archive.php – Định dạng hiển thị cho toàn bộ trang lưu trữ trên website như lưu trữ theo ngày tháng, category, tag, custom taxonomy,..
    • category.php – Định dạng hiển thị cho toàn bộ category của website.
      • category-tin-tuc.php – Định dạng hiển thị trang category có slug là tin-tuc.
      • category-123.php – Định dạng hiển thị cho category mang ID 123.
    • tag.php – Định dạng hiển thị toàn bộ tag của website.
      • tag-tin-tuc.php – Định dạng hiển thị toàn bộ tag có slug là tin-tuc.
      • tag-123.php – Định dạng hiển thị toàn bộ tag có ID là 123.
    • author.php – Định dạng hiển thị cho trang toàn bộ các tác giả trong website.
      • author-thachpham.php – Định dạng trang hiển thị tác giả tên thachpham.
      • author-123.php – Định dạng trang hiển thị tác giả có ID là 123.
    • archive-product.php – Định dạng trang hiển thị danh sách các bài viết thuộc post type tên product.
  • taxonomy-product-category.php – Định dạng trang hiển thị danh sách các bài viết thuộc custom taxonomy tên product-category.
Template hiển thị trang nội dung

Template này sẽ định dạng cho trang hiển thị nội dung của Post hoặc Page hoặc một Custom Post Type nào đó.

  • single.php – Định dạng trang hiển thị nội dung của tất cả các Post.
    • single-product.php – Định dạng trang hiển thị nội dung tất cả các post trong post type tên product.
    • single-hello.php – Định dạng trang hiển thị nội dung của post có slug là hello.
    • single-123.php – Định dạng trang hiển thị nội dung của post mang ID là 123.
  • page.php – Định dạng hiển thị toàn bộ Page trong website.
    • page-123.php – Định dạng hiển thị page có ID là 123.
Template trang chủ

Các template này sẽ được sử dụng cho việc định dạng hiển thị của trang chủ.

  • index.php
    • front-page.php
      • home.php
Template trang 404

Template này sẽ hiển thị lỗi 404 trong website, và nó chỉ có 1 tập tin duy nhất là 404.php.

Template trang kết quả tìm kiếm

Khi sử dụng chức năng tìm kiếm trên website, kết quả tìm kiếm sẽ được hiển thị bằng template search.php. Nếu search.php không tồn tại thì nó sẽ dùng archive.php.

Tài nguyên tham khảo

  • Template Hierarchy – WordPress Developer
  • wphierarchy.com

Tips: Nếu bạn mới làm quen với template trong WordPress, hãy tập tuỳ biến một theme có sẵn thay vì lao vào tạo theme riêng. Nếu bạn học, hãy nên sử dụng các theme miễn phí hoặc theme mặc định.

Tìm hiểu về Template Tag

Nếu các tập tin template là những tập tin đại diện cho trang hiển thị các thành phần trong website thì template tag là những hàm được sử dụng để hiển thị một thành phần đặc biệt trong template. Các template tag bạn có thể sử dụng bằng cách lồng vào những thẻ HTML để nó hiển thị.

Các template tag là hàm PHP nên nó sẽ phải được nằm trong cặp thẻ <?php ?> của ngôn ngữ PHP.

Trong khi danh sách template tags có trong WordPress rất nhiều, mình chỉ nói qua một số template tag thường gặp nhất và cũng là quan trọng nhất.

Nhắc lại: Template Tag là những hàm PHP được sử dụng trong template.

Toàn bộ các template tag trong WordPress đều được khai báo ở các tập tin sau:

  • wp-includes/general-template.php
  • wp-includes/author-template.php
  • wp-includes/bookmark-template.php
  • wp-includes/category-template.php
  • wp-includes/comment-template.php
  • wp-includes/link-template.php
  • wp-includes/post-template.php
  • wp-includes/post-thumbnail-template.php
  • wp-includes/nav-menu-template.php

Vòng lặp (Loop)

Đây không được gọi là template tag nhưng nó là một phần quan trọng được sử dụng thường xuyên trong các template để có thể hiển thị thông tin của. Vòng lặp là mệnh đề while() trong PHP được sử dụng để tạo ra chu kỳ hiển thị toàn bộ nội dung trong một trang nhất định (như tiêu đề trang, nội dung,…).

Vòng lặp trong WordPress thường được sử dụng kèm với mệnh đề if() để tránh việc thực thi vòng lặp khi truy vấn ở trang hiện tại không có dữ liệu. Vòng lặp thường có cấu trúc như sau:


<?php
    if( have_posts() ) :
        while( have_posts() ) :
            the_post();

            // Template tag hiển thị nội dung của trang ở đây.

        endwhile;
    endif;
?>

Về chi tiết ý nghĩa các hàm trong vòng lặp như have_posts() hoặc the_post() mình sẽ nói kỹ hơn ở bài sau.

Bây giờ bạn hãy thử mở tập tin page.php trong theme Twenty Fifteen, bạn sẽ dễ dàng thấy nó có một vòng lặp như sau.


<?php
// Start the loop.
while ( have_posts() ) : the_post();

    // Include the page content template.
    get_template_part( ‘content’, ‘page’ );

    // If comments are open or we have at least one comment, load up the comment template.
    if ( comments_open() || get_comments_number() ) :
        comments_template();
    endif;

// End the loop.
endwhile;
?>

Và vòng lặp này sẽ tạo chu kỳ thực thi hàm get_template_part() và các thành phần khác bên trong để hiển thị nội dung của một page.

Hàm nối get_template_part()

Một trong các template tag được sử dụng nhiều nhất nhưng nhiều bạn cũng khó hiểu nhất đó chính là get_template_part(). Đây là hàm trong WordPress được sử dụng để nối nội dung của một tập tin PHP nào đó vào vị trí hiện tại mà hàm này đang được khai báo.

Ví dụ trong Twenty Fifteen nó sử dụng hàm get_template_part() như sau:

get_template_part( ‘content’, ‘page’ );

Có nghĩa là nó nối tập tin content-page.php có trong cùng thư mục vào vị trí nó được khai báo. Sở dĩ nó phải sử dụng hai tham số thay vì một tham số như vậy là để giúp lập trình viên dễ dàng quản lý các tập tin dựa theo slug (tham số content) và tên template (tham số page).

Như vậy bạn có thể hiểu, thay vì họ viết toàn bộ code của tập tin content-page.php vào vị trí đó thì họ sẽ tách nó ra một tập tin riêng nhằm có thể tái sử dụng lại trong các template khác hoặc cho dễ dàng quản lý code trong theme.

Ngoài ra, nó cũng có thể được sử dụng để nối một tập tin nào đó trong một thư mục nào đó. Ví dụ dưới đây là nối tập tin /part/content-single.php

get_template_part( ‘part/content’, ‘single’ );

Template Tags tổng hợp

Các template tags này thường không đại diện cho một chức năng cụ thể nào.

  • get_header() – Nối tập tin header.php trong theme.
  • get_sidebar() – Nối tập tin sidebar.php trong theme.
  • get_footer() – Nối tập tin footer.php trong theme.
  • bloginfo() & get_bloginfo() – Hiển thị thông tin của website.
  • wp_head() – Hook mặc định của WordPress để hiển thị các thành phần trong thẻ <head>.
  • wp_footer() – Hook mặc định của WordPress để sử dụng ở footer.
  • wp_nav_menu() – Hiển thị một Menu Location.
  • dynamic_sidebar() – Hiển thị một sidear.

Template Tags cho Post

  • the_permalink() – Hiển thị permalink của post hiện tại trong truy vấn.
  • the_title() – Hiển thị tiêu đề post hiện tại trong truy vấn.
  • the_content() – Hiển thị toàn bộ nội dung của post hiện tại trong truy vấn.
  • the_excerpt() – Hiển thị excerpt hoặc một phần đầu nội dung của post hiện tại trong truy vấn.
  • the_ID() – Hiển thị ID của post hiện tại trong truy vấn.
  • the_tags() – Hiển thị các tag có trong post hiện tại trong truy vấn.
  • the_date() – Hiển thị ngày đăng post hiện tại trong truy vấn.
  • the_category() – Hiển thị các category của post hiện tại trong truy vấn.
  • post_class() – Hiển thị các class HTML đặc trưng của post hiện tại trong truy vấn.

Template Tags cho ảnh thumbnail của Post

  • has_post_thumnail() – Kiểm tra xem post hiện tại trong truy vấn có thiết lập thumbnail (Featured Image) hay không.
  • the_post_thumbnail() – Hiển thị ảnh thumbnail của post hiện tại trong truy vấn.

Template Tags cho Category và Tag

Các template tags này sẽ sử dụng cho template archive.php trở xuống.

  • category_description() – Hiển thị mô tả của category.
  • tag_description() – Hiển thị mô tả của tag.
  • wp_dropdown_categories() – Hiển thị danh sách category với dạng dropdown.
  • single_cat_title() – Hiển thị tên category trong truy vấn.
  • single_tag_title() – Hiển thị tên tag trong truy vấn.
  • wp_tag_cloud() – Hiển thị mây thẻ.

Lời kết

Yeah, vậy bạn đã hiểu thế nào là cấu trúc template trong theme WordPress và những đoạn code bên trong đó (đa phần là template) chưa? Rất đơn giản phải không nào, thật ra  để hiểu template trong WordPress rất đơn giản, bạn chịu khó xem hướng dẫn của mình trong bài này cùng với việc thường xuyên vọc mã nguồn của theme là sẽ nhanh chóng hiểu thôi.

Ở bài sau, mình sẽ giải thích cho bạn về thuật ngữ truy vấn (query) vốn mình đã nói nhiều trong bài này, ở bài đó bạn sẽ hiểu thêm về template nữa.

Xem tiếp bài trong serie

Phần trước: Tìm hiểu cách vận hành của mã nguồn WordPressPhần kế tiếp: Sử dụng WP Query và Loop (vòng lặp) để lấy bài viết

Học Wordpress

Tìm hiểu cách vận hành của mã nguồn WordPress

58

Bài này thuộc phần 3 của 10 phần trong serie WordPress nâng cao


Trước khi chúng ta nhảy vào làm việc với WordPress nâng cao như tiếp cận WordPress Core và sử dụng nó, thì ít nhất chúng ta nên hiểu qua về cách mã nguồn WordPress làm các việc như xử lý dữ liệu, tiếp nhận request truy cập (khi ai đó truy cập hoặc làm một thao tác gì đó trên website được gọi là 1 request). Việc hiểu những khái niệm căn bản này rất có ích cho các bạn biết rõ thật sự WordPress là cái gì, chúng ta có thể làm được gì trong WordPress.

Nhưng bây giờ, chúng ta nên tự hỏi rằng mã nguồn WordPress có thể làm gì? Điểm danh sơ qua, ta thấy nó có thể làm:

  • Blog cá nhân.
  • Trang tin tức, tạp chí.
  • Trang bán hàng.
  • Trang giới thiệu bất động sản.
  • Trang rao vặt.
  • Portfolio điện tử.
  • ….

Nhưng chúng ta có cảm thấy là các loại website trên đều có một điểm chung là lưu trữ nội dung nhập vào, quản lý nội dung và cho phép người truy cập xem nội dung không? Chúng ta gọi chung nó là CMS – Content Management System (hệ thống quản trị nội dung). Và WordPress là một mã nguồn PHP thuộc loại CMS.

Các dữ liệu làm việc thế nào?

Trong mã nguồn WordPress, nó đã được lập trình nhiều tính năng giúp bản thân nó có thể tương tác với cơ sở dữ liệu (database) như MySQL để giúp người sử dụng có thể lưu trữ dữ liệu mềm trên website. Tất cả các dữ liệu mềm được lưu trữ vào database sẽ bao gồm các nội dung văn bản được nhập vào website, các thiết lập (vì các thiết lập sẽ lưu dưới dạng một kiểu dữ liệu) và một số dữ liệu linh ta linh tinh khác.

Nếu các bạn có vào xem database thông qua phpMyAdmin hoặc các ứng dụng tương tự, bạn sẽ thấy WordPress có nhiều bảng dữ liệu để chứa các dữ liệu được lưu vào

wp-database-table

Rồi sau đó, các tính năng trong mã nguồn sẽ tương tác với các bảng dữ liệu đó và đưa ra ngoài trình duyệt hiển thị dưới dạng HTML thông qua các tập tin đã được thiết lập khuôn mẫu trong theme (ta gọi là template). Những cái này có thể bây giờ bạn chưa hiểu nhưng từ từ bạn sẽ hiểu nó trong serie này.

Xem thêm: Cấu trúc database của WordPress và cách tối ưu

WordPress làm gì mỗi khi có người truy cập vào website?

Khi một người truy cập vào website, WordPress sẽ tự động xử lý theo quy trình sau:

Bước 1 – Khởi động mã nguồn

Tập tin index.php trong mã nguồn (không phải của theme hay plugin) được tải ra, sau đó nó sẽ truy xuất các tập tin cốt lõi khác như wp-config.php vốn để kết nối đến cơ sở dữ liệu, wp-settings.php,…. Bạn có thể mở tập tin index.php lên xem và lần mò theo các tập tin được nhúng vào sẽ biết được quy trình nó load theo thứ tự các tập tin.

Ở bước này, WordPress sẽ kết nối đến cơ sở dữ liệu được thiết lập trong wp-config.php, sau đó sẽ tiến hành tải những tính năng trong mã nguồn như /wp-include/functions.php, /wp-include/options.php,…nhằm nạp sẵn các chức năng cần thiết để có thể tiếp nhận những dữ liệu.

Và cũng trong bước này, toàn bộ các dữ liệu được lưu vào bảng wp_options có giá trị ở cột autoloadtrue sẽ được lôi ra hết, dù thiết lập đó có được sử dụng hay không. Mục đích của bước này là mang sẵn các tuỳ chọn của website cùng các plugin để hỗ trợ cho các bước sau, đặc biệt là bước tải plugin để nó làm việc chính xác. Đó là lý do tại sao ở bài tối ưu bảng wp_options, mình có khuyên bạn nên xoá bớt các hàng dữ liệu không dùng đến ở bảng này để giảm thời gian tải.

Bước 2 – Kích hoạt plugin

Các plugin mà bạn đang kích hoạt trong website sẽ được tải ra ngay sau khi mã nguồn WordPress khởi động xong. Bởi vì các tính năng trong WordPress Core được sử dụng trong plugin thường sẽ được gắn vào hook init (bạn tạm thời hiểu nó là một điểm neo để kích hoạt kịch bản nào đó) nên nó sẽ load ngay sau khi WordPress khởi động là vậy.

Bước 3 – Thực thi tập tin functions.php trong theme

Lúc này, WordPress sẽ tiến hành dò tìm đến tập tin functions.php trong theme đang được kích hoạt để tải các tính năng mà người tạo ra theme đã khai báo ở đó. Vậy làm sao WordPress có thể hiểu được website đang dùng theme nào? Đó là ở bước 1, nó đã kết nối vào database và dựa theo khoá current_theme trong cột option_name tại bảng wp_options.

WordPress xác định thêm hiện tại thông qua database

WordPress xác định thêm hiện tại thông qua database

Bước 4 – Phân tích truy vấn và khởi tạo truy vấn

Đây là bước quan trọng để website của bạn có thể hiển thị nội dung ra bên ngoài, vì các nội dung sẽ được trả về sau khi các truy vấn gửi vào database. Nếu bạn muốn biết nó phân tích như thế nào thì xem tại đây.

Truy vấn nghĩa là một mệnh lệnh được gửi vào database nhằm lấy các thông tin mà truy vấn đó cần xem. Truy vấn ở đây là truy vấn SQL gửi vào MySQL Server.

Trước tiên, WordPress sẽ chạy hàm wp() được thiết lập trong /wp-include/functions.php vốn để gọi phương thức $wp->main() cho mục đích thiết lập truy vấn. Đối tượng $wp được tạo ra bởi lớp WP trong /wp-include/class-wp.php.


/**
 * Set up the WordPress query.
 *
 * @since 2.0.0
 *
 * @param string|array $query_vars Default WP_Query arguments.
 */
function wp( $query_vars = ” ) {
    global $wp, $wp_query, $wp_the_query;
    $wp->main( $query_vars );

    if ( !isset($wp_the_query) )
        $wp_the_query = $wp_query;
}

Lúc này, phương thức $wp->parse_request() sẽ được khởi động cho mục đích phân tích truy vấn dựa theo đường dẫn của website. Vì bạn biết rằng WordPress sẽ tự động sinh truy vấn dựa theo đường dẫn, ví dụ khi chúng ta vào http://domain.com/?p=123 thì WordPress sẽ gửi một truy vấn vào database để lấy dữ liệu của post mang số ID là 123.

Sau khi truy vấn được phân tích, WordPress sẽ làm việc tiếp theo là thiết lập các hàm điều kiện thông qua phương thức $wp_query->parse_query(). Sau đó nó sẽ chuyển các truy vấn đã được tạo ra thành truy vấn bằng các lệnh SQL nhằm gửi đến MySQL để lấy dữ liệu bài viết bằng phương thức $wp_query->get_posts(). Nếu database có dữ liệu, các bài viết sẽ được lấy về sau khi gửi truy vấn và nó sẽ được lưu vào đối tượng $wp_query để nó sử dụng trong các vòng lặp cho việc hiển thị bài viết.

Trong quá trình gửi truy vấn này, nếu nó không tìm thấy dữ liệu thì sẽ phân tích và hiển thị báo lỗi 404.

Và cuối cùng là nó có dữ liệu, thì nó sẽ thiết lập biến $post để sử dụng trong vòng lặp. Biến $post là đối tượng chứa các dữ liệu của bài viết thông qua các thuộc tính. Phần này chúng ta sẽ đào sâu hơn ở phần tìm hiểu sâu về query và vòng lặp.

Bước 5 – Thực thi các tập tin khuôn mẫu (template) trong theme

Sau khi nó đã có dữ liệu bài viết và các dữ liệu liên quan mà nó đã làm ở bước 4, thì nó sẽ tiến hành xử lý các tập tin template của theme thông qua cấu trúc template. Sau đó các nội dung và trang chủ của website sẽ được hiển thị dựa theo các template tags dưới dạng HTML. Phần này chúng ta sẽ tìm hiểu kỹ hơn ở bài sau.

Chúng ta có thể can thiệp gì vào mã nguồn WordPress?

Một câu hỏi được đặt ra, chúng ta có thể làm gì để can thiệp vào mã nguồn WordPress nhằm điều khiển nó hoạt động theo ý mình, hoặc hiểu theo cách khác là tạo thêm tính năng và thay đổi giao diện hiển thị.

Không phải tự nhiên mà mình kể chi tiết ra quy trình WordPress xử lý dữ liệu ra ở trên, mà nó sẽ giúp bạn dễ hiểu hơn ở phần này.

Trước tiên, chúng ta có thể can thiệp vào các tính năng của WordPress và tái tạo lại nó vốn đã được WordPress xử lý ở bước 1 như trên. Sở dĩ chúng ta có thể làm được là vì mã nguồn của WordPress được viết theo kiểu chúng ta có thể can thiệp gián tiếp vào nó và có thể tái tạo lại (thông qua các lớp – Class). Và các tính năng chúng ta tự tạo ra từ việc can thiệp vào mã nguồn có thể được khai báo với dạng plugin và nó sẽ được sử dụng ngay sau khi WordPress khởi động các chức năng cần thiết.

Thứ hai, chúng ta có thể can thiệp vào lớp WP_Query để tự tạo một truy vấn riêng để lấy dữ liệu bất kỳ trong database (nhiều truy vấn có thể sử dụng bằng một hàm nào đó, như get_post_meta() chẳng hạn). Chúng ta ứng dụng WP_Query nhiều nhất vào việc lấy dữ liệu các bài viết (bao gồm post, page, attachment,…).

Thứ ba, chúng ta có thể tạo ra theme, sau đó tự định tuỳ chỉnh lại các tập tin template trong đó để các nội dung của WordPress hiển thị ra theo đúng ý đồ của mình. Vì sau khi WordPress gửi truy vấn lấy dữ liệu, thì việc hiển thị ra thế nào là do các template quyết định, và trong template sẽ là các mã PHP kết hợp với HTML/CSS để hiển thị nó ra website.

Đó là những việc chúng ta có thể làm.

Vậy làm như thế nào?

Câu hỏi hay đó, chúng ta đã biết qua cách WordPress tải như thế nào khi có lượt truy cập đi vào, rồi tuần tự các chức năng được thực thi ra và biết luôn các việc chúng ta có thể làm. Còn làm như thế nào, chúng ta sẽ tìm hiểu ở các phần sau trong serie Học WordPress nâng cao này.

Xem tiếp bài trong serie

Phần trước: Tra cứu WordPress với WordPress CodexPhần kế tiếp: Cấu trúc Template trong theme và Template Tag

Học Wordpress

Cách sử dụng Action Hook trong WordPress

50

Bài này thuộc phần 6 của 10 phần trong serie WordPress nâng cao

Trong mã nguồn WordPress, ngoài việc nắm vững WP Query để hiểu cách nó lấy nội dung như mình đã trình bày ở phần trước thì một trong các tính năng cực kỳ quan trọng khác để bạn “giao tiếp” với mã nguồn của nó đó chính là Action Hook, trong bài này mình sẽ nói chi tiết về action hook nhiều nhất có thể.

Action Hook là gì?

Như trong bài 2 mình đã có nói qua về quy trình WordPress xử lý mỗi khi có một lượt truy cập vào. Và Action Hook chính là một điểm neo để chúng ta thực hiện một hành động gì đó tại một chu kỳ nhất định.

Ví dụ bạn muốn đoạn script của chúng ta sẽ thực thi sau khi mã nguồn đã được tải để tránh việc bị lỗi do sử dụng một số thành phần trong mã nguồn thì chúng ta sẽ móc đoạn script đó vào hook init trong WordPress.

Cách sử dụng một Action Hook

Để sử dụng Action Hook, chúng ta sẽ phải tạo ra một hàm chứa đoạn script PHP cần chạy (gọi là callback function), sau đó sử dụng hàm add_action() trong WordPress để móc cái callback của mình vào cái action hook cần cho nó móc vào. Ví dụ dưới đây là mình sẽ chạy một hàm móc vào hook init.


function thachpham_theme_setup(){
    // PHP Script here
}
add_action( ‘init’, ‘thachpham_theme_setup’ )

Và đây không phải là template tag, nên bạn sẽ chèn nó ở functions.php trong theme hoặc trong plugin của bạn.

Cấu trúc sử dụng của hàm add_action() là:

add_action( $hook, $function_to_add, $priority, $accepted_args );

Trong đó:

  • $hook (string) (bắt buộc) – Tên hook cần móc vào.
  • $function_to_add (callback) (bắt buộc) – Tên hàm cần sử dụng.
  • $priority (integer) (tuỳ chọn) – Mức độ ưu tiên của hàm này thực thi với các hàm khác nếu nó có chung một hook. Mặc định là 10, số càng nhỏ thì nó càng thực hiện sớm hơn.
  • $accepted_args (integer) (tuỳ chọn) – Số lượng tham số được sử dụng trong hàm callback. Mặc định là 1.

Action Hook được tạo ra thế nào?

Action Hook được tạo ra bằng hàm do_action(), hàm này chỉ đơn giản là khai báo một điểm neo ngay tại vị trí của nơi nó cần thực thi. Do tính chất của nó chỉ là khai báo điểm neo nên nó có thể sử dụng như tạo điểm neo hành động trong một chu kỳ nào đó, hoặc bạn có thể chèn thêm một cái gì đó vào ngay tại vị trí của điểm neo.

Ví dụ bạn có thể khai báo một action hook tên thachpham_before_content trong template ở vị trí bất kỳ với đoạn code sau (đặt vào template của theme):

<?php do_action( ‘thachpham_before_content’ ); ?>

Và bây giờ, nếu bạn muốn chèn một cái gì đó hoặc thực thi cái gì đó ngay tại vị trí mà bạn đã chèn hook thachpham_before_content thì chỉ cần móc nó vào một hàm callback nào đó là được.

Một số ví dụ Action Hook trong WordPress

Bạn đã biết Action Hook là gì rồi và cách sử dụng cơ bản của nó, bây giờ chúng ta cùng thực hành một số action hook thông dụng trong WordPress nhé. Bạn có thể tham khảo danh sách action hook trong WordPress để biết thêm.

pre_get_posts

Đây là hook mà bạn sẽ sử dụng nếu như bạn cần thay đổi lại tham số của truy vấn ở một trang nào đó bằng hàm callback của mình. Hook này được gọi ra sau khi truy vấn mặc định của WordPress được tạo ra nhưng trước khi truy vấn được chạy. Hook này thường được sử dụng kèm với đối tượng $query để sửa lại tham số của truy vấn hay làm việc gì đó để thao tác với truy vấn mặc định.

Ví dụ mình muốn ở trang lưu trữ của WordPress sẽ có truy vấn lấy bài viết ngẫu nhiên thì mình sẽ kết hợp với các hàm điều kiện của WordPress và phương thức $query->set() trong hook này.

Các hàm điều kiện khi dùng trong hook này sẽ phải viết dưới dạng phương thức của $query. Ví dụ: $query->is_home().


function thachpham_modify_archive_query( $query ) { // khai báo biến cần sử dụng trong callback

    if( $query->is_archive() && $query->is_main_query() ) : // is_main_query được sử dụng để tránh nó can thiệp vào truy vấn không phải mặc định
        $query->set(‘orderby’, ‘rand’); // orderby=rand => sắp xếp bài ngẫu nhiên
        $query->set(‘posts_per_page’, ‘1’); // posts_per_page=1 => hiển thị 1 bài mỗi trang
    endif;
    
}
add_action( ‘pre_get_posts’, ‘thachpham_modify_archive_query’ );

Như vậy chúng ta đã làm thành công việc tuỳ biến query ở mỗi trang mà không cần chạm vào mã nguồn, hay phải không nào?

wp_head

Hook này sẽ được sử dụng nếu như bạn muốn chèn một cái gì đó vào cặp thẻ <head> của theme mà không cần sửa template của theme.


function thachpham_author_tag(){
    echo "<link rel="author" href="https://thachpham.com" />n";
}
add_action( ‘wp_head’, ‘thachpham_author_tag’ );

Nếu bạn cần chèn vào footer thì có hook là wp_footer.

Lời kết

Trong bài viết này, có lẽ bạn đã nắm được khá nhiều các kiến thức về add_action trong WordPress rồi đó và mặc định nó cũng chỉ có như vậy thôi, nhưng về sau nếu bạn viết plugin thì tính năng này cực kỳ hữu ích. Hoặc khi bạn sử dụng các theme framework nó cũng sử dụng action hook rất nhiều.

Ở bài sau, chúng ta sẽ tìm hiểu thêm một loại hook nữa gọi là Filter Hook.

Xem tiếp bài trong serie

Phần trước: Sử dụng WP Query và Loop (vòng lặp) để lấy bài viếtPhần kế tiếp: Cách dùng Filter Hook trong WordPress

Học Wordpress

Thêm trường dữ liệu (custom field) cho bài viết

50

Bài này thuộc phần 8 của 10 phần trong serie WordPress nâng cao


Một trong số các tính năng mạnh mẽ trong WordPress có thể giúp các lập trình viên có thể thêm nhiều tính năng hay trong các bài viết trong WordPress, đó là tính năng Custom Field. Hầu hết hiện nay chúng ta không sử dụng custom field độc lập nhưng hiểu custom field là nền tảng quan trọng để sau này bạn tìm hiểu thêm Meta Boxes hoặc các plugin thông dụng như Advanced Custom Field.

Custom Field là gì?

Giải thích ngắn gọn thì đó là một dữ liệu bổ sung để thêm vào các bài viết (Post, Page). Nghĩa là chúng ta có thể thêm một cột dữ liệu trong mỗi bài viết để nó mang một giá trị tương ứng. Ví dụ như mặc định WordPress chỉ hỗ trợ nhập tiêu đề bài viết, nhưng với Custom Field bạn có thể thêm một trường dữ liệu kiểu như Tiêu đề phụ chẳng hạn.

Hướng dẫn ứng dụng Custom Field

Các bạn vào Posts -> Add New và nhìn xuống dưới sẽ thấy cái khung Custom Field này.

wordpress-custom-field

Nếu không thấy thì các bạn nhìn tít lên trên, bấm vào chữ Screen Options và tick dấu vào Custom Field.

Hướng dẫn custom field trong WordPressBây giờ các bạn thử thêm Meta Key (tên địa diện của field) với Value (giá trị của field) như sau:

Thêm custom field và giá trị của nó vào bài

Thêm custom field và giá trị của nó vào bài

Thêm xong nhớ ấn nút Add Custom Field.

Trong đó,

  • tp_country : Là tên đại diện của field của bạn.
  • Sweden : Giá trị của field.

Ok, vậy là chúng ta đã hoàn tất việc khai báo xong các meta key và giá trị của nó.

Dữ liệu custom field lưu vào đâu?

Các dữ liệu từ custom field sẽ được lưu lại thành các Post Metadata và nằm trong bảng wp_postmeta trong database (xem ở các trang cuối).

wordpress-custom-field-databaseTrong đó, bạn sẽ thấy tên key (meta_key), ID của bài viết chưa key (post_id) và giá trị của nó (meta_value). Và khi bạn dùng field này cho nhiều bài viết khác nhau thì nó cũng sẽ có thêm nhiều hàng dữ liệu có meta_key giống nhau nhưng sẽ có post_id khác nhau.

Các hàm hiển thị giá trị custom field

Nếu bạn muốn lấy giá trị của field nào đó trong bài viết ra hiển thị bên ngoài (như template single.php chẳng hạn) thì bạn có thể sử dụng nhiều hàm khác nhau.

get_post_meta()

Hàm này thích hợp sử dụng nếu bạn cần lấy giá trị của một field nào đó dựa vào Post ID đang chứa field.

Cách sử dụng: get_post_meta( $post, $meta_key, $single )

Trong đó,

  • $post: Là ID của bài viết cần lấy custom field.
  • $meta_key: tên key của field cần lấy trong bài viết. Mặc định sẽ lấy toàn bộ field có trong post.
  • $single: Tuỳ chọn hiển thị một giá trị hay một mảng giá trị. Mặc định là false (hiển thị mảng).

Ví dụ mình muốn hiển thị giá trị của field tp_country trong bài hiện tại thì sẽ đặt đoạn code sau vào single.php (có thể đặt ở các template khác bất kỳ, miễn là lấy được ID của bài viết cần lấy field).


        <?php
            $tp_country = get_post_meta( $post->ID, ‘tp_country’, true );
            
            if( $tp_country ) { // kiểm tra xem nó có dữ liệu hay không
                echo ‘Country: ‘ . $tp_country . ‘</br>’;
            }
        ?>

the_meta()

Nếu bạn cần đơn giản là in ra toàn bộ meta key và meta value của tất cả các field có trong bài viết và hiển thị dưới dạng danh sách bằng HTML thì sẽ sử dụng hàm này, hàm này không có tham số, sử dụng như là một template tags.

get_post_custom()

Hàm này thích hợp nếu bạn cần lấy ra toàn bộ meta key và meta value của bài viết hiện tại (hoặc bài viết bất kỳ dựa vào ID), kết quả trả về là dạng mảng lồng nhau.

Cách sử dụng: get_post_custom( $post_id )

Nếu $post_id không được khai báo thì nó sẽ lấy ID của bài viết hiện tại.


        <?php
            $tp_field = get_post_custom();
            
            echo ‘<pre>’;
            print_r( $tp_field );
            echo ‘</pre>’;
            
        ?>

Ngoài các hàm trên thì còn có get_post_custom_values()get_post_custom_keys() nhưng mình thấy nó không thông dụng cho lắm vì chỉ cần 3 hàm ở trên là đã rất linh hoạt rồi.

Các hàm thao tác với custom field

Ngoài việc hiển thị ra, bạn cũng có thể sử dụng một số hàm riêng biệt để hỗ trợ thêm, sửa hoặc xoá custom field trong database mà không cần thao tác thông qua việc sửa bài viết. Thông thường các hàm này sẽ có ích khi bạn dùng nó trong các action hook của WordPress.

update_post_meta()

Đây là hàm nên sử dụng nếu bạn cần cập nhật một giá trị mới vào meta key nào đó, và nếu meta key cần cập nhật chưa tồn tại cho post thì nó sẽ tự tạo thêm.

Cách sử dụng: update_post_meta( $post_id, $meta_key, $meta_value, $prev_value )

Trong đó,

  • $post_id : ID của bài viết cần cập nhật key.
  • $meta_key : Tên key cần cập nhật dữ liệu.
  • $meta_value : Dữ liệu cần cập nhật vào.
  • $prev_value : Dữ liệu cũ cần thay đổi thành dữ liệu mới. Không bắt buộc phải nhập vì mặc định nếu bạn khai báo $meta_value thì nó sẽ đổi tất cả các giá trị cũ thành mới. Sẽ có ích nếu một meta key có nhiều giá trị khác nhau.

Ví dụ:


// Đổi giá trị ‘tp_country’ của post_id là 15 sang giá trị ‘Viet Nam’
update_post_meta( 15, ‘tp_country’, ‘Viet Nam’ );

Ở hàm này, bạn có thể xem ví dụ ứng dụng làm tính năng lượt xem bài viết rất hay.

delete_post_meta()

Hàm này sẽ xoá toàn bộ dữ liệu trong một meta key nào đó hoặc xoá giá trị meta key. Cách sử dụng tương tự như update_post_meta().

Cách dùng: delete_post_meta( $post_id, $meta_key, $meta_value )

Trong đó,

  • $post_id : ID của bài viết cần xoá field.
  • $meta_key: Tên meta key cần xoá.
  • $meta_value: Tên giá trị cần xoá. Không bắt buộc, vì mặc định nó sẽ xoá toàn bộ giá trị. Nhưng nếu bạn có nhiều giá trị trong một field thì dùng cái này nếu cần giữ lại giá trị theo ý muốn.

Ví dụ sử dụng:


// Xoá toàn bộ giá trị trong key ‘tp_country’ của post_id là 15
delete_post_meta( 15, ‘tp_country’, ‘Viet Nam’ );

Lời kết

Như vậy là trong bài viết này bạn đã làm quen được với tính năng Custom Field trong WordPress, và đây là một tính năng vô cùng thú vị.

Trên thực tế khi làm việc với custom field, ít ai làm thủ công như thế này mà họ sẽ kết hợp với meta box để tạo thêm 1 số khung nhập liệu đẹp mắt dưới khung viết bài. Nếu bạn muốn tạo, có thể xem qua hướng dẫn ACF để làm nhé.

Xem tiếp bài trong serie

Phần trước: Cách dùng Filter Hook trong WordPressPhần kế tiếp: Cách tự tạo một Meta Box đơn giản toàn tập

Học Wordpress

Hướng dẫn tự tạo Widget

52

Bài này thuộc phần 10 của 10 phần trong serie WordPress nâng cao


Widget trong WordPress ai cũng hiểu nó là một block nội dung được đặt trong một khu vực được chỉ định, khu vực này ta thường gọi là Widget Area hoặc Sidebar. Ngoài các widget có sẵn như Recent Posts, Recent Comments,…thì nếu muốn có thêm widget bạn phải cài plugin hoặc một số theme cũng cho bạn thêm vài widget tùy chọn.

Vậy làm thế nào để hiểu quy trình tạo một widget ra sao? Ở bài này mình sẽ phân tích kỹ lưỡng cách tạo một widget là như thế nào, nhưng dĩ nhiên là bạn cần có sẵn kiến thức PHP ví dụ như bạn nên hiểu Class và đối tượng trong PHP là thế nào.

Khái niệm về cách tạo widget

Xem trước: Widgets API – WordPress Codex

Trong WordPress đã có sẵn một class tên là WP_Widget, trong class này có những method (phương thức), nghĩa là bạn phải viết các phương thức này theo chuẩn của nó, không được thiếu mà cũng không có thừa và phải viết đúng tên phương thức.

Trong class WP_Widget có tổng cộng 3 phương thức bắt buộc, bao gồm:

__construct: Phương thức khởi tạo này sẽ có nhiệm vụ khai báo tên widget, mô tả widget.

form: Phương thức này sẽ hỗ trợ bạn tạo các form nhập liệu bên trong một widget, xem hình dưới.

Mẫu form trong widget

Mẫu form trong widget

update: Phương thức này sẽ hỗ trợ bạn lưu dữ liệu mà người dùng đã nhập vào các form mà bạn đã tạo bằng phương thức form.

widget: Phương thức này sẽ giúp bạn gọi dữ liệu và hiển thị ra ngoài website khi bạn gắn cái widget này lên.

Ngoài ra, trong class này bạn cũng phải khai báo một phương thức nào đó do bạn tùy chọn để thiết lập tên và mô tả của widget. Một số thì dùng phương thức __construct() và một số thì tự tạo một phương thức khác. Ở đây mình chọn cách tự tạo phương thức vì nó dễ nhìn và dẽ hiểu hơn.

Chuẩn bị

Bạn có thể thực hành bài này bằng cách viết code vào file functions.php trong theme, nhưng tốt hơn hết là bạn tạo một plugin đi. Tạo một file với tên nào đó ở thư mục wp-content/plugins và viết đoạn này ở đầu file


<?php
/*
Plugin Name: Test Widget
Plugin URI: https://thachpham.com
Description: Thực hành tạo widget item.
Author: Thach Pham
Version: 1.0
Author URI: http://google.com
*/

Khỏi cần nói cũng biết, các code thực hành trong bài này bạn viết vào bên dưới dòng trên nhé.

6 bước tạo widget item

Bước 1. Khởi tạo widget

Đầu tiên, để khởi tạo một widget thì ta có 4 đoạn sau để khởi tạo.


/*
* Khởi tạo widget item
*/
add_action( ‘widgets_init’, ‘create_thachpham_widget’ );
function create_thachpham_widget() {
register_widget(‘Thachpham_Widget’);
}

Trong đó, Thachpham_Widget là class mà chút nữa chúng ta sẽ tạo.

Bước 2. Tạo class và cấu trúc các phương thức

Như mình đã nói, bây giờ chúng ta sẽ tạo một class mang tên Thachpham_Widget kế thừa cái class WP_Widget mặc định, trong đó sẽ có 3 phương thức bắt buộc là form, update, widget và kèm theo một phương thức để đặt tên cho widget. Ta có như sau.


/**
* Tạo class Thachpham_Widget
*/
class Thachpham_Widget extends WP_Widget {

/**
* Thiết lập widget: đặt tên, base ID
*/
function __construct() {

}

/**
* Tạo form option cho widget
*/
function form( $instance ) {

}

/**
* save widget form
*/

function update( $new_instance, $old_instance ) {

}

/**
* Show widget
*/

function widget( $args, $instance ) {

}

}

Mình đã có comment rõ ràng trong đó rồi nhé.

Bây giờ bạn thử lưu lại xem và có thấy phần Appearance -> Widget của mình xuất hiện thêm một cục không ghi tên như hình dưới không, nếu có thì bạn đã làm đúng.

create_widget_form_basic

Bước 3: Đặt tên cho widget (__construct)

Ở bước này, chúng ta sẽ làm việc trong phương thức __construct() nhé. Bây giờ ta sẽ tạo cho nó một cái mảng bao gồm các giá trị như sau:


function __construct() {
parent::__construct (
‘thachpham_widget’, // id của widget
‘ThachPham Widget’, // tên của widget

array(
‘description’ => ‘Mô tả của widget’ // mô tả
)
);
}

Trong đó, các thông tin mình đã có ghi chú thích vào trong đó rồi nhé.

Bây giờ chúng ta gắn cái biến này vào đoạn sau.

Bây giờ lưu lại và vào Appearance -> Widget tìm cái tên widget mà bạn vừa tạo ra nào.

Title và Description của widget

Title và Description của widget

Bước 4: Tạo form cho widget (form)

Bất kỳ widget nào cũng nên có một form nhập liệu để khách nhập những tùy chọn hay giá trị nào đó vào đây, bạn có thể sử dụng dropdown, checkbox,…nhưng ở đây mình sẽ dùng input loại text cho đơn giản.

Trong bước này ta sẽ làm việc trong phương thức form() nhé. Phương thức này ta có một biến là $instance.

Đầu tiên ra khai báo một mảng như sau:


//Biến tạo các giá trị mặc định trong form
$default = array(
‘title’ => ‘Tên của bạn’
);

Mảng này có vai trò thiết lập các giá trị mặc định cho từng form. Ví dụ bạn có một form tên title thì giá trị mặc định của nó nếu người dùng chưa nhập vào là Tên của bạn, nếu bạn có nhiều form thì làm thêm nhiều giá trị trong mảng này.

Kế tiếp là viết thêm đoạn này


//Gộp các giá trị trong mảng $default vào biến $instance để nó trở thành các giá trị mặc định
$instance = wp_parse_args( (array) $instance, $default);

Đoạn này bạn hiểu đơn giản là nó sẽ lôi toàn bộ giá trị mảng của biến $default sang biến $instance.

Tiếp tục viết thêm một đoạn này


//Tạo biến riêng cho giá trị mặc định trong mảng $default
$title = esc_attr( $instance[‘title’] );

Đơn giản là ta đưa $instance['title'] vào một biến cho dễ nhớ, dễ viết. Trong đó, $title là biến sẽ chứa giá trị của tiêu đề lấy từ khóa title trong mảng $instance.

Và cuối cùng là đoạn quan trọng nhất, chúng ta sẽ tạo ra một cái trường nhập liệu và nó sẽ hiển thị giá trị là biến $title. Điều này có nghĩa là nếu như sau này chúng ta truyền giá trị mới cho $title thì nó cũng sẽ hiển thị ra.


//Hiển thị form trong option của widget
echo "Nhập tiêu đề <input class="widefat" type="text" name="’".$this->get_field_name(‘title’)."’ value=’".$title."’ />";

Bây giờ bạn lưu lại và mở widget ra sẽ thấy có một form và thuộc tính mặc định như sau:

create_widget_form_new

Bạn có thể thử bằng cách nhập một cái gì đó vào form rồi ấn Save lại thì thấy nó không được lưu lại mà toàn trả về giá trị mặc định. Đó là do chúng ta chưa viết code cho phương thức update.

Toàn bộ code trong bước này:


/**
* Tạo form option cho widget
*/
function form( $instance ) {
parent::form( $instance );

//Biến tạo các giá trị mặc định trong form
$default = array(
‘title’ => ‘Tiêu đề widget’
);

//Gộp các giá trị trong mảng $default vào biến $instance để nó trở thành các giá trị mặc định
$instance = wp_parse_args( (array) $instance, $default);

//Tạo biến riêng cho giá trị mặc định trong mảng $default
$title = esc_attr( $instance[‘title’] );

//Hiển thị form trong option của widget
echo "Nhập tiêu đề <input class="widefat" type="text" name="’".$this->get_field_name(‘title’)."’ value=’".$title."’ />";

}

Bước 5. Lưu giá trị khi nhập form (update)

Bước này ta sẽ làm việc với phương thức update(). Trong phương thức này ta có hai tham số chính là $new_instance được dùng để lưu những giá trị sau khi ấn nút Save và $old_instance là giá trị cũ trong cơ sở dữ liệu. Sau khi dữ liệu nhập vào được lưu thì ta sẽ return nó ra.

Ta có


$instance = $old_instance;
$instance[‘title’] = strip_tags($new_instance[‘title’]);
return $instance;

Nghĩa là ở trên mình sẽ lưu lại các giá trị trong form nhập tiêu đề. Hàm strip_tags() được sử dụng để cho cái form không thực thi PHP và HTML.

Toàn bộ code sẽ là


/**
* save widget form
*/

function update( $new_instance, $old_instance ) {
parent::update( $new_instance, $old_instance );

$instance = $old_instance;
$instance[‘title’] = strip_tags($new_instance[‘title’]);
return $instance;
}

Bây giờ bạn thử viết gì vào form rồi lưu lại, các giá trị sẽ lưu lại.

Bước 6. Xuất dữ liệu hiển thị ra ngoài

Ta đã tạo form, rồi lưu dữ liệu trong form vào. Vậy làm thế nào để có thể xuất nó hiển thị ra ngoài đây? Trong bước này ta sẽ làm việc với phương thức widget để hiển thị nó ra ngoài.

Trong phương thức này ta có 2 tham số là $args để khai báo các giá trị thuộc tính của một widget (title, các thẻ HTML,..) và $instance là giá trị mà khách đã nhập vào form trong widget.

Nếu bạn muốn sử dụng lại các thuộc tính bên trong widget thì tốt hơn hết bạn nên extract cái array trong widget ra thành từng biến riêng. Ta có:


extract( $args );

Sau đó, để hiển thị giá trị của một form thì ta chỉ cần echo $instance['form_name']. Như ví dụ này thì ta có $instance['title'].

Nhưng do cái form này là ta nhập tiêu đề của widget nên bạn nên thêm filter hook cho nó để đúng chuẩn trong WordPress.


echo apply_filters( ‘widget_title’, $instance[‘title’] );

Nhưng mà đợi đã, ta không thể viết chay như vậy, tại sao? Bởi vì trong Widget nó có những cái hook như hook vị trí trước widget (before widget), sau widget (after widget) và quan trọng là nếu bạn hiển thị cái tiêu đề widget như thế kia thì không được do ta thiếu hook $before_widget$after_widget, hai biến này là hook in ra thẻ heading để tiêu đề widget hiển thị đúng “phong cách”.

Như vậy, ta tạm đưa đoạn apply_filters() vào trong một biến:


$title = apply_filters( ‘widget_title’, $instance[‘title’] );

Sau đó ta viết như sau:


echo $before_widget;

//In tiêu đề widget
echo $before_title.$title.$after_title;

// Nội dung trong widget

echo "ABC XYZ";

// Kết thúc nội dung trong widget

echo $after_widget;

Như vậy, khi in widget ra bạn bắt buộc phải echo thêm biến $before_widget$after_widget để bọc nội dung lại, không có nó không có hiển thị đâu nhé.

Và kết quả là:

create_widget_show

Toàn bộ code trong bước này là:


function widget( $args, $instance ) {

extract( $args );
$title = apply_filters( ‘widget_title’, $instance[‘title’] );

echo $before_widget;

//In tiêu đề widget
echo $before_title.$title.$after_title;

// Nội dung trong widget

echo "ABC XYZ";

// Kết thúc nội dung trong widget

echo $after_widget;
}

Quá dễ phải không nào.

Tải source code

Thực hành – Tạo widget hiển thị bài ngẫu nhiên

Bạn đã biết cách tạo một widget là như thế nào rồi, vậy thì tại sao lại không thực hành nó ngay? Ở đây mình sẽ thực hành cách tạo một widget hiển thị bài viết ngẫu nhiên với tùy chọn cho phép khách nhập số lượng bài cần hiển thị bằng việc ứng dụng khái niệm Loop và Query.

</pre>
<pre>class Random_Post extends WP_Widget {

function __construct() {
parent::__construct(
‘random_post’,
‘Bài ngẫu nhiên’,
array( ‘description’ => ‘Widget hiển thị bài viết ngẫu nhiên’ )
);
}

function form( $instance ) {

$default = array(
‘title’ => ‘Tiêu đề widget’,
‘post_number’ => 10
);
$instance = wp_parse_args( (array) $instance, $default );
$title = esc_attr($instance[‘title’]);
$post_number = esc_attr($instance[‘post_number’]);

echo ‘<p>Nhập tiêu đề <input type="text" class="widefat" name="’.$this->get_field_name(‘title’).’" value="’.$title.’"/></p>’;
echo ‘<p>Số lượng bài viết hiển thị <input type="number" class="widefat" name="’.$this->get_field_name(‘post_number’).’" value="’.$post_number.’" placeholder="’.$post_number.’" max="30" /></p>’;

}

function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance[‘title’] = strip_tags($new_instance[‘title’]);
$instance[‘post_number’] = strip_tags($new_instance[‘post_number’]);
return $instance;
}

function widget( $args, $instance ) {
extract($args);
$title = apply_filters( ‘widget_title’, $instance[‘title’] );
$post_number = $instance[‘post_number’];

echo $before_widget;
echo $before_title.$title.$after_title;
$random_query = new WP_Query(‘posts_per_page=’.$post_number.’&orderby=rand’);

if ($random_query->have_posts()):
echo "<ol>";
while( $random_query->have_posts() ) :
$random_query->the_post(); ?>

<li><a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></li>

<?php endwhile;
echo "</ol>";
endif;
echo $after_widget;

}

}

add_action( ‘widgets_init’, ‘create_randompost_widget’ );
function create_randompost_widget() {
register_widget(‘Random_Post’);
}</pre>
<pre>

Lời kết

Như vậy là bạn đã biết qua cách tạo một widget là như thế nào rồi đúng không nào? Thoạt nhìn code có thể bạn nghĩ nó khó nhưng thật ra nó chẳng có gì khó cả và mình tin là bạn có thể tự làm được sau khi đọc kỹ bài của mình.

Nếu có gì thắc mắc, hãy comment phía dưới nhé.

Tham khảo: Cách tạo widget nhanh với scbFramework – WordPressKite

Xem tiếp bài trong serie

Phần trước: Cách tự tạo một Meta Box đơn giản toàn tập