Day18 - 铁人付外挂前置作业(三)- 建立资料夹结构

使用 Valet 或是其他本机环境软件把 WordPress 安装好之後,切换到网站根目录,可以看到 以下的档案结构:

├── index.php
├── license.txt
├── readme.html
├── wp-activate.php
├── wp-admin
├── wp-blog-header.php
├── wp-comments-post.php
├── wp-config-sample.php
├── wp-config.php
├── wp-content
├── wp-cron.php
├── wp-includes
├── wp-links-opml.php
├── wp-load.php
├── wp-login.php
├── wp-mail.php
├── wp-settings.php
├── wp-signup.php
├── wp-trackback.php
└── xmlrpc.php

一共有三个资料,分别是 wp-admin、wp-content 与 wp-includes,其中 wp-admin 是存放後台相关的档案,wp-includes 是提供所有开发时会用到的 API,关於这两个资料夹我们必须要记住的唯一一个重点就是:千万绝对不可不要去修改里面的档案,因为他们是 WordPress 的核心程序,只要一更新就会被复写,如果你在网路上爬到一些程序码片段是要进去这两个资料夹修改的,请直接忽略跳过。

绝对不要修改 wp-admin 与 wp-includes 里面的档案

根目录中我们唯一可以自行修改的档案是 wp-config.php,里面包含了资料库连线资讯、验证用的金钥,以及可以控制环境的常数设定,如果需要启用除错模式、设定资料表前缀,都是在 wp-config.php 里面处理。

接下来我们的主战场是在 wp-content,结构说明如下:

wp-content
├── languages
├── plugins
├── themes
└── uploads

languages : 放布景主题或是外挂的语系档,只会有 .po 与 .mo 两种档案类型

plugins : 放外挂的资料夹,如果不透过後台而要手动安装的话,把外挂资料夹放到这个目录即可

themes 放布景主题的资料夹,同样的,直接将布景主题资料夹放到这个目录就能在後台看到相对应的布景主题

uploads 所有透过後台上传的档案、图片都会放在这个目录中

新增外挂

我们现在要来开发外挂,所以先将目录切换至 plugins,并且新增一个名为 iron-pay 的资料夹:

$ cd Sites/woocommerce/wp-content/plugins
~/Sites/woocommerce/wp-content/plugins $ mkdir iron-pay

这时候我们就可以看到 plugins 目录里面有两个资料夹:

plugins
├── iron-pay
└── woocommerce

开发 WordPress 外挂与 WooCommerce 外挂基本上是一模一样的,因为 WordPress 的机制让我们可以开发外挂的外挂,只要该外挂本身有提供勾点 ( Hook ),就能在不动到原始程序码的情境下进行修改,WooCommerce 提供非常丰富且数量庞大的勾点,因此我们可以不用修改 WooCommerce 的原始码就能新增金流功能。

要写一支外挂很简单,开好资料夹并切换到该目录後新增一个与资料夹同名的档案:

~/Sites/woocommerce/wp-content/plugins $ cd iron-pay
~/Sites/woocommerce/wp-content/plugins/iron-pay $ touch iron-pay.php

开启 iron-pay.php 将以下注解放入档案最上方:

<?php

/**
 * @link              https://oberonlai.blog
 * @since             1.0.0
 * @package           irp
 *
 * @wordpress-plugin
 * Plugin Name:       WooCommerce 铁人付
 * Plugin URI:        https://oberonlai.blog
 * Description:       新增 WooCommerce 铁人支付金流
 * Version:           1.0.0
 * Author:            Oberon Lai
 * Author URI:        https://oberonlai.blog
 * License:           GPL-2.0+
 * License URI:       http://www.gnu.org/licenses/gpl-2.0.txt
 * Text Domain:       irp
 * Domain Path:       /languages
 * WC tested up to: 5.6.0
 * WC requires at least: 5.3
 */

需要注意的地方是 Plugin Name 与 Description,这是外挂名称与描述,WC tested up to 是 WooCommerce 的版本相容性,WC requires at least 是该站的 WooCommerce 最低版本,存档後就可以在 WordPress 後台的外挂清单看到这支外挂并启用它。

接下来加入一些开发外挂时常会用到的功能:

判断 WooCommerce 是否有启用

因为我们的金流外挂是依附在 WooCommerce 上面的,如果它没有启用的话可能会造成某些预期外的错误,因此先做启用判断会比较保险,继续在 iron-pay.php 中加入以下程序码:

<?php

