[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管理
- 請求環境
- 返回響應
- 安全
- 加密/解密
- 安全
- 國際化
- 國際化
- 多語言支持