[TOC]
# Assets管理
`Phalcon\Assets` 是一个允许您在Web应用程序中管理静态资源(如CSS样式表或JavaScript库)的组件。
`Phalcon\Assets\Manager` 在服务容器中可用,因此您可以从容器可用的应用程序的任何部分添加资源。
## 添加资源
Assets支持两种内置资源:CSS和JavaScripts。如果需要,您可以创建其他资源。资产管理器在内部存储两个默认资源集合 - 一个用于JavaScript,另一个用于CSS。
您可以轻松地向这些集合添加资源,如下所示:
```php
<?php
use Phalcon\Mvc\Controller;
class IndexController extends Controller
{
public function index()
{
// Add some local CSS resources
$this->assets->addCss('css/style.css');
$this->assets->addCss('css/index.css');
// And some local JavaScript resources
$this->assets->addJs('js/jquery.js');
$this->assets->addJs('js/bootstrap.min.js');
}
}
```
然后在视图中,可以打印这些资源:
```php
<html>
<head>
<title>Some amazing website</title>
<?php $this->assets->outputCss(); ?>
</head>
<body>
<!-- ... -->
<?php $this->assets->outputJs(); ?>
</body>
<html>
```
Volt 语法:
```volt
<html>
<head>
<title>Some amazing website</title>
{{ assets.outputCss() }}
</head>
<body>
<!-- ... -->
{{ assets.outputJs() }}
</body>
<html>
```
为了获得更好的页面加载性能,建议将JavaScript放在HTML的末尾而不是`<head>`。
## 本地/远程资源
本地资源是由同一应用程序提供的资源,它们位于应用程序的文档根目录中。本地资源中的URL由`url`服务生成,通常为`Phalcon\Mvc\Url`。
远程资源是由[CDN](https://en.wikipedia.org/wiki/Content_delivery_network)提供的诸如[jQuery](https://jquery.com),[Bootstrap](http://www.bootcss.com/)等公共库的资源。
`addCss()`和`addJs()`的第二个参数表示资源是否为本地资源(true为local,false为remote)。默认情况下,Assets管理器将假定资源是本地的:
```php
<?php
public function indexAction()
{
// Add some remote CSS resources
$this->assets->addCss('//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css', false);
// Then add some local CSS resources
$this->assets->addCss('css/style.css', true);
$this->assets->addCss('css/extra.css');
}
```
## 集合
集合组相同类型的资源。Assets管理器隐式创建两个集合:`css`和`js` 。您可以创建其他集合以对特定资源进行分组,以便更轻松地将这些资源放置在视图中:
```php
<?php
// Javascripts in the header
$headerCollection = $this->assets->collection('header');
$headerCollection->addJs('js/jquery.js');
$headerCollection->addJs('js/bootstrap.min.js');
// Javascripts in the footer
$footerCollection = $this->assets->collection('footer');
$footerCollection->addJs('js/jquery.js');
$footerCollection->addJs('js/bootstrap.min.js');
```
然后在视图中:
```php
<html>
<head>
<title>Some amazing website</title>
<?php $this->assets->outputJs('header'); ?>
</head>
<body>
<!-- ... -->
<?php $this->assets->outputJs('footer'); ?>
</body>
<html>
```
Volt语法:
```twig
<html>
<head>
<title>Some amazing website</title>
{{ assets.outputCss('header') }}
</head>
<body>
<!-- ... -->
{{ assets.outputJs('footer') }}
</body>
<html>
```
## URL前缀
集合可以是URL前缀,这使您可以随时轻松地从一台服务器更改为另一台服务器:
```php
<?php
$footerCollection = $this->assets->collection('footer');
if ($config->environment === 'development') {
$footerCollection->setPrefix('/');
} else {
$footerCollection->setPrefix('http:://cdn.example.com/');
}
$footerCollection->addJs('js/jquery.js');
$footerCollection->addJs('js/bootstrap.min.js');
```
链式语法也可用:
```php
<?php
$headerCollection = $assets
->collection('header')
->setPrefix('http://cdn.example.com/')
->setLocal(false)
->addJs('js/jquery.js')
->addJs('js/bootstrap.min.js');
```
## 压缩/过滤
`Phalcon\Assets` 提供JavaScript和CSS资源的内置压缩。您可以创建一组资源,指示Assets管理器必须过滤哪些资源以及必须保留哪些资源。 除此之外,[Douglas Crockford](http://www.crockford.com) 的 `Jsmin` 是核心扩展的一部分,提供JavaScript文件的缩小以获得最佳性能。 在CSS领域, [Ryan Day](https://github.com/soldair)的`CSSMin` 也可用于缩小CSS文件。
以下示例显示如何压缩资源集合:
```php
<?php
$manager
// These JavaScripts are located in the page's bottom
->collection('jsFooter')
// The name of the final output
->setTargetPath('final.js')
// The script tag is generated with this URI
->setTargetUri('production/final.js')
// This is a remote resource that does not need filtering
->addJs('code.jquery.com/jquery-1.10.0.min.js', false, false)
// These are local resources that must be filtered
->addJs('common-functions.js')
->addJs('page-functions.js')
// Join all the resources in a single file
->join(true)
// Use the built-in Jsmin filter
->addFilter(
new Phalcon\Assets\Filters\Jsmin()
)
// Use a custom filter
->addFilter(
new MyApp\Assets\Filters\LicenseStamper()
);
```
集合可以包含JavaScript或CSS资源,但不能同时包含两者。某些资源可能是远程的,也就是说,它们是通过HTTP从远程源获取的,以便进一步过滤。建议将外部资源转换为本地资源以获得更好的性能。
如上所示, `addJs()` 方法用于向集合添加资源,第二个参数指示资源是否为外部资源,第三个参数指示资源是应该过滤还是保留原样:
```php
<?php
// These Javascripts are located in the page's bottom
$jsFooterCollection = $manager->collection('jsFooter');
// This a remote resource that does not need filtering
$jsFooterCollection->addJs('code.jquery.com/jquery-1.10.0.min.js', false, false);
// These are local resources that must be filtered
$jsFooterCollection->addJs('common-functions.js');
$jsFooterCollection->addJs('page-functions.js');
```
过滤器在集合中注册,允许多个过滤器,资源中的内容按照过滤器注册的顺序进行过滤:
```php
<?php
// Use the built-in Jsmin filter
$jsFooterCollection->addFilter(
new Phalcon\Assets\Filters\Jsmin()
);
// Use a custom filter
$jsFooterCollection->addFilter(
new MyApp\Assets\Filters\LicenseStamper()
);
```
请注意,内置和自定义过滤器都可以透明地应用于集合。最后一步是确定集合中的所有资源是否必须连接到单个文件中,或者单独为每个资源提供服务。要告诉集合必须连接所有资源,可以使用`join()` 方法。
如果要连接资源,我们还需要定义将用于存储资源的文件以及将用于显示资源的URI。使用`setTargetPath()``setTargetUri()`设置这些:
```php
<?php
$jsFooterCollection->join(true);
// The name of the final file path
$jsFooterCollection->setTargetPath('public/production/final.js');
// The script HTML tag is generated with this URI
$jsFooterCollection->setTargetUri('production/final.js');
```
### 内置过滤器
Phalcon提供了2个内置过滤器来缩小JavaScript和CSS,它们的C-backend提供了执行此任务的最小开销:
| 过滤器 |描述 |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `Phalcon\Assets\Filters\Jsmin` | 通过删除Javascript解释器/编译器忽略的不必要的字符来压缩JavaScript|
| `Phalcon\Assets\Filters\Cssmin` |通过删除已被浏览器忽略的不必要字符来压缩CSS |
### 自定义过滤器
除了内置过滤器,您还可以创建自己的过滤器。这些可以利用现有的和更高级的工具,如[YUI](http://yui.github.io/yuicompressor/),[Sass](http://sass-lang.com/),[Closure](https://developers.google.com/closure/compiler/)等:
```php
<?php
use Phalcon\Assets\FilterInterface;
/**
* Filters CSS content using YUI
*
* @param string $contents
* @return string
*/
class CssYUICompressor implements FilterInterface
{
protected $options;
/**
* CssYUICompressor constructor
*
* @param array $options
*/
public function __construct(array $options)
{
$this->options = $options;
}
/**
* Do the filtering
*
* @param string $contents
*
* @return string
*/
public function filter($contents)
{
// Write the string contents into a temporal file
file_put_contents('temp/my-temp-1.css', $contents);
system(
$this->options['java-bin'] .
' -jar ' .
$this->options['yui'] .
' --type css ' .
'temp/my-temp-file-1.css ' .
$this->options['extra-options'] .
' -o temp/my-temp-file-2.css'
);
// Return the contents of file
return file_get_contents('temp/my-temp-file-2.css');
}
}
```
用法:
```php
<?php
// Get some CSS collection
$css = $this->assets->get('head');
// Add/Enable the YUI compressor filter in the collection
$css->addFilter(
new CssYUICompressor(
[
'java-bin' => '/usr/local/bin/java',
'yui' => '/some/path/yuicompressor-x.y.z.jar',
'extra-options' => '--charset utf8',
]
)
);
```
在前面的示例中,我们使用了名为`LicenseStamper`的自定义过滤器:
```php
<?php
use Phalcon\Assets\FilterInterface;
/**
* Adds a license message to the top of the file
*
* @param string $contents
*
* @return string
*/
class LicenseStamper implements FilterInterface
{
/**
* Do the filtering
*
* @param string $contents
* @return string
*/
public function filter($contents)
{
$license = '/* (c) 2015 Your Name Here */';
return $license . PHP_EOL . PHP_EOL . $contents;
}
}
```
## 自定义输出
`outputJs()` 和 `outputCss()`方法可用于根据每种类型的资源生成必要的HTML代码。您可以通过以下方式覆盖此方法或手动打印资源:
```php
<?php
use Phalcon\Tag;
$jsCollection = $this->assets->collection('js');
foreach ($jsCollection as $resource) {
echo Tag::javascriptInclude(
$resource->getPath()
);
}
```
## 提高性能
有许多方法可以优化处理资源。我们将在下面描述一种简单的方法,允许直接通过Web服务器处理资源以优化响应时间。
首先,我们需要设置 Assets管理器。我们将使用基本控制器,但您可以使用服务提供商或任何其他地方:
```php
<?php
namespace App\Controllers;
use Phalcon\Mvc\Controller;
use Phalcon\Assets\Filters\Jsmin;
/**
* App\Controllers\ControllerBase
*
* This is the base controller for all controllers in the application.
*/
class ControllerBase extends Controller
{
public function onConstruct()
{
$this->assets
->useImplicitOutput(false)
->collection('global')
->addJs('https://code.jquery.com/jquery-3.2.1.js', false, true)
->addFilter(new Jsmin());
}
}
```
然后我们必须配置路由:
```php
<?php
/*
* Define custom routes.
* This file gets included in the router service definition.
*/
$router = new Phalcon\Mvc\Router();
$router->addGet('/assets/(css|js)/([\w.-]+)\.(css|js)', [
'controller' => 'assets',
'action' => 'serve',
'type' => 1,
'collection' => 2,
'extension' => 3,
]);
// Other routes...
```
最后,我们需要创建一个控制器来处理资源请求:
```php
<?php
namespace App\Controllers;
use Phalcon\Http\Response;
/**
* Serve site assets.
*/
class AssetsController extends ControllerBase
{
public function serveAction() : Response
{
// Getting a response instance
$response = new Response();
// Prepare output path
$collectionName = $this->dispatcher->getParam('collection');
$extension = $this->dispatcher->getParam('extension');
$type = $this->dispatcher->getParam('type');
$targetPath = "assets/{$type}/{$collectionName}.{$extension}";
// Setting up the content type
$contentType = $type == 'js' ? 'application/javascript' : 'text/css';
$response->setContentType($contentType, 'UTF-8');
// Check collection existence
if (!$this->assets->exists($collectionName)) {
return $response->setStatusCode(404, 'Not Found');
}
// Setting up the Assets Collection
$collection = $this->assets
->collection($collectionName)
->setTargetUri($targetPath)
->setTargetPath($targetPath);
// Store content to the disk and return fully qualified file path
$contentPath = $this->assets->output($collection, function (array $parameters) {
return BASE_PATH . '/public/' . $parameters[0];
}, $type);
// Set the content of the response
$response->setContent(file_get_contents($contentPath));
// Return the response
return $response;
}
}
```
如果文件系统中存在预编译资源,则必须由Web服务器直接提供。因此,要获得静态资源的好处,我们必须更新服务器配置。我们将使用Nginx的示例配置。对于Apache来说,它会有所不同:
```nginx
location ~ ^/assets/ {
expires 1y;
add_header Cache-Control public;
add_header ETag "";
# If the file exists as a static file serve it directly without
# running all the other rewrite tests on it
try_files $uri $uri/ @phalcon;
}
location / {
try_files $uri $uri/ @phalcon;
}
location @phalcon {
rewrite ^(.*)$ /index.php?_url=$1;
}
# Other configuration
```
我们需要在应用程序的文档根目录中创建`assets/js`和`assets/css`目录(例如`public`)。
每当用户使用`/assets/js/global.js`类型的地址请求资源时,如果文件系统中没有此文件,请求将被重定向到 `AssetsController` 。否则,资源将由Web服务器处理。
这不是最好的例子。但是,它反映了主要思想:使用应用程序合理配置Web服务器可以帮助优化多倍的响应时间。
在专用文章Web服务器设置和路由中了解有关Web服务器设置和路由的详细信息。
- 常规
- Welcome
- 贡献
- 生成回溯
- 测试重现
- 单元测试
- 入门
- 安装
- Web服务器设置
- WAMP
- XAMPP
- 教程
- 基础教程
- 教程:创建一个简单的REST API
- 教程:Vökuró
- 提升性能
- 教程:INVO
- 开发环境
- Phalcon Compose (Docker)
- Nanobox
- Phalcon Box (Vagrant)
- 开发工具
- Phalcon开发者工具的安装
- Phalcon开发者工具的使用
- 调试应用程序
- 核心
- MVC应用
- 微应用
- 创建命令行(CLI)应用程序
- 依赖注入与服务定位
- MVC架构
- 服务
- 使用缓存提高性能
- 读取配置
- 上下文转义
- 类加载器
- 使用命名空间
- 日志
- 队列
- 数据库
- 数据库抽象层
- Phalcon查询语言(PHQL)
- ODM(对象文档映射器)
- 使用模型
- 模型行为
- ORM缓存
- 模型事件
- 模型元数据
- 模型关系
- 模型事务
- 验证模型
- 数据库迁移
- 分页
- 前端
- Assets管理
- 闪存消息
- 表单
- 图像
- 视图助手(标签)
- 使用视图
- Volt:模板引擎
- 业务逻辑
- 访问控制列表(ACL)
- 注解解析器
- 控制器
- 调度控制器
- 事件管理器
- 过滤与清理
- 路由
- 在session中存储数据
- 生成URL和路径
- 验证
- HTTP
- Cookies管理
- 请求环境
- 返回响应
- 安全
- 加密/解密
- 安全
- 国际化
- 国际化
- 多语言支持