มีใครใช้การโหลดอัตโนมัติและ / หรือ PHP namespaces ภายในปลั๊กอินหรือชุดรูปแบบ?
ความคิดในการใช้พวกเขา? อันตรายใด ๆ ผิดพลาด?
หมายเหตุ: เนมสเปซเป็น PHP 5.3 ขึ้นไปเท่านั้น สมมติว่าคุณรู้ว่าคุณกำลังเผชิญกับเซิร์ฟเวอร์ที่คุณรู้ว่ามี PHP 5.3 หรือสูงกว่า
มีใครใช้การโหลดอัตโนมัติและ / หรือ PHP namespaces ภายในปลั๊กอินหรือชุดรูปแบบ?
ความคิดในการใช้พวกเขา? อันตรายใด ๆ ผิดพลาด?
หมายเหตุ: เนมสเปซเป็น PHP 5.3 ขึ้นไปเท่านั้น สมมติว่าคุณรู้ว่าคุณกำลังเผชิญกับเซิร์ฟเวอร์ที่คุณรู้ว่ามี PHP 5.3 หรือสูงกว่า
คำตอบ:
โอเคฉันมีสองโครงการใหญ่ที่ฉันควบคุมเซิร์ฟเวอร์ได้เพียงพอที่จะกำหนดชื่อและพึ่งพาการโหลดอัตโนมัติ
ขึ้นก่อน การโหลดอัตโนมัติยอดเยี่ยม ไม่ต้องกังวลเกี่ยวกับความต้องการเป็นสิ่งที่ค่อนข้างดี
นี่คือตัวโหลดที่ฉันใช้ในโปรเจ็กต์สองสามตัว ตรวจสอบเพื่อให้แน่ใจว่าคลาสอยู่ในเนมสเปซปัจจุบันก่อนแล้วค่อยไปถ้าไม่ใช่ จากนั้นเป็นเพียงการจัดการสตริงเพื่อหาชั้นเรียน
<?php
spl_autoload_register(__NAMESPACE__ . '\\autoload');
function autoload($cls)
{
$cls = ltrim($cls, '\\');
if(strpos($cls, __NAMESPACE__) !== 0)
return;
$cls = str_replace(__NAMESPACE__, '', $cls);
$path = PLUGIN_PATH_PATH . 'inc' .
str_replace('\\', DIRECTORY_SEPARATOR, $cls) . '.php';
require_once($path);
}
หนึ่งสามารถปรับได้อย่างง่ายดายสำหรับการใช้งานโดยไม่ต้อง namespaces สมมติว่าคุณนำหน้าปลั๊กอิน / ชุดรูปแบบของคุณอย่างสม่ำเสมอคุณสามารถทดสอบคำนำหน้านั้นได้ จากนั้นใช้เครื่องหมายขีดล่างในชื่อคลาสเป็นตัวยึดตำแหน่งสำหรับตัวคั่นไดเรกทอรี หากคุณใช้คลาสจำนวนมากเป็นไปได้ว่าคุณอาจต้องการใช้ตัวโหลดอัตโนมัติคลาสแมปบางประเภท
ระบบ hooks ของ WordPress ใช้งานได้โดยใช้call_user_func
(และcall_user_func_array
) ซึ่งใช้ชื่อฟังก์ชั่นเป็นสตริงและเรียกพวกมันเมื่อมีการเรียกใช้ฟังก์ชันdo_action
(และต่อมาcall_user_func
)
ด้วยเนมสเปซนั่นหมายความว่าคุณจะต้องผ่านชื่อฟังก์ชันที่ผ่านการรับรองโดยสมบูรณ์ซึ่งรวมถึงเนมสเปซไว้ใน hooks
<?php
namespace WPSE\SomeNameSpace;
add_filter('some_filter', 'WPSE\\SomeNameSpace\\the_function');
function the_function()
{
return 'did stuff';
}
มันคงเป็นการดีกว่า__NAMESPACE__
ถ้าคุณใช้เวทมนต์คงที่หากคุณต้องการทำสิ่งนี้
<?php
namespace WPSE\SomeNameSpace;
add_filter('some_filter', __NAMESPACE__ . '\\the_function');
function the_function()
{
return 'did stuff';
}
หากคุณใส่ตะขอลงในคลาสเสมอมันง่ายกว่า อินสแตนซ์สร้างมาตรฐานของคลาสและ hooks ทั้งหมดในตัวสร้างด้วยการ$this
ทำงานที่ดี
<?php
namespace WPSE\SomeNameSpace;
new Plugin;
class Plugin
{
function __construct()
{
add_action('plugins_loaded', array($this, 'loaded'));
}
function loaded()
{
// this works!
}
}
หากคุณใช้วิธีการคงที่เช่นฉันต้องการคุณจะต้องส่งชื่อคลาสที่ผ่านการรับรองเป็นอาร์กิวเมนต์แรกของอาร์เรย์ นั่นเป็นจำนวนมากของการทำงานเพื่อให้คุณก็สามารถใช้เวทมนตร์คงที่หรือ__CLASS__
get_class
<?php
namespace WPSE\SomeNameSpace;
Plugin::init();
class Plugin
{
public static function init()
{
add_action('plugins_loaded', array(__CLASS__, 'loaded'));
// OR: add_action('plugins_loaded', array(get_class(), 'loaded'));
}
public static function loaded()
{
// this works!
}
}
ความละเอียดของ classname ของ PHP นั้นค่อนข้างแย่ หากคุณกำลังจะใช้คลาส WP หลัก ( WP_Widget
ในตัวอย่างด้านล่าง) คุณต้องระบุuse
คำสั่ง
use \WP_Widget;
class MyWidget extends WP_Widget
{
// ...
}
หรือคุณสามารถใช้ชื่อคลาสที่ผ่านการรับรองโดยสมบูรณ์ - เพียงแค่นำหน้าด้วยแบ็กสแลช
<?php
namespace WPSE\SomeNameSpace;
class MyWidget extends \WP_Widget
{
// ...
}
นี่เป็น PHP ทั่วไปมากกว่า แต่มันก็เป็นบิตสำหรับฉันดังนั้นนี่คือ
คุณอาจต้องการกำหนดสิ่งที่คุณจะใช้บ่อยเช่นเส้นทางไปยังปลั๊กอินของคุณ การใช้คำสั่ง define ทำให้สิ่งต่าง ๆ ในรูทเนมสเปซเว้นแต่ว่าคุณจะส่งเนมสเปซไปที่อาร์กิวเมนต์แรกของ define อย่างชัดเจน
<?php
namespace WPSE\SomeNameSpace;
// root namespace
define('WPSE_63668_PATH', plugin_dir_path(__FILE__));
// in the current namespace
define(__NAMESPACE__ . '\\PATH', plugin_dir_path(__FILE__));
นอกจากนี้คุณยังสามารถใช้const
คำหลักในระดับรากของไฟล์ด้วย PHP 5.3 บวก consts
s มักจะอยู่ใน namespace ปัจจุบัน แต่มีความยืดหยุ่นน้อยกว่าการdefine
โทร
<?php
namespace WPSE\SomeNameSpace;
// in the current namespace
const MY_CONST = 1;
// this won't work!
const MY_PATH = plugin_dir_path(__FILE__);
โปรดเพิ่มเคล็ดลับอื่น ๆ ที่คุณอาจมี!
นี่คือคำตอบปี 2017
การโหลดอัตโนมัติยอดเยี่ยม การกำหนดชื่อน่ากลัว
แม้ว่าคุณจะสามารถม้วนมันด้วยตัวคุณเองได้ในปี 2560 แต่มันก็สมเหตุสมผลดีที่จะใช้Composer ที่งดงามและแพร่หลายเพื่อจัดการกับความต้องการ PHP ของคุณ นักแต่งเพลงสนับสนุนการโหลดอัตโนมัติทั้งPSR-0และPSR-4แต่ตัวแรกนั้นถูกคัดค้านมาตั้งแต่ปี 2014 ดังนั้นให้ใช้ PSR-4 มันลดความซับซ้อนของไดเรกทอรีของคุณ
เราเก็บแต่ละปลั๊กอินของเรา / รูปแบบในพื้นที่เก็บข้อมูล Github ของตัวเองแต่ละคนมีของตัวเองcomposer.json
ของไฟล์และcomposer.lock
แฟ้ม
นี่คือโครงสร้างไดเรกทอรีที่เราใช้สำหรับปลั๊กอินของเรา (เราไม่มีปลั๊กอินที่เรียกว่าจริงๆawesome-plugin
แต่เราควรทำ)
plugins/awesome-plugin/bootstrap.php
plugins/awesome-plugin/composer.json
plugins/awesome-plugin/composer.lock
plugins/awesome-plugin/awesome-plugin.php
plugins/awesome-plugin/src/*
plugins/awesome-plugin/vendor/autoload.php
plugins/awesome-plugin/vendor/*
หากคุณให้composer.json
ไฟล์ที่เหมาะสมนักแต่งเพลงจะจัดการการเว้นวรรคชื่อและการโหลดอัตโนมัติที่นี่
{
"name": "awesome-company/awesome-plugin",
"description": "Wordpress plugin for AwesomeCompany website, providing awesome functionality.",
"type": "wordpress-plugin",
"autoload": {
"psr-4": {
"AwesomeCompany\\Plugins\\AwesomePlugin\\": "src"
}
}
}
เมื่อคุณเรียกใช้composer install
มันจะสร้างvendor
ไดเรกทอรีและvendor/autoload.php
ไฟล์ซึ่งจะทำการโหลดไฟล์ที่เว้นวรรคชื่อของคุณทั้งหมดsrc/
และไลบรารีอื่น ๆ ที่คุณอาจต้องการ
จากนั้นที่ด้านบนของไฟล์ปลั๊กอินหลักของคุณ (ซึ่งสำหรับพวกเราawesome-plugin.php
) หลังจากเมตาดาต้าปลั๊กอินของคุณคุณเพียงแค่ต้องการ:
// Composer autoloading.
require_once __DIR__ . '/vendor/autoload.php';
...
ไม่ใช่ความจำเป็น แต่เราใช้แผ่นสำเร็จรูปBedrock Wordpress เพื่อใช้ Composer ตั้งแต่เริ่มต้น จากนั้นเราสามารถใช้ Composer เพื่อรวบรวมปลั๊กอินที่เราต้องการผ่าน Composer รวมถึงปลั๊กอินของคุณที่คุณเขียนไว้ด้านบน นอกจากนี้ด้วยWPackagistคุณสามารถใช้ปลั๊กอินอื่น ๆ จาก Wordpress.org (ดูตัวอย่างcool-theme
และcool-plugin
ด้านล่าง)
{
"name": "awesome-company/awesome-website",
"type": "project",
"license": "proprietary",
"description": "WordPress boilerplate with modern development tools, easier configuration, and an improved folder structure",
"config": {
"preferred-install": "dist"
},
"repositories": [
{
"type": "composer",
"url": "https://wpackagist.org"
},
{ // Tells Composer to look for our proprietary Awesome Plugin here.
"url": "https://github.com/awesome-company/awesome-plugin.git",
"type": "git"
}
],
"require": {
"php": ">=5.5",
"awesome-company/awesome-plugin": "dev-production", // Our plugin!
"wpackagist-plugin/cool-plugin": "dev-trunk", // Someone else' plugin
"wpackagist-theme/cool-theme": "dev-trunk", // Someone else' theme
"composer/installers": "~1.2.0", // Bedrock default
"vlucas/phpdotenv": "^2.0.1", // Bedrock default
"johnpbloch/wordpress": "4.7.5", // Bedrock default
"oscarotero/env": "^1.0", // Bedrock default
"roots/wp-password-bcrypt": "1.0.0" // Bedrock default
},
"extra": {
// This is the magic that drops packages with the correct TYPE in the correct location.
"installer-paths": {
"web/app/mu-plugins/{$name}/": ["type:wordpress-muplugin"],
"web/app/plugins/{$name}/": ["type:wordpress-plugin"],
"web/app/themes/{$name}/": ["type:wordpress-theme"]
},
"wordpress-install-dir": "web/wp"
},
"scripts": {
"test": [
"vendor/bin/phpcs"
]
}
}
หมายเหตุ 1: ความคิดเห็นไม่ถูกกฎหมายใน JSON แต่ฉันได้ใส่คำอธิบายประกอบไฟล์ด้านบนเพื่อความชัดเจนมากขึ้น
หมายเหตุ 2: ฉันได้ตัดบางส่วนของไฟล์ Bedrock สำเร็จรูปเพื่อความสั้น
หมายเหตุ 3: นี่คือสาเหตุที่type
ฟิลด์ในcomposer.json
ไฟล์แรกมีความสำคัญ นักแต่งเพลงจะวางลงในweb/app/plugins
ไดเรกทอรีโดยอัตโนมัติ
ฉันใช้การโหลดอัตโนมัติ (เนื่องจากปลั๊กอินของฉันมีการโหลดคลาส - ส่วนหนึ่งเป็นเพราะมี Twig) ไม่เคยมีปัญหามาถึงความสนใจของฉัน (ติดตั้งปลั๊กอิน> 20,000 ครั้ง)
หากคุณมั่นใจว่าคุณจะไม่จำเป็นต้องใช้การติดตั้ง php ที่ไม่รองรับเนมสเปซอีกต่อไปคุณก็สบายดี (ประมาณ 70% ของบล็อก WordPress ปัจจุบันไม่รองรับเนมสเปซ) สิ่งที่ควรทราบ:
ฉันดูเหมือนจะจำได้ว่า namespaces ไม่ตรงตามตัวพิมพ์ใหญ่ - เล็กใน php ปกติ แต่เมื่อใช้ fastcgi php บน iis - นี่ทำให้ปวดหัวบางอย่างถ้าคุณทดสอบบน linux และไม่เห็นอักษรตัวพิมพ์เล็กอันธพาล
แม้ว่าคุณจะแน่ใจว่ารหัสที่คุณกำลังพัฒนานั้นจะใช้กับ> 5.3.0 คุณจะไม่สามารถใช้รหัสซ้ำกับโครงการที่ไม่มีความหรูหรานั้น - นั่นคือเหตุผลหลักว่าทำไมฉันถึงไม่ได้ ใช้เนมสเปซในโครงการภายใน ฉันได้พบว่า namespaces จริงๆไม่ได้เพิ่มที่มากเมื่อเทียบกับอาการปวดหัวเป็นไปได้ของการมีการลบพึ่งพาพวกเขา