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

в 3:14, , рубрики: yii, метки:

Доброго времени суток.

На этот раз хочу, рассказать о способе автоматического подключения 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

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js