<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>WordPress &#8211; Larry的午茶時光</title>
	<atom:link href="https://blog.yuyansoftware.com.tw/category/php/wordpress/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.yuyansoftware.com.tw</link>
	<description></description>
	<lastBuildDate>Sun, 08 Jan 2023 09:28:56 +0000</lastBuildDate>
	<language>zh-TW</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://blog.yuyansoftware.com.tw/wp-content/uploads/2022/10/favicon-45x45.png</url>
	<title>WordPress &#8211; Larry的午茶時光</title>
	<link>https://blog.yuyansoftware.com.tw</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>WordPress plugin development 外掛開發</title>
		<link>https://blog.yuyansoftware.com.tw/2017/11/wordpress-plugin-development/</link>
		
		<dc:creator><![CDATA[Larry]]></dc:creator>
		<pubDate>Mon, 20 Nov 2017 15:16:00 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">http://test234.yuyansoftware.com.tw/2017/11/20/wordpress-plugin-%e6%8f%92%e4%bb%b6%e9%96%8b%e7%99%bc/</guid>

					<description><![CDATA[Wordpress 開放 plugin/外掛給網站主做客製化開發，也訂定了一些寫法和規範。對 plugin/外掛開發有興趣的朋友，可以參考這篇文章。]]></description>
										<content:encoded><![CDATA[
<p>圖片來源 <a href="https://wordpress.org/" target="_blank" rel="noreferrer noopener" aria-label=" (在新分頁中開啟)">https://wordpress.org</a></p>



<p><a rel="noreferrer noopener" aria-label=" (在新分頁中開啟)" href="https://codex.wordpress.org/Writing_a_Plugin" target="_blank">https://codex.wordpress.org/Writing_a_Plugin</a><br><a href="https://developer.wordpress.org/plugins/plugin-basics/" target="_blank" rel="noreferrer noopener" aria-label=" (在新分頁中開啟)">https://developer.wordpress.org/plugins/plugin-basics/</a></p>



<p>WordPress 的 plugin (外掛) 放在 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">wp-content/plugins</mark></code>, 官方文件提到，開發 plugin 第一件事情就是想名稱，plugin 的名稱要有獨一性。即使你的 plugin 沒上架，也要考慮 plugin 名稱的獨一性，如果名稱跟其他 plugin 有重複時，會造成升級時的混淆。</p>



<p>官方建議名稱可以取&nbsp;<code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">mycompanyname-fabulous-functionality</mark></code> (前置你的公司名稱，用 dash 分隔)。每個 plugin 至少要有一支 php, 官方建議檔名跟資料夾一致，也就是 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">mycompanyname-fabulous-functionality.php</mark></code></p>



<p>但實務上不一定要加公司名 (很多官方出的外掛也沒有冠 Automattic, 裡面的 PHP 檔名也沒有跟資料夾一致）</p>



<p>plugin 裡每支 php 應該第一行是&nbsp;<code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">defined('ABSPATH') or die();</mark></code><br>以確保你的每支 php 是在 WordPress core system 裡面。</p>



<p>plugin 裡的其中一支 (而且只能有一支) PHP 要加上 header, 其中只有 plugin name 是 required.<br><a href="https://developer.wordpress.org/plugins/the-basics/header-requirements/" target="_blank" rel="noopener noreferrer">https://developer.wordpress.org/plugins/the-basics/header-requirements/</a></p>



<p>基本上有三個 action hook 是一定要的，在這支有 header 的 PHP 加上</p>



<pre class="wp-block-preformatted">register_activation_hook( __FILE__, 'your_activation_function')
register_deactivation_hook( __FILE__, 'your_deactivation_function')
register_uninstall_hook( __FILE__, 'your_uninstall_function')</pre>



<p>可以很直覺的看出來，分別是啟用時調用、停用時調用，和解除安裝時調用。通常這三個 action hook 是寫在這支 PHP 裡 (暫稱之為 main plugin file), 但是也可以寫在其他 PHP 裡。如果寫在其他 PHP，記得 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">__FILE__</mark></code> 要換成 main plugin file 的路徑。</p>



<p><a rel="noopener noreferrer" href="https://developer.wordpress.org/plugins/the-basics/uninstall-methods/" target="_blank">https://developer.wordpress.org/plugins/the-basics/uninstall-methods/</a><br>deactivate 跟 uninstall hooks 官方文件特別提了，<code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">deactivation hook</mark></code> 處理的是移除 temp files/folders, flush permalinks 等，<code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">uninstall hook</mark></code> 處理的是移除你新加的 options, DB tables, 也就是復原系統。不要把 deactivate 跟 uninstall hooks 搞混了。</p>



<p><a rel="noopener noreferrer" href="https://developer.wordpress.org/plugins/the-basics/best-practices/" target="_blank">https://developer.wordpress.org/plugins/the-basics/best-practices/</a><br>多個外掛時，很有可能變數名, 函數名, class名稱可能會衝到。官方文件提供了一些好的 coding practice, 分析的很漂亮，相信很多有工程背景的朋友也會覺得這篇官方文件很讚。</p>



<h4 class="wp-block-heading">1.&nbsp;Procedural</h4>



<p>&#8211; 所有變數, 函數, class名稱加上 prefix<br>&#8211;&nbsp;<strong>check for existence</strong>, 尤其是 functions<br>Variables: isset() (includes arrays, objects, etc.)<br>Functions: function_exists()<br>Classes: class_exists()<br>Constants: defined()</p>



<h4 class="wp-block-heading">2. OOP</h4>



<p>將外掛子模組的 code 包成 class.</p>



<h4 class="wp-block-heading">3.&nbsp;File Organization</h4>



<p>外掛裡的檔案要有檔案結構，而不是都擺在同一層。</p>



<h4 class="wp-block-heading">4.&nbsp;Plugin Architecture</h4>



<p>&#8211;&nbsp;Conditional Loading, 把 admin code 跟 public code 分開，調用時用&nbsp;<code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">is_admin()</mark></code> 來區分。<br>&#8211;&nbsp;Architecture Patterns.</p>



<h4 class="wp-block-heading">5.&nbsp;Boilerplate Starting Points</h4>



<p>上方文件建議開發者「不要」每次都從 0 開始寫 plugin，而是要建立自己的樣板，這樣你所有開發的 plugin 才會有一致性 (consistency)。上方文件並提供一些 template 可以參考。</p>



<p>除了 activation, deactivation, uninstall 三個 action, 整個 WP 其實是 action (用軟體工程比較通用的說法是 event) 驅動的一個框架，底下是 WP 的 action reference, 包含前後台每次 request 的 action 順序<br><a href="https://codex.wordpress.org/Plugin_API/Action_Reference" target="_blank" rel="noopener noreferrer">https://codex.wordpress.org/Plugin_API/Action_Reference</a></p>



<p>提一下 form&nbsp;submission 的部分&#8230;<br><a href="https://codex.wordpress.org/Plugin_API/Action_Reference/admin_post_(action)" target="_blank" rel="noopener noreferrer">https://codex.wordpress.org/Plugin_API/Action_Reference/admin_post_(action)</a><br>在 WP 寫表單時，首先要定義一個 hidden field</p>



<pre class="wp-block-preformatted">&lt;input type="hidden" name="action" value="your_post_action_name"&gt;</pre>



<p><code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">your_post_action_name</mark></code> 請自行選擇，注意這個 action 跟 &lt;form&gt; action 無關。&lt;form&gt; 一般是</p>



<pre class="wp-block-preformatted">&lt;form method="post" action="&lt;?php echo esc_url( admin_url( 'admin-post.php' ) ); ?&gt;"&gt;</pre>



<p>然後註冊你的 handler</p>



<pre class="wp-block-preformatted">add_action( 'admin_post_your_post_action_name', your_handler_function );</pre>



<p>這個 action 就是你的 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">your_post_action_name</mark></code> 前面直接黏上 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">admin_post_</mark></code></p>



<p>如果你是給前台沒登入的用戶 submit form</p>



<pre class="wp-block-preformatted">add_action( 'admin_post_nopriv_your_post_action_name', your_handler_function );</pre>



<p>就是 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">admin_post_</mark></code> 改成 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">admin_post_nopriv_</mark></code>, 後面一樣黏 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">your_post_action_name</mark></code></p>



<h4 class="wp-block-heading">結論</h4>



<p>WP 的開發眉眉角角很多，而且很多是實務的經驗 (其實 larry 不是很建議初學 web 的工程師以 WP 當做第一個學習框架)。以上只是就大的框架走過一遍，後續有空再跟大家分享吧 ~</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>WordPress child theme 子主題</title>
		<link>https://blog.yuyansoftware.com.tw/2017/10/wordpress-child-theme/</link>
		
		<dc:creator><![CDATA[Larry]]></dc:creator>
		<pubDate>Wed, 04 Oct 2017 07:54:00 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">http://test234.yuyansoftware.com.tw/2017/10/04/wordpress-child-theme/</guid>

					<description><![CDATA[每個 Wordpress 網站基本上都會套用一個主題 (theme). 主題會由其開發者繼續維護及演進，而業主客製的部分則建議寫在子主題 (child theme). 如此當主題更新時，客製的部分會仍然留存。]]></description>
										<content:encoded><![CDATA[
<p>圖片來源 <a href="https://wordpress.org/" target="_blank" rel="noreferrer noopener" aria-label=" (在新分頁中開啟)">https://wordpress.org</a></p>



<p><a rel="noreferrer noopener" aria-label="https://developer.wordpress.org/themes/advanced-topics/child-themes/ (在新分頁中開啟)" href="https://developer.wordpress.org/themes/advanced-topics/child-themes/" target="_blank">https://developer.wordpress.org/themes/advanced-topics/child-themes/</a><br><a href="https://docs.woocommerce.com/document/set-up-and-use-a-child-theme/" target="_blank" rel="noreferrer noopener" aria-label="https://docs.woocommerce.com/document/set-up-and-use-a-child-theme/ (在新分頁中開啟)">https://docs.woocommerce.com/document/set-up-and-use-a-child-theme/</a></p>



<p>一個 child theme (子主題) 至少要加三部分</p>



<h4 class="wp-block-heading">1. child theme 的資料夾</h4>



<p>如官方文件所述，如果你想要幫<br><code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">wp-content/themes/twentyfifteen</mark></code> 加 child theme, 則資料夾是<br><code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">wp-content/themes/twentyfifteen-child</mark></code></p>



<p>加上 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">-child</mark></code>, 把它當做 coding convention.</p>



<h4 class="wp-block-heading">2. style.css</h4>



<p>以 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">twentyfifteen-child</mark></code> 來說，就是 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">wp-content/themes/twentyfifteen-child/style.css</mark></code><br>一樣要加上 <a rel="noopener noreferrer" href="https://codex.wordpress.org/Theme_Development#Theme_Stylesheet" target="_blank">stylesheet header</a>, 注意新增一個 Template 欄位，例如<br><code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">Template: twentyfifteen</mark></code>&nbsp;指定你的 parent 是 twentyfifteen</p>



<h4 class="wp-block-heading">3. functions.php</h4>



<p>子主題的 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">functions.php</mark></code> 會「先於」父主題的 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">functions.php</mark></code> 被執行 (兩者都會執行)</p>



<p>接著要引用 parent 的 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">style.css</mark></code>, 官方文件提到在 child theme 使用 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">@import</mark></code> 是「以前」方法了，目前建議的方法是在子主題的 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">functions.php</mark></code> 加上</p>



<pre class="wp-block-preformatted">&lt;?php
function my_theme_enqueue_styles() {

    $parent_style = 'parent-style';

    wp_enqueue_style( $parent_style, get_template_directory_uri() . '/style.css' );
    wp_enqueue_style( 'child-style',
        get_stylesheet_directory_uri() . '/style.css',
        array( $parent_style ),
        wp_get_theme()-&gt;get('Version')
    );
}
add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_styles' );
?&gt;</pre>



<p>注意</p>



<p>a. 去父主題的 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">functions.php</mark></code> 找到&nbsp;<code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">wp_enqueue_style</mark></code>, 一般來說，主題需要告訴 WP 核心去引用 css,&nbsp;<code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">wp_enqueue_style</mark></code> 的第一個參數就是識別字串 (官方文件叫 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">$handle</mark></code>), 把這個識別字串記住，上方的 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">$parent_style</mark></code> 改成這個識別字串。</p>



<p>b. 檢查父主題 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">functions.php</mark></code> 是否已有幫子主題&nbsp;<code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">wp_enqueue_style</mark></code> 的 code, 檢查 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">wp_enqueue_style</mark></code> 和&nbsp;<code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">is_child_theme</mark></code>. 如果有的話，子主題連 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">functions.php</mark></code> 都不用加 (當然如果你要客製化 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">functions.php</mark></code> 的話還是要加)</p>



<p>c. 承 b, 如果父主題「沒有」幫子主題&nbsp;<code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">wp_enqueue_style</mark></code> 的 code, 則需要上方附的程式碼，否則父主題的 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">style.css</mark></code> 不會被引用到 html head.</p>



<p>d. 如果你的 child theme 不只有 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">style.css</mark></code>, 要 review 所有 css 檔案的相依性，照順序 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">wp_enqueue_style</mark></code></p>



<p>到目前為止，你的後台主題面板應該已經看得到你的 child theme, 並可以啟用。如果你想換的不只是 css, 還需要換 template. 那直接在 child theme 新增一樣檔名的 template php 即可。</p>



<p>官方文件有提到，要改 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">functions.php</mark></code> 時，建議新增 child theme, 在 child theme <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">functions.php</mark></code> 裡 orverwrite 你要改的 function, 因為當主題升級時，<code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">functions.php</mark></code> 會被覆寫掉。要注意的是，你的父主題的 function 要 &#8220;pluggable&#8221; (用 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">function_exists</mark></code> 包住)</p>



<p>官方文件附了一個寫 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">&lt;link&gt;</mark></code> 的範例，程式上沒有特殊之處，但概念上 WordPress 有點像是在 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">functions.php</mark></code> 裡做 templating.</p>



<p>最後有 child theme 時，<code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">get_template_directory()</mark></code> return 的是父主題的資料夾，要拿到子主題的路徑，請用 <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">get_stylesheet_directory()</mark></code></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
