Skip to content

Latest commit

 

History

History

Helper

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

FormHelper

Добавлено несколько параметров для метода control():

  • append - добавить произвольный текст после input, строка;
  • sub - append, обёрнутый в тег <sub>, строка;
  • inputTemplate - использовать другой шаблон вместо шаблона input, строка - название шаблона. В кейке есть похожая возможность - задать содержимое шаблона в опциях в массиве templates. Но так нужно копипастить содержимое. Я сделал, чтобы можно было один раз определить шаблон в конфиге, и использовать его по имени;
  • divAttrs - атрибуты для тега <div> в шаблоне inputDiv (тот <div>, в который обёрнуты input и его label), массив;
  • container - использовать нестандартный контейнер. Значение:
    • Строка - название шаблона,
    • Либо массив: элемент 'template' - название шаблона, а все остальные элементы массива станут атрибутами;
  • containerClass - сокращение для ['container']['class'], строка;

Добавлен контейнер noDivContainer, в котором input и label не обёрнуты в <div>, как в обычном inputContainer

AssetHelper

Автоматическая загрузка ассетов js и css, и управление их зависимостями. А также передача параметров в из php в javascript

Загрузка ассетов

Метод AssetHelper->load(?string $controller, ?string $action): void выведет теги, подключающие скрипты и стили, в соответствующие блоки. То есть где-то (скорее всего в layout) эти блоки должны быть выведены методами:

  • echo $this->Asset->fetchScripts();
  • echo $this->Asset->fetchStyles();
  • echo $this->Asset->fetchScriptsBottom();

При выводе таким способом всем скриптам и стилям автоматически пропишется базовый урл (URL_PREFIX в crm) и версия (версия задаётся вызовом Asset->setAssetVersion() при инициализации в классе View)

При вызове load() без параметров контроллер и экшн будут взяты из текущего реквеста. При вызове с параметрами они должны быть в lowerCamelCase.

Файлы скриптов и стилей можно задать явно в конфиге, но это лучше делать только для внешних зависимостей. Для наших скриптов и стилей путь к файлу можно не задавать, если он соответствует конвенции: В папках webroot/js и webroot/css делается структура папок и файлов аналогичная структуре src/Template: На каждый контроллер - папка в UpperCamelCase, на каждый экшн - файл в snake_case. Шаблоны handlebars располагаются рядом с использующими их скриптами и имеют то же имя файла и расширение .hbs.

Если папка или файл отсутствуют, то они просто не подгрузятся.

Если же путь к файлу задан явно, и такого файла нет, то будет ошибка.

Все ассеты загружаются 1 раз, даже если load был вызван несколько раз или если одна зависимость была использована несколько раз.

Зависимости любой вложенности нормально прогружаются (т.е. при вызове load нормально загрузится её зависимость зависимости зависимости зависимости зависимости зависимости).

Сначала загружаются зависимости, а уже потом то, что от них зависит.

Есть обнаружение циклических зависимостей (ассет1 зависит от ассет2, а ассет2 зависит от ассет1. В таком случае кидается ошибка)

Конфигурация ассета

Конфиг имеет формат:

[
	controllerName => [ // camelCase
		actionName => [ // camelCase
			// все параметры не обязательны
		
			self::KEY_SCRIPT => path_to_script,     // по умолчанию возьмётся controllerName/actionName
			self::KEY_TEMPLATE => path_to_template, // шаблон handlebars, по умолчанию возьмётся controllerName/actionName
			self::KEY_STYLE => path_to_style,       // по умолчанию возьмётся controllerName/actionName
			// эти 3 параметра могут быть либо строкой, либо массивом строк для загрузки нескольких файлов сразу
			// пути начинаются с папки webroot (не включая саму папку webroot) без слеша в начале
			
			self::KEY_IS_BOTTOM => false,           // скрипт подключается внизу body или в head. По умолчанию = false, т.е. head
			self::KEY_DEPEND => [
				'controllerName1.actionName1',		// зависимости вот в таком формате
				'controllerName1.actionName2',		// можно задать зависимость на ассет, не определённый в конфиге, если его файлы соответствуют конвенции именования
				'controllerName2.actionName3',
			],
			self::KEY_VARS => [						// проверять, что нужные переменные переданы в js 
				'varName' => self::TYPE_STRING,		// и что они именно такого типа
				'varName2' => self::TYPE_JSON,
			]
		],
		actionName2 => [...],
		...
	],
	controllerName2 => [...],
	...
]

Конфиг определён в соответствии с InstanceConfigTrait, т.е. сам конфиг лежит в свойстве _config, доступ к нему через setConfig и getConfig, значения по-умолчанию - в свойстве _defaultConfig.

Как правильно работать с конфигом:

  • Все внешние зависимости определить в _defaultConfig, в качестве controllerName использовать 'assets', пути к файлам задавать явно.
  • Наши библиотечные файлы (которые лежат в папке Lib) тоже настраиваются в _defaultConfig, если их вообще нужно настраивать. Если от них нужны только 1 скрипт и 1 стиль, и они названы по конвенции, то настраивать ничего не нужно, зависимости нормально подгрузятся.
  • Настройки ассета для экшна делаются внутри шаблона (файла .ctp), чтобы не превращать конфиг в помойку. К тому же, они используются только в одном месте. Для этого сделаны методы:
    • setConfigs(array $configs, bool $merge = true) - задать несколько конфигов, второй параметр - merge/overwrite. Формат такой, как описано выше.
    • setActionConfig(string $controller, string $action, array $config, $merge = true) - задать конфиг на 1 экшн. Соответственно, controllerName и actionName в массиве не нужны, нужна только внутренняя часть.
    • setCurrentConfig(array $config, $merge = true) - как setActionConfig, но контроллер и экшн берутся из текущего реквеста.
    • addDependencies(string[] $dependencies) - задать для текущего экшна только зависимости.
    • addDependency(string $folder, string $file) - задать для текущего экшна только 1 зависимость, параметры в lowerCamelCase.
    • addLayoutDependency(string $folder, string $file) - задать зависимть для Layout'а. Они прогужаются раньше зависимостей акшна.
    • setCurrentBottom() - задать текущему экшну флаг IS_BOTTOM = true, т.е. грузить его снизу, а не в head.

Передача параметров из php в js

При вызове load() перед всеми скриптами делается тег <script>, в который пишутся все нужные переменные. Они правильно сериализуются (строки в кавычках, кавычки внутри строк заэкранированы, для массивов - json_encode и т д), а названия переменных проверяются на содержание плохих символов и соответствие конвенции. Переменные грузятся в <head>. Если <head> уже был отрендерен, (т.е. был вызван fetchScripts()), то они загрузятся вниз. Если оба блока скриптов были отрендерены, то кинется ошибка.

  • setVars(array $variables, bool|array $overwrite = false) - передача переменных. Ключ - название переменной, значение - значение переменной. Названия переменных должны быть в lowerCamelCase (при обнаружении подчёркиваний выкидывается ошибка). $overwrite - перезаписывать ли переменные, определённые ранее. True/false - для всех переменных, но можно в массиве задать для каждой отдельно. Если перезаписывать нельзя, а такая переменныя уже была определена, то кидается ошибка. Если перезаписывать можно, но переменная уже была выведена (был вызван load()), то тоже будет ошибка.
  • setConsts() - то же самое, но названия должны быть в UPPER_SNAKE_CASE (т.е. ошибка при наличии символов в нижнем регистре)

Минификация

Для всех локальных JS скриптов вида имя.js ищется файл имя.min.js, и если такой есть - то прикрепляется.