支付宝扫一扫付款
微信扫一扫付款
(微信为保护隐私,不显示你的昵称)
Asset组件管理URL的生成以及web assets的版本,诸如CSS样式表,JavaScripts以及图片文件等。
过去,在web程序中写死web assets的链接是很常见的。例如:
这种实践现已不再推荐,除非程序极其简单。写死链接有其不利点,因为:
main.css?v=5
) 到asset URLs对某些程序来说是必不可少的,因为它可以让你控制资源(assets)应如何被缓存。Asset组件能让你对不同的包(package)制定不同的版本策略;http://
) 还是安全的 (https://
)。你可以通过下述两种方式安装:
通过Composer安装(Packagist上的symfony/asset
)
通过官方Git宝库(https://github.com/symfony/asset)
然后,包容vendor/autoload.php
文件,以开启Composer提供的自动加载机制。否则,你的程序将无法找到这个Symfony组件的类。
Asset组件通过包(packages)来管理资源(assets)。一个包,集合了全部资源,这些资源共享着相同属性:版本策略,基本路径(base path),CDN主机等。在下面的基本用例中,一个包被创建并管理着没有版本功能的资源:
1 2 3 4 5 6 7 | use Symfony\Component\Asset\Package;
use Symfony\Component\Asset\VersionStrategy\EmptyVersionStrategy;
$package = new Package(new EmptyVersionStrategy());
echo $package->getUrl('/image.png');
// result: /image.png |
Packages实现的是 PackageInterface
接口,它定义了如下两个方法:
getVersion()
getUrl()
使用一个包,你可以:
Asset组件的一个主要功能,是具有对程序资源的版本进行管理的能力。Asset version常用于控制资源的缓存。
不同于依赖于简单的版本架构,Asset组件允许你通过PHP类定义高级版本策略(strategies)。两个内置的策略分别是 EmptyVersionStrategy
,它不对资源添加任何版本,以及 StaticVersionStrategy
,它允许你以格式化字符串来设置版本。
在下面例程中, StaticVersionStrategy
用于加挂 v1
后缀到任何意的资源路径:
1 2 3 4 5 6 7 | use Symfony\Component\Asset\Package;
use Symfony\Component\Asset\VersionStrategy\StaticVersionStrategy;
$package = new Package(new StaticVersionStrategy('v1'));
echo $package->getUrl('/image.png');
// result: /image.png?v1 |
如果你希望调整版本格式,传入一个兼容sprintf的格式化字符串,作为 StaticVersionStrategy
构造器的第二个参数:
1 2 3 4 5 6 7 8 9 10 11 12 13 | // put the 'version' word before the version value
// 在版本值的前面放一个 'version' 字样
$package = new Package(new StaticVersionStrategy('v1', '%s?version=%s'));
echo $package->getUrl('/image.png');
// result: /image.png?version=v1
// put the asset version before its path
// 在路径前面放置资源的版本
$package = new Package(new StaticVersionStrategy('v1', '%2$s/%1$s'));
echo $package->getUrl('/image.png');
// result: /v1/image.png |
使用 VersionStrategyInterface
来定义你自己的版本策略。例如,你的程序可能需要附加当前日期到所有的web资源,以便在每天销毁缓存:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | use Symfony\Component\Asset\VersionStrategy\VersionStrategyInterface;
class DateVersionStrategy implements VersionStrategyInterface
{
private $version;
public function __construct()
{
$this->version = date('Ymd');
}
public function getVersion($path)
{
return $this->version;
}
public function applyVersion($path)
{
return sprintf('%s?v=%s', $path, $this->getVersion($path));
}
} |
一般来讲,很多资源都被存放于常见路径下 (如 /static/images
)。如果你也是如此,用 PathPackage
来替换默认的 Package
类,即可避免一次又一次地重复那个路径:
1 2 3 4 5 6 7 | use Symfony\Component\Asset\PathPackage;
// ...
$package = new PathPackage('/static/images', new StaticVersionStrategy('v1'));
echo $package->getUrl('/logo.png');
// result: /static/images/logo.png?v1 |
如果你在项目中同时使用了 HttpFoundation 组件 (例如,在一套Symfony程序中),那么 PathPackage
可以统管当前请求的上下文:
1 2 3 4 5 6 7 8 9 10 11 12 | use Symfony\Component\Asset\PathPackage;
use Symfony\Component\Asset\Context\RequestStackContext;
// ...
$package = new PathPackage(
'/static/images',
new StaticVersionStrategy('v1'),
new RequestStackContext($requestStack)
);
echo $package->getUrl('/logo.png');
// result: /somewhere/static/images/logo.png?v1 |
现在,request context已设置, PathPackage
将准备好当前请求的base URL。所以,举例来说,如果你的整个网站都存放在服务器根目录的 /somewhere
目录下,并且配置好的基本路径是 /static/images
,则全部路径都将增加 /somewhere/static/images
前缀。
那些把资源存放在不同的域名和CDN下的程序 (Content Delivery Networks) 应该使用 UrlPackage
类,以生成各自资源的绝对URL:
1 2 3 4 5 6 7 8 9 10 | use Symfony\Component\Asset\UrlPackage;
// ...
$package = new UrlPackage(
'http://static.example.com/images/',
new StaticVersionStrategy('v1')
);
echo $package->getUrl('/logo.png');
// result: http://static.example.com/images/logo.png?v1 |
你也可以传一个schema-agnostic(译注:是否https未知)的URL:
1 2 3 4 5 6 7 8 9 10 | use Symfony\Component\Asset\UrlPackage;
// ...
$package = new UrlPackage(
'//static.example.com/images/',
new StaticVersionStrategy('v1')
);
echo $package->getUrl('/logo.png');
// result: //static.example.com/images/logo.png?v1 |
这非常有用,因为如果有用户通过https来访问你的网站,资源将自动地通过HTTPS被请求。只需确保你的CDN托管支持https即可。
如果你把资源托在多个域名上以改进程序性能,传入一个URL的数组到 UrlPackage
构造器的第一个参数:
1 2 3 4 5 6 7 8 9 10 11 12 13 | use Symfony\Component\Asset\UrlPackage;
// ...
$urls = array(
'//static1.example.com/images/',
'//static2.example.com/images/',
);
$package = new UrlPackage($urls, new StaticVersionStrategy('v1'));
echo $package->getUrl('/logo.png');
// result: http://static1.example.com/images/logo.png?v1
echo $package->getUrl('/icon.png');
// result: http://static2.example.com/images/icon.png?v1 |
对于每个资源,链接中的某一个会被随机使用。但是,这种选择是确定了的,也就是说,每一个asset总是会服务于相同的某个域名。这种行为可以简化HTTP缓存的管理。
与相对于程序的资源类似,绝对资源(absolute assets)也能够统管当前请求的上下文。下例中,只有考虑了请求的scheme时,才能选出合适的基本路径(对于HTTPs请求,是HTTPs链接或者“与协议相关”的链接,对于HTTP请求则是任意的base URL)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | use Symfony\Component\Asset\UrlPackage;
use Symfony\Component\Asset\Context\RequestStackContext;
// ...
$package = new UrlPackage(
array('http://example.com/', 'https://example.com/'),
new StaticVersionStrategy('v1'),
new RequestStackContext($requestStack)
);
echo $package->getUrl('/logo.png');
// assuming the RequestStackContext says that we are on a secure host
// 假设RequestStackContext说我们正处于安全连接
// result: https://example.com/logo.png?v1 |
管理着许多资源的程序可能需要把它们打包成相同的版本策略和基本路径。Asset组件包含了一个 Packages
的类以简化多个assets的管理。
下例中,所有的包都使用相同的版本策略(versioning strategy),但他们却有着不同的基本路径(base paths):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | use Symfony\Component\Asset\Package;
use Symfony\Component\Asset\PathPackage;
use Symfony\Component\Asset\UrlPackage;
use Symfony\Component\Asset\Packages;
// ...
$versionStrategy = new StaticVersionStrategy('v1');
$defaultPackage = new Package($versionStrategy);
$namedPackages = array(
'img' => new UrlPackage('http://img.example.com/', $versionStrategy),
'doc' => new PathPackage('/somewhere/deep/for/documents', $versionStrategy),
);
$packages = new Packages($defaultPackage, $namedPackages) |
Packages
类能够定义默认的package,为的是给那些没有定义“包名称”的资源使用。此外,程序还定义了一个名为 img
的包,用于伺服外部域名的图片,以及一个 doc
包,用于在模板中链接到文档时,避免重复使用超长的路径:
1 2 3 4 5 6 7 8 | echo $packages->getUrl('/main.css');
// result: /main.css?v1
echo $packages->getUrl('/logo.png', 'img');
// result: http://img.example.com/logo.png?v1
echo $packages->getUrl('/resume.pdf', 'doc');
// result: /somewhere/deep/for/documents/resume.pdf?v1 |
本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。