Доброго времени суток.
На этот раз хочу, рассказать о способе автоматического подключения css и js файлов в Yii. Идея заключается в том, что бы к каждому файлу вида привязывать соответствующую папку с ресурсами (css, js, images). Это удобно, т.к. в большенстве случаев конкретные «assets» используются для конкретных файлов вида.
И так, ближе к коду. Расширим класс Controller (который наверняка лежит у вас в папке «components» :)), добавив в него следующую функциональность:
/**
* Array of alias of assets
* @var array
*/
private $_assetsAlias = array();
/**
* Array of asset Url
* @var array
*/
private $_assetsUrl = array();
/**
* Name of directory for css files
* @var strign
*/
protected $_cssDirName = 'css';
/**
* Default file name of css
* @var string
*/
protected $_defaultCssFile = 'index.css';
/**
* Name of directory for script files
* @var strign
*/
protected $_scriptDirName = 'js';
/**
* Default file name of script
* @var string
*/
protected $_defaultScriptFile = 'index.js';
/**
* Name of directory for images
* @var strign
*/
protected $_imageDirName = 'images';
/**
* This method is invoked at the beginning of {@link render()}.
*
* @param string $view the view to be rendered
* @return boolean whether the view should be rendered.
*/
protected function beforeRender($view)
{
$this->_setupScript($view);
$this->_setupCss($view);
$viewCamelCase = preg_replace_callback(
'/_([a-z0-9])/',
function ($char) {
return strtoupper($char[1]);
},
ucfirst($view)
);
$methodScript = '_setupScript' . $viewCamelCase;
if (method_exists($this, $methodScript)) {
$this->$methodScript($view);
}
$methodCss = '_setupCss' . $viewCamelCase;
if (method_exists($this, $methodCss)) {
$this->$methodCss($view);
}
return true;
}
/**
* Setup script files
*
* @param string $view
* @return void
*/
protected function _setupScript($view)
{
$scriptRealPath = $this->getScriptPath($view, $this->_defaultScriptFile);
if (is_file($scriptRealPath)) {
$scriptPublishedUrl = $this->getScriptUrl($view, $this->_defaultScriptFile);
Yii::app()->clientScript->registerScriptFile($scriptPublishedUrl);
}
}
/**
* Setup css files
*
* @param string $view
* @return void
*/
protected function _setupCss($view)
{
$cssRealPath = $this->getCssPath($view, $this->_defaultCssFile);
if (is_file($cssRealPath)) {
$cssPublishedUrl = $this->getCssUrl($view, $this->_defaultCssFile);
Yii::app()->clientScript->registerCssFile($cssPublishedUrl);
}
}
/**
* Returns the published script URL
*
* @param string $view
* @param string $fileName
* @return string|false
*/
public function getScriptUrl($view, $fileName)
{
$PublishedUrl = $this->getPublishedAssetsUrl($view);
if ($PublishedUrl) {
return $PublishedUrl . '/' . $this->_scriptDirName . '/' . $fileName;
}
return false;
}
/**
* Returns the real script Path
*
* @param string $fileName
* @param string $view
* @return string|false
*/
public function getScriptPath($view, $fileName)
{
$path = Yii::getPathOfAlias($this->getAssetsAlias($view));
if ($path) {
return $path . DIRECTORY_SEPARATOR . $this->_scriptDirName . DIRECTORY_SEPARATOR . $fileName;
}
return false;
}
/**
* Returns the published css URL
*
* @param string $view
* @param string $fileName
* @return string|false
*/
public function getCssUrl($view, $fileName)
{
$PublishedUrl = $this->getPublishedAssetsUrl($view);
if ($PublishedUrl) {
return $PublishedUrl . '/' . $this->_cssDirName . '/' . $fileName;
}
return false;
}
/**
* Returns the real css path
*
* @param string $view
* @param string $fileName
* @return string|false
*/
public function getCssPath($view, $fileName)
{
$path = Yii::getPathOfAlias($this->getAssetsAlias($view));
if ($path) {
return $path . DIRECTORY_SEPARATOR . $this->_cssDirName . DIRECTORY_SEPARATOR . $fileName;
}
return false;
}
/**
* Returns the published image URL
*
* @param string $view
* @param string $fileName
* @return string|false
*/
public function getImageUrl($view, $fileName)
{
$PublishedUrl = $this->getPublishedAssetsUrl($view);
if ($PublishedUrl) {
return $PublishedUrl . '/' . $this->_imageDirName . '/' . $fileName;
}
return false;
}
/**
* Returns the real image path
*
* @param string $view
* @param string $fileName
* @return string|false
*/
public function getImagePath($view, $fileName)
{
$path = Yii::getPathOfAlias($this->getAssetsAlias($view));
if ($path) {
return $path . DIRECTORY_SEPARATOR . $this->_imageDirName . DIRECTORY_SEPARATOR . $fileName;
}
return false;
}
/**
* Returns alias of assets
*
* @param string $view
* @return string|false
*/
protected function getAssetsAlias($view)
{
if (!array_key_exists($view, $this->_assetsAlias)) {
$assetsAlias = false;
$viewPath = $this->getViewFile($view);
if ($viewPath && ($pos = strpos($viewPath, ROOT_PATH)) === 0) {
$viewPath = substr($viewPath, strlen(ROOT_PATH) + 1);
if (($pos = strpos($viewPath, '.')) !== false) {
$viewPath = substr($viewPath, 0, $pos);
}
$viewElements = explode(DIRECTORY_SEPARATOR, $viewPath);
if (($key = array_search('views', $viewElements))) {
$viewElements[$key] = 'assets';
}
$assetsAlias = implode($viewElements, '.');
}
$this->_assetsAlias[$view] = $assetsAlias;
}
return $this->_assetsAlias[$view];
}
/**
* Returns the published asset URL
*
* @param string $view
* @return string|false
*/
public function getPublishedAssetsUrl($view)
{
if (!array_key_exists($view, $this->_assetsUrl)) {
$assetsUrl = false;
$assetsPath = Yii::getPathOfAlias($this->getAssetsAlias($view));
if ($assetsPath) {
$assetsUrl = Yii::app()->assetManager->publish(
Yii::getPathOfAlias($this->getAssetsAlias($view))
);
}
$this->_assetsUrl[$view] = $assetsUrl;
}
return $this->_assetsUrl[$view];
}
Разберем как это работает. В «beforeRender($view)» перед рендерингом вызываются методы:
_setupScript($view) // Подключение скриптов (по умолчанию подключает файл по пути assets/{controllerName}/{viewName}/js/index.js)
_setupCss($view) // Подключение стилей (по умолчанию подключает файл по пути assets/{controllerName}/{viewName}/css/index.css)
В них происходит автоматическое подключение соответствующих css и js файлов для заданного файла вида.
Далее, здесь же в «beforeRender()» запускаются дополнительные методы для подключения стилей и скриптов (если они определены). Отличие этих методов от предыдущих в том, что они привязаны к конкретному файлу вида. Т.е. в формировании названия соответствующего метода участвует имя файла вида, например: имя метода для скриптов складывается из правила: "_setupScript" + «Имя файла вида в верблюжьей нотации», для стилей: "_setupCss" + «Имя файла вида в верблюжьей нотации».
Так же теперь нам доступны следующие методы.
Методы возвращающие URL адреса до опубликованных ресурсов:
getScriptUrl($view, $fileName) // возвращает URL адрес до js файла
getCssUrl($view, $fileName) // возвращает URL адрес до css файла
getImageUrl($view, $fileName) // возвращает URL адрес до файла изображения
Методы возвращающие реальные пути ресурсов (в папке assets в protected):
getScriptPath($view, $fileName) // возвращает путь до js файл
getCssPath($view, $fileName) // возвращает путь до css файл
getImagePath($view, $fileName) // возвращает путь до файл изображения
И общие методы:
getAssetsAlias($view) // возвращает алиас до папки "assets", которая лежит в protected
getPublishedAssetsUrl($view) // возвращает URL адрес до опубликованной директории "assets"
Имена директорий (для js, css файлов и изображений) и файлов по умолчанию определены в свойствах класса контроллера.
protected $_cssDirName = 'css';
protected $_defaultCssFile = 'index.css';
protected $_scriptDirName = 'js';
protected $_defaultScriptFile = 'index.js';
protected $_imageDirName = 'images';
Соответственно вы можете изменить их на нужные вам. По желанию можно вынести их в конфиг приложения, проделав несложные модификации в коде.
Использование.
Вы можете либо переопределить метод "_setupCss($view)", если вам нужно подключать css файлы для всех возможных видов контроллера:
/**
* Setup css files
*
* @param string $view
* @return void
*/
protected function _setupCss($view)
{
parent::_setupCss($view);
// будет искать my_css_file.css для каждого файла вида
Yii::app()->clientScript->registerCssFile($this->getCssUrl($view, 'my_css_file.css'));
}
Либо создать метод "_setupCss" + «Имя файла вида в верблюжьей нотации», если вам нужно подключать css файлы для конкретного файла вида:
/**
* Setup css files
*
* @param string $view
* @return void
*/
protected function _setupCssRegistration($view)
{
Yii::app()->clientScript->registerCssFile($this->getCssUrl($view, 'my_css_file.css'));
}
Данный метод будет вызван только при рендеринге «registration»
Картинки можно получать так:
CHtml::image($this->getImageUrl($view));
На это всё. Всем спасибо за внимание. Надеюсь моя статься будет хоть кому-то полезной.
Автор: Nilov_A