Pull to refresh

Автоматическое подключение css и js файлов в Yii

Reading time6 min
Views25K
Доброго времени суток.

На этот раз хочу, рассказать о способе автоматического подключения css и js файлов в Yii. Идея заключается в том, что бы к каждому файлу вида привязывать соответствующую папку с ресурсами (css, js, images). Это удобно, т.к. в большенстве случаев конкретные «assets» используются для конкретных файлов вида.

И так, ближе к коду. Расширим класс Controller (который наверняка лежит у вас в папке «components» :)), добавив в него следующую функциональность:

/**
 * Array of paths of assets 
 * @var array
 */
private $_assetsPaths = 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) 
{
    if (($publishedUrl = $this->getPublishedAssetsUrl($view))) {
        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) 
{
    if (($path = $this->getAssetsPath($view))) {
        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) 
{
    if (($publishedUrl = $this->getPublishedAssetsUrl($view))) {
        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) 
{
    if (($path = $this->getAssetsPath($view))) {
        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) 
{
    if (($publishedUrl = $this->getPublishedAssetsUrl($view))) {
        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) 
{
    if (($path = $this->getAssetsPath($view))) {
        return $path . DIRECTORY_SEPARATOR . $this->_imageDirName . DIRECTORY_SEPARATOR .  $fileName;
    }

    return false;  
}

/**
 * Returns alias of assets
 * 
 * @param string $view
 * @return string|false
 */
protected function getAssetsPath($view) 
{
    if (!array_key_exists($view, $this->_assetsPaths)) {
        $assetPath = false;

        $viewPath = $this->getViewFile($view);
        if ($viewPath) {
            if (($pos = strrpos($viewPath, DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR)) !== false) {
                $extension = ($renderer=Yii::app()->getViewRenderer()) !== null ? 
                    $renderer->fileExtension : 
                    '.php';

                $assetPath = substr($viewPath, 0, $pos) . DIRECTORY_SEPARATOR 
                           . 'assets'
                           . substr($viewPath, $pos + 1 + strlen('views'));
                $assetPath = dirname($assetPath) . DIRECTORY_SEPARATOR .  basename($assetPath, $extension);
            }
        }

        $this->_assetsPaths[$view] = $assetPath;
    }

    return $this->_assetsPaths[$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 = $this->getAssetsPath($view);
        if ($assetsPath) {
            $assetsUrl = Yii::app()->assetManager->publish($assetsPath);
        }

        $this->_assetsUrl[$view] = $assetsUrl;
    }

    return $this->_assetsUrl[$view];
}    

Разберем как это работает. В «beforeRender($view)» перед рендерингом вызываются методы:

// Подключение скриптов (по умолчанию подключает файл по пути assets/{controllerName}/{viewName}/js/index.js)
_setupScript($view) 

// Подключение стилей (по умолчанию подключает файл по пути assets/{controllerName}/{viewName}/css/index.css)
_setupCss($view)

В них происходит автоматическое подключение соответствующих 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));


На это всё. Всем спасибо за внимание.
Tags:
Hubs:
+6
Comments16

Articles

Change theme settings