/**
 * @link              https://oberonlai.blog
 * @since             1.0.0
 * @package           irp
 *
 * @wordpress-plugin
 * Plugin Name:       WooCommerce 铁人付外挂
 * Plugin URI:        https://oberonlai.blog
 * Description:       新增 WooCommerce 铁人支付金流
 * Version:           1.0.0
 * Author:            Oberon Lai
 * Author URI:        https://oberonlai.blog
 * License:           GPL-2.0+
 * License URI:       http://www.gnu.org/licenses/gpl-2.0.txt
 * Text Domain:       irp
 * Domain Path:       /languages
 * WC tested up to: 5.6.0
 * WC requires at least: 5.3
 */
	
/**
 * Check WooCommerce Activied
 */
if ( ! in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ), true ) ) {
    
	require_once ABSPATH . 'wp-admin/includes/plugin.php';
    
	if ( is_plugin_active( plugin_basename( __FILE__ ) ) ) {
        deactivate_plugins( plugin_basename( __FILE__ ) );
        /**
         * Error admin notice
         */
        function require_woocommerce_notice() {
            echo '<div class="error"><p>外挂启用失败,需要安装并启用 WooCommerce 5.3 以上版本。</p></div>';
        }
        add_action( 'admin_notices', 'require_woocommerce_notice' );
        return;
    }
}

第一行先判断在已启用的外挂列表中,是否含有 woocommerce/woocommerce.php 这笔资料,get_option() 是取得设定值的函式,apply_filters 是放入勾点的函式,这边代表的是如果有其他的程序使用了 add_filter( 'active_plugins' ) 这个勾点来修改已启用的外挂清单,那麽也会被列入 in_array 的判断之中。

接下来我们因为要使用 is_plugin_active 所以要先引入 wp-admin/includes/plugin.php,这个函式会判断我们的外挂是否被启用,它传入的参数是外挂的主档案,也就是 iron-pay.php,所以我们先判断 WooCommerce 是否有被启用,如果没有的话而我们的外挂被启用了,就会触发 deactivate_plugins() 停用外挂以及出现错误提示。

add_action() 是另外一种勾点,这边带入两个参数,第一个是勾点的名称 admin_notices,也就是後台的提示讯息,第二个是回呼函式,也就是我们要在这个勾点上做什麽事情。

函式 require_woocommerce_notice() 里面输出提示讯息,提示说要先启用 WooCommerce 才能启用我们的外挂。这段程序码我们带到了 WordPress 的核心概念勾点,勾点有两种:action 与 filter。

action 是可以把一些特定的函式交由勾点来执行,就像 add_action( 'admin_notices', 'require_woocommerce_notice' ) 这样。Filter 是可以修改参数、显示文字或设定值,就像add_filter( 'active_plugins', 'new_plugin_active' ) 这样,action 的回呼函式不一定要输出结果,而 filter 因为修改资料所以会需要 return 回传修改後的结果。

勾点可以放在布景主题或是外挂来执行,这样就不用修改到核心程序码。如果现在还不了解勾点是什麽也没关系,後续关於勾点的部分会在外挂实作中一直反覆出现,

常数定义与自动载入

当判断我们的外挂可以正确被启用後,接下来就先把之後会常用到的常数定义出来:

<?php

/**
 * @link              https://oberonlai.blog
 * @since             1.0.0
 * @package           irp
 *
 * @wordpress-plugin
 * Plugin Name:       WooCommerce 铁人付外挂
 * Plugin URI:        https://oberonlai.blog
 * Description:       新增 WooCommerce 铁人支付金流
 * Version:           1.0.0
 * Author:            Oberon Lai
 * Author URI:        https://oberonlai.blog
 * License:           GPL-2.0+
 * License URI:       http://www.gnu.org/licenses/gpl-2.0.txt
 * Text Domain:       irp
 * Domain Path:       /languages
 * WC tested up to: 5.6.0
 * WC requires at least: 5
 */
	
/**
 * Check WooCommerce Activied
 * 略
 */
	
/**
 * Define Variable
 */
define( 'IRP_PLUGIN_VERSION', '1.0.0' );
define( 'IRP_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
define( 'IRP_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'IRP_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );

/**
 * Autoload
 */
require_once( IRP_PLUGIN_DIR . 'vendor/autoload.php' );
\A7\autoload( IRP_PLUGIN_DIR . 'src' );

这四个常数经常会用到,像是引入 js 或 css 档,就可以用这些常数来指定路径与版本号,Autoload 的部分使用了由 Aaron Holbrook 所开发的 a7/autoload,他使用了回圈去扫指定目录的所有档案,然後再透过 autoload 机制去逐一载入,虽然该套件已经有两年多没更新了,但用到目前为止都非常的稳定没出过任何问题。

用了它在 src 目录底下所有的档案,不管有几层目录、多少档案,透过它就可以自动完整载入,纵使修改了档名或是资料夹名称,依旧都能正常运作,非常适合需要频繁变动的资料夹结构。

下一步这我们就用 Composer 来进行安装。

设定 Composer 环境

安装 Composer 的教学网路非常多,这边主要示范给 WordPress 外挂开发者的环境设定。第一步先开启终端机然後把目录切到正在开发的外挂底下然後执行 composer init:

~/Sites/woocommerce/wp-content/plugins/iron-pay $ composer init

composer 会用对话式的介面来协助我们进行设定,依序要回答六个问题:

This command will guide you through creating your composer.json config.

Package name (<vendor>/<name>) [oberonlai/my-plugin]: 
Description []: 
Author [Oberon Lai <[email protected]>, n to skip]: 
Minimum Stability []: stable
Package Type (e.g. library, project, metapackage, composer-plugin) []: project
License []: propreitary

基本上因为这不是要上传到 Composer 套件库 Packagist 的套件,我习惯都直接采用预设值,如果有特殊需求可以再个别调整,第七题是关键,它会问你是否要安装相依套件:

Define your dependencies.

Would you like to define your dependencies (require) interactively [yes]? 
Search for a package: a7/autoload
Enter the version constraint to require (or leave blank to use the latest version): 

输入套件名称 a7/autoload 按下 Enter 後 Composer 就会开始自动搜寻 Packagist 上面的所有 PHP 套件并且指定安装的版本,如果要安装最新版就直接 Enter 下一步即可,a7/autoload 这个套件可以把指定资料夹里面的档案全部自动载入,如果没有它就需要一个一个手动指定要自动载入的资料夹。

完成後接下来又会再问一次是否要搜寻其他套件,这边我们什麽都不输入直接下 Enter 即可。

接下来它会询问是否要安装只有在开发时才需要的套件,像是做单元测试 PHPUnit 这一类只会在开发环境中需要的套件就可以在这边安装,但目前我们先跳过,之後讲解单元测试的文章再另行说明:

Would you like to define your dev dependencies (require-dev) interactively [yes]? no

接下来就会看到整个 Composer 设定档的草稿,它会请你确认是否正确,输入 Enter 即可,这样就完成 composer.json 设定档了。

{
    "name": "oberonlai/irpon-pay",
    "type": "project",
    "require": {
        "a7/autoload": "^2.1"
    },
    "license": "propreitary",
    "authors": [
        {
            "name": "Oberon Lai",
            "email": "[email protected]"
        }
    ],
    "minimum-stability": "stable"
}

Do you confirm generation [yes]? yes

最後它会问你是否要安装设定档中的套件,按下 Enter 即可

Would you like to install dependencies now [yes]? yes

最後就会出现安装完成的讯息,这就代表我们已经把 Composer 已经所需套件准备完成:

No lock file found. Updating dependencies instead of installing from lock file. Use composer update over composer install if you do not have a lock file.
Loading composer repositories with package information
Updating dependencies
Lock file operations: 1 install, 0 updates, 0 removals
  - Locking a7/autoload (2.1)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Installing a7/autoload (2.1): Extracting archive
Generating autoload files

观察我们外挂的目录,会发现多了 composer.json、composer.lock 以及 vendor 资料夹,未来我们任何从 Composer 安装的套件都会放在 vendor 这个资料夹底下。

完成 Composer 的设定後我们再新增一个 src 资料夹,之後需要自动载入的类别都会放在这个目录下:

~/Sites/woocommerce/wp-content/plugins/iron-pay $ mkdir src

到这边,外挂的基本结构就完成了:

iron-pay
├── composer.json
├── composer.lock
├── iron-pay.php
├── src
└── vendor
    ├── a7
    ├── autoload.php
    └── composer

接下来我们开始来进行设定页面的实作。

本文同步发表於:https://oberonlai.blog/tw/woocommerce-payment-structure/


<<:  索引合并(index merge)

>>:  [想试试看JavaScript ] 为什麽需要这麽多种注册事件处理的方式

[11 月限时免费] 3 款 WordPress 布景主题免费下载

1.【WordPress 付费主题免费下载】Sentobar — Barbershop WordPr...

#19 No-code 之旅 — Avatars Libraries

嗨~ 今天来个比较特别的主题,Avatars libraries。很多时候我们需要显示一些头贴,有的...

[DAY 30] 总结及回顾

机器人与我们同在 大家好,虽然令人不舍,但这天还是来临了 。30天的时间倏忽即逝,是时候跟大家道别了...

DAY 25 Full Screen Modal - Follow Us

这个部分主要是 social media 的区块,会用到 fontawesome 上的 icon 们...

Day 13 | 同步与非同步- Thread类别与runOnUiThread()方法

Thread Thread是Java的原生类别,当需要执行绪处理费时任务时,就可以新增该类别执行Ta...