x3p0-dev/x3p0-asset 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

x3p0-dev/x3p0-asset

Composer 安装命令:

composer require x3p0-dev/x3p0-asset

包简介

A small, modern asset-resolution library for WordPress plugins and themes.

README 文档

README

A small, modern asset-resolution library for WordPress plugins and themes. It turns a project-relative path (public/css/screen.css) into a value object that knows its public URL, absolute path, and — when the file was built with @wordpress/scripts — its dependencies and cache-busting version, read automatically from the generated .asset.php file.

License PHP Version

Features

  • One value type: Asset describes any bundled file — script, style, image, font, audio — with its URL and filesystem path.
  • Automatic build metadata: reads the .asset.php file emitted by @wordpress/scripts, so dependencies() and version() are filled in for you.
  • Sensible fallback: files with no .asset.php fall back to the file's modification time for cache busting.
  • Location resolvers: pick where paths resolve — the active theme, the parent theme, or a plugin — behind one abstract AssetResolver.
  • WordPress-friendly, core-free values: only the resolvers call WordPress functions; the Asset value itself stays free of WordPress dependencies.
  • Type-Safe: full PHP 8.1+ type declarations for better IDE support.

Requirements

  • PHP 8.1 or higher
  • WordPress (recommended latest version)
  • Composer

Installation

Install via Composer:

composer require x3p0-dev/x3p0-asset

Important: If you're releasing this as part of a theme or plugin bundle, please vendor prefix your installation to avoid conflicts with other plugins/themes. See Vendor Prefixing below.

Quick Start

1. Pick a resolver

A resolver decides where relative paths are resolved from. Bundle a single resolver of your chosen direction and ask it for every asset:

use X3P0\Asset\ThemeAssetResolver;

$assetResolver = new ThemeAssetResolver();

2. Get an asset

$style = $assetResolver->asset('public/css/screen.css');

3. Use it

The asset carries everything the WordPress enqueue functions need:

wp_enqueue_style(
	'my-theme-screen',
	$style->fileUrl(),
	$style->dependencies(),
	$style->version()
);

// Register the path so WordPress can inline the stylesheet when it's small.
wp_style_add_data('my-theme-screen', 'path', $style->filePath());

For a script whose build emitted public/js/editor.asset.php, the dependencies and version come straight from that file:

$script = $assetResolver->asset('public/js/editor.js');

wp_enqueue_script(
	'my-theme-editor',
	$script->fileUrl(),
	$script->dependencies(), // e.g. ['wp-blocks', 'wp-element']
	$script->version(),      // e.g. the build hash
	true
);

Core Concepts

The Asset value

Asset extends SplFileInfo, so every filesystem helper you already know (getSize(), getMTime(), getExtension(), …) is available alongside these:

Method Returns
fileUrl() Public URL to the file
filePath() Absolute filesystem path to the file
dependencies() Registered dependencies, or [] when there's no .asset.php
version() Build hash from the .asset.php, otherwise the file's modification time
hasDataFile() Whether the .asset.php data file exists

An Asset is location-agnostic: it's constructed with an already-resolved absolute path and public URL, so it holds no knowledge of themes or plugins. You normally don't construct it directly — a resolver mints it for you.

The .asset.php data file

When you build scripts and styles with @wordpress/scripts, the dependency-extraction plugin emits a companion asset file next to each entry point — editor.js gets editor.asset.php — returning an array of dependencies and a version.

Asset finds that file automatically (its own name with the extension swapped for .asset.php) and uses it:

  • dependencies() returns the array's dependencies, or [] if the file is absent.
  • version() returns the array's version, or the built file's modification time if the file is absent.
  • hasDataFile() reports whether the file exists — useful for skipping registration when a build output is missing.

The lookup is memoized, so the file is checked and included at most once per Asset.

Resolvers

An AssetResolver resolves relative paths against a base location and mints Asset objects that live there. The base — the one thing that differs between a plugin and a theme — is supplied by the concrete resolvers:

Resolver Resolves against Backing functions
ThemeAssetResolver the active theme (child-overridable) get_theme_file_path() / get_theme_file_uri()
ParentThemeAssetResolver the parent theme (always ships from the parent) get_parent_theme_file_path() / get_parent_theme_file_uri()
PluginAssetResolver a plugin directory plugin_dir_path() / plugins_url()

Each exposes:

$assetResolver->asset('public/js/app.js');   // Asset from a relative path
$assetResolver->fromFile($splFileInfo);      // Asset from a discovered file
$assetResolver->path('public/js/app.js');    // absolute filesystem path (string)
$assetResolver->url('public/js/app.js');     // public URL (string)
$assetResolver->relativize($absolutePath);   // absolute path -> base-relative path

PluginAssetResolver takes the plugin's main file so it can anchor both the path and the URL:

use X3P0\Asset\PluginAssetResolver;

// Typically from the plugin's bootstrap file.
$assetResolver = new PluginAssetResolver(__FILE__);

Choosing a resolver

  • ThemeAssetResolver lets a child theme override a bundled file by shipping its own copy at the same relative path. Good for assets a child theme should be able to replace (images, fonts, editor styles).
  • ParentThemeAssetResolver always loads from the theme that ships the file, even when a child theme is active. Good for built scripts and styles that belong to the parent.
  • PluginAssetResolver resolves against a plugin directory.

A project generally binds one resolver and uses it everywhere.

Discovering assets

fromFile() mints an Asset from an already-discovered SplFileInfo, deriving its base-relative path via relativize(). This pairs well with directory iteration — for example, collecting every built block stylesheet in a folder:

foreach ($cssFiles as $file) {
	$asset = $assetResolver->fromFile($file);

	if ($asset->hasDataFile()) {
		// register/enqueue $asset->fileUrl(), $asset->dependencies(), ...
	}
}

Errors

Every exception the package throws implements the AssetException marker interface (which extends Throwable), so you can catch anything originating here in a single block. Each concrete exception also extends the most fitting SPL class, so code that only cares about the SPL type keeps working too.

Exception Extends Thrown when
PathOutsideBaseException InvalidArgumentException relativize() / fromFile() receive a path that isn't within the resolver's base
InvalidAssetDataException UnexpectedValueException an .asset.php file exists but does not return an array (a malformed build)
use X3P0\Asset\AssetException;

try {
	$asset = $assetResolver->fromFile($file);
	$deps  = $asset->dependencies();
} catch (AssetException $e) {
	// Any failure from this package: bad path, malformed build metadata, etc.
}

Both are programmer/build errors rather than routine conditions — in correct usage neither fires — so catching them is optional. The exceptions carry no WordPress dependency, so they behave the same whether or not WordPress is loaded.

Dependency Injection

The library has no container of its own, but it's designed to be bound in one. Bind the abstract AssetResolver to the concrete resolver your project uses, then type-hint AssetResolver wherever you need assets:

use X3P0\Asset\AssetResolver;
use X3P0\Asset\ThemeAssetResolver;

// Wherever you register bindings:
$container->singleton(AssetResolver::class, ThemeAssetResolver::class);
use X3P0\Asset\AssetResolver;

final class FrontendAssets
{
	public function __construct(private readonly AssetResolver $assetResolver)
	{}

	public function enqueue(): void
	{
		$style = $this->assetResolver->asset('public/css/screen.css');

		wp_enqueue_style(
			'my-theme-screen',
			$style->fileUrl(),
			$style->dependencies(),
			$style->version()
		);
	}
}

Swapping the whole project between the active theme and the parent theme is then a one-line change to the binding.

Vendor Prefixing

Because WordPress loads every active plugin and theme into the same PHP process, two of them shipping the same un-prefixed library will collide. If you distribute your plugin or theme, prefix this package's namespace so your copy is isolated from everyone else's.

The X3P0 projects do this at build time with x3p0-dev/x3p0-prelude, which copies the dependency into your project and rewrites its namespace under your own — for example, X3P0\Asset becomes Acme\MyPlugin\Asset. A general-purpose alternative is PHP-Scoper.

Prefix at release time, not during development, and point your autoloader at the prefixed copy.

License

X3P0: Asset is licensed under the GPL-2.0-or-later license.

Credits

Created and maintained by Justin Tadlock under the X3P0 umbrella.

Support

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 0
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: GPL-2.0-or-later
  • 更新时间: 2026-07-09

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固