Функции хелперы для MODX
Друзья, поздравляю всех с наступающим Новым годом! Надеюсь, в новом году мы преодолеем все трудности и нам всем улыбнётся удача!

Ещё я хочу представить новую разработку в сфере улучшения процесса разработки — функции для работы с MODX.
Это глобальные функции, которые можно использовать в любом месте — и в сниппетах, и в классах, и даже в чанках и шаблонах, если установлен Fenom. В данный момент доступно около 50 функций:
# Получить данные из кэша
# Отправка почты
# Получить последний ресурс.
# Последние 10 ресурсов.
# Массив с заголовками ресурсов родителя с id=20. Можно использовать для формирования селекта.
# Записать значение в сессию
# Проверить авторизован ли пользователь
# Проверить валидность email
# Переместить ресурсы от одного родителя другому и установить другой шаблон
# Удалить дочерние ресурсы родителя с id = 20
# Получить количество заблокированных пользователей
# Получить количество пользователей с подготовкой запроса
Подробное описание доступно тут. Дублировать не буду. Мне кажется это должно понравиться разработчикам. Это только первая бета версия и потенциала для развития ещё много. Было бы неплохо развивать эту библиотеку всем вместе. В общем, пробуйте. Надеюсь, пригодится.
Проект на GitHub.
П.С. Друзья, есть мнение, что это никому не нужная и бесполезная вещь. Просьба ко всем кто не согласен с данным мнением поставить звёздочку у проекта на гитхабе. Ну и здесь плюсик важен. Хочу понять объективную потребность.

Ещё я хочу представить новую разработку в сфере улучшения процесса разработки — функции для работы с MODX.
Это глобальные функции, которые можно использовать в любом месте — и в сниппетах, и в классах, и даже в чанках и шаблонах, если установлен Fenom. В данный момент доступно около 50 функций:
- url() — генерирует url.
- redirect() — переадресация на указанный url или страницу, если указан id.
- forward() — выводит указанную страницу без изменения url.
- abort() — переадресация на страницу ошибки.
- config() — работа с массивом настроек.
- session() — работа с сессией.
- cache() — управляет кэшем.
- parents() — возвращает массив родителей указанного ресурса.
- children() — возвращает массив дочерних ресурсов.
- pls() — чтение/установка прейсхолдеров.
- pls_delete() — используется для удаления плейсхолдеров.
- lang() — для работы с лексиконом.
- email() — отправка почты.
- email_user() — отправка почты пользователю.
- quote() — экранирует строку.
- esc() — оборачивает спец. символом драйвера базы данных.
- css() — подключает стили.
- script() — подключает скрипты.
- html() — подключает HTML разметку.
- chunk() — вызывает указанный чанк.
- snippet() — вызывает указанный сниппет.
- processor() — вызывает процессор.
- is_auth() — проверяет, авторизован ли пользователь в указанном контексте.
- is_guest() — проверка, является ли пользователь гостем.
- can() — проверка прав.
- resource_id() — получает id текущего ресурса.
- template_id() — получает id шаблона текущего ресурса.
- user_id() — получает id текущего пользователя.
- tv() — получает TV текущего ресурса.
- object() — функция для работы с объектами MODX.
- collection() — функция для работы с коллекциями объектов MODX.
- resource() — функция для работы с ресурсами MODX.
- resources() — функция для работы с коллекцией ресурсов MODX.
- user() — функция для работы с пользователями MODX.
- users() — функция для работы с коллекцией пользователей MODX.
- object_exists() — проверка существования объекта с указанными свойствами.
- resource_exists() — проверка существования ресурсов.
- user_exists() — проверка существования пользователей.
- str_clean() — очищает строку от указанных символов.
- table_name() — выводит название таблицы класса.
- columns() — выводит список полей таблицы класса.
- is_url() — проверка валидности url.
- is_email() — проверка валидности email.
- log_error() — запись в журнал ошибок для уровня логирования ERROR.
- log_warn() — запись в журнал ошибок для уровня логирования WARN.
- log_info() — запись в журнал ошибок для уровня логирования INFO.
- log_debug() — запись в журнал ошибок для уровня логирования DEBUG.
- context() — Выводит указанное свойство текущего контента. По-умолчанию это ключ.
- query() — для работы с сырыми SQL запросами.
- memory() — выводит отформатированную строку используемой памяти.
- img() — формирует HTML тэг img.
- faker() — создает фейковые данные.
Немного примеров
# Проверка существования пользователя по emailif (user_exists(['email'=>'admin@mail.ru']) {
// Пользователь с таким email существует
}# Получить данные из кэша
$value = cache('key', 'my_data');
// Альтернативный вариант
$value = cache()->get('key', 'my_data');# Отправка почты
email('pupsik@mail.ru', 'Тема','Содержание письма');
// Пользователю
email_user('admin', $subject, $content);# Получить последний ресурс.
$resourceObject = resource()->last(); // Объект ресурса
$resourceArray = resource()->last()->toArray(); // Массив с данными ресурса# Последние 10 ресурсов.
$resObjects = resources()->last(10);# Массив с заголовками ресурсов родителя с id=20. Можно использовать для формирования селекта.
$titles= resources()->where(['parent'=>20])->get('pagetitle'); // array('pagetitle 1', 'pagetitle 2', 'pagetitle 3')# Записать значение в сессию
session('key1.key2', 'value'); // => $_SESSION['key1']['key2'] = $value;
//# Получить значение из сессии
$value = session('key1.key2'); // $value = $_SESSION['key1']['key2']# Проверить авторизован ли пользователь
if (is_auth) {} // альтернатива $modx->user->isAuthenticated($modx->context->key)# Проверить валидность email
if (is_email($_POST['email'])) {
// Почта валидная
}# Переместить ресурсы от одного родителя другому и установить другой шаблон
resources()->where(['parent'=>20])->set(['parent'=>5, 'tempate'=>1]);# Удалить дочерние ресурсы родителя с id = 20
collection('modResource')->where(['parent'=>20])->remove();
// Для ресурсов есть своя функция
resources()->where(['parent'=>20])->remove();# Получить количество заблокированных пользователей
$count = users()->profile()->where(['Profile.blocked'=>1])->count();# Получить количество пользователей с подготовкой запроса
$userArray = query('select * from ' . table_name('modUser'). ' WHERE id < ?')->execute(10);
// или так
$userArray = query('select * from ' . table_name('modUser'). ' WHERE id < ?')->bind(10)->execute();
// или так // $_POST['email'] = 'user@mail.ru'
$userArray = query('select * from ' . table_name('modUser'). ' WHERE id < :email')->bind($_POST)->execute();Подробное описание доступно тут. Дублировать не буду. Мне кажется это должно понравиться разработчикам. Это только первая бета версия и потенциала для развития ещё много. Было бы неплохо развивать эту библиотеку всем вместе. В общем, пробуйте. Надеюсь, пригодится.
Проект на GitHub.
П.С. Друзья, есть мнение, что это никому не нужная и бесполезная вещь. Просьба ко всем кто не согласен с данным мнением поставить звёздочку у проекта на гитхабе. Ну и здесь плюсик важен. Хочу понять объективную потребность.
Комментарии: 46
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
Fi1osofВероятность того, что объект $modx->user будет отсутствовать — практически нулевая, потому что при инициализации MODX в любом случае создает этот объект, даже если пользователь не авторизован. А если этого не произойдет, то все развалится нафиг фатальной ошибкой.
children() как альтернатива $modx->getChildIds()? И прочее в том же духе? Это все напоминает попытки русских отучить от вилки и ложки, потому что палочками тоже можно кушать. Еще раз сорри, но более бесполезного материала не видел давно. Ты же способен на большее. Зачем писать такое?
P.S. Здесь одинарные кавычки явно лишние.
С юзером знаю. Перестраховка.
За найденный баг с кавычками спасибо.
Fi1osofА теперь то же самое на чистом MODX:
Во-первых, люди будут больше понимать основы MODX-а.
Во-вторых, это работать будет везде, без установки всяких дополнительных библиотек. Да, на своем частном проекте можно поставить допбиблиотеку. А если вопрос стоит в переносимости кода? Написать свой компонент и требовать, чтобы все ставили допкомпонент для его работы? Я понимаю это в случае с pdoTools и modxSite компонентами, там код обширный. Но просто ради синтаксического сахара, согласись, оно того не стоит.
А покопать MODX было бы и тебе полезно (и наверняка интересно). К примеру, ты знал, что ::getOption() есть не только у MODx, но и у xPDOObject? У любого. Это очень полезный механизм. Зачем это бывает нужно? Например, в одном сниппете установил $modx->resource->setOption($key, $value), а в другом перехватил $modx->resource->getOption($key, $value). И точно знаешь, что это нигде больше не перехватится и не перетрется. А то бывает в одном сниппете устанавливаешь $modx->setPlaceholder(), и тут же где-то в другом месте его перетирают, просто потому что это слишком глобально и имя переменной не уникальное использовал.
Ну и согласись, просто из-за того, что API слишком обширное, лень тобою обуяла, и ты местами просто не в полной мере функционал поддержал. К примеру, config(). Ты не стал здесь расширять MODx-метод, мы просто переписал на свой лад, дав возможность получать только текущие конфиги объекта $modx. Но родной MODx-овый метод поддерживает 4 параметра. Один из них — «значение по умолчанию», поддержку которого ты не перенес в свой метод. Таким образом ты не только добавил лишние сущности, но и обеднил функционал. Не надо так.
Функцию email() вообще практически как есть взял из modUser::sendEmail(). Знаешь как я иногда делаю, когда хочу отправить мыло на произвольные емейл?
И никаких лишних библиотек.
В общем, это мое личное мнение. Понятно дело, тебе решать что делать, и народу решать что принимать и что изучать. Скажу только, напоследок, что я вижу много ненужных сторонних псевдотехнологий, и очень мало, касающегося самого MODX-а. То, что ты написал, не будет работать без самого MODX-а. То есть прежде, чем написать это, ты изучал MODX. Но вместо того, чтобы научить других полученным знаниям, ты придумываешь и впариваешь всем вот этот свой синтаксический сахар. И все это для того, чтобы всеобщее внимание сосредотачивалось на тебе. Почему ты все оцениваешь в количестве скаченных твоих компонентов? Зачем? Если никто не будет качать твои компоненты, то у тебя самооценка понизится? Мои компоненты практически никто сейчас не качает. Ну и что? Я все равно знаю больше тебя в MODX. Не хочешь ли и ты реально знать больше в MODX, вместо того, чтобы писать компоненты, которые и скачают только те, кто знает значительно меньше тебя. Я говорил тебе подобное больше года назад, и вот опять говорю. Подумай над этим.
По последнему абзацу… Чем же тебе помочь, брат? Может тебе отдыхать нужно побольше? Отвлекись. Найди что-ли девушку. Сходите в кафе или театр. Вокруг столько интересного.
Подумай на этим.
Fi1osofЯ тоже все сказал. И не говорю, что ты должен поступить именно так. Тебе решать. Я просто высказал свое мнение. А высказал, просто потому что жалко, что имеющийся потенциал идет немного не в том русле. Но может ты когда-нибудь поймешь это.
Fi1osofА еще я, было дело, спрашивал «Нафига в минишопе контроллеры так все переписывать?».
Короче, ты тоже, смотрю, любитель все попереписывать. Вот в админтулс ты нафига вот это переписал вот этим.
Ты бы не только мои мемуары читал, но и в код подсматривал. К примеру, у меня в modxSDK этот момент был реализован вот так.
Знаешь к чему я это все? Ты вот кичишься своим гениальным кодом, и совершенно никого не слушаешь. Написал что-то лично свое, что ломает работу других компонентов. Вот очередная жалоба поступила. Ты считаешь, это профессионально?
Вот так выглядел диалог по этой проблеме:
Ты не ориентируйся на количество здесь плюсов тебе и минусов мне. Я не на своем поле. Глобально же большинство твоих компонентов вызывают у нормальных программистов реакцию от легкой усмешки до дикого ржача. Сколько раз я слышал «Коля, перепиши ты этот oneBooking! Там под капотом ппц! А альтернативы пока не написали».
В общем, если ты в кафе или театре, возвращайся, больше учись, а то так и будешь писать код для новичков. А ведь наверняка мечтаешь о признании и среди опытных программистов.
P.S. отправил тебе PR.
P.P.S. хочешь ответить? Лучше отправь мне парочку ответных годных PR куда-нибудь.
Если ты не понял зачем, может тогда ты себя переоцениваешь? За PR спасибо, но так как ты не понял смысла, то соответственно он ломает задуманный функционал. За $this->modx->smarty->get_template_vars() тоже благодарность, возьму на вооружение.
А чё не сотая, тысячная, миллионная для драматизма? Конфликты приложений существовали до меня и будут существовать после. А профессиональным я считаю дать знать автору о проблеме.
Перечитай мою страничку. Я не вижу ничего позорного писать для новичков.
П.С. PR не приму по описанной выше причине.
П.П.С. Я один раз имел неосторожность обратить внимание на твой robots.txt. Твоими «благовониями» все браузеры пропахли. На те же грабли наступать не собираюсь.
У меня только единственное к тебе пожелание — «Коля, перепиши ты этот oneBooking!»
Fi1osofЛадно, это лирика. Я так понял, подмену в контроллере ты делаешь для того, чтобы можно было дерево документов справа выводить через кастомный JS-layout?
ОК, тогда такое решение, для примера:
Замена через регулярки, конечно, жестко, но в твоем случае это меньший хардкод, чем было. И в таком случае дерево справа выводится, и modxSDK работает.
А теперь интересное: я так понял, при включенной JS-компрессии в админке у тебя эта штука не работает? Ведь ты вклиниваешься только в блоке отключенной компрессии. Поэтому я и добавил проверку включена ли компрессия. Включаем компрессию, и уже кастомный JS отсутствует, и функционал не работает.
Не работает и без моих модификаций (без них только еще и modxSDK работать перестает).
Правда тут сложнее становится? Надо в компрессированный JS-файл вклиниться, а это уже гораздо сложнее и простой регулярочкой сложно, а главное — глупо. Поэтому ищем более правильное решение, а именно расширение самого MODx.Layout. Вот тебе такой расширяющий Layout.
Согласись, 90 строк лучше 420-ти?
А в классе твоем итоговый код будет таким:
И здесь сразу несколько плюсов:
1. Это работает теперь в том числе и на включенной компрессии.
2. Это не перетирает чужие кастомные скрипты.
3. Это не ломает чужие лейауты (сейчас, если кто-то переопределит на свой лад modx-layout, свой код его затрет).
4. Гораздо меньше кода (что обслуживать легче).
5. БОльшая обратная совместимость (не придется отслеживать версию MODX-а в случае, если в новой версии MODX-а будут изменения на уровне твоего текущего переопределенного блока контроллера).
В общем, если ты хочешь писать правильные компоненты, во-первых, меньше огрызайся и больше слушай других, а во-вторых, научись хотеть писать правильный код. У тебя есть мышление, но нет правильного взгляда на такие вещи.
P.S. А еще лучше пуллреквест бы в MODX отправил. Там вопрос в двух строчках.
Честно говоря был уверен, что в лейауты админки никто не лазит.
Слушать что, бесконечные оскорбления и фантазии? Это первый комментарий, где ты как более опытный товарищ помог решить проблему. Правда приправив опять же фирменным хамством. Видимо без этого никак. Но если первый и последний абзац выкинуть, то очень хороший разбор.
Они мой безобидный PR для отображения используемой памяти принять уже год не могут. А уж про PR с лейаутом и мечтать нечего. Они только критические PR принимают. Видимо интереса ко второй ветке у них уже нет.
Fi1osofЭто уже кто что хочет видеть и что видит. Я много раз тебе писал годные советы (можешь пробежаться по старым комментам, сейчас у тебя опыта больше, ты можешь заметить то, чего раньше не замечал).
И я много раз говорил: меньше обращайте внимания на эмоции, больше на суть. Ребят в своей команде я еще не так отчитываю.
У меня тоже 3 открытых PR и больше половины из трех десятков закрытых не принято (хотя есть критичные, баги с которым до сих пор проявляются). А что делать? Все равно приходится отправлять.
Fi1osofТу же самую ошибку допустил. Тогда меня с этим разве что danyaPostfactum мог поправить, он всегда в JS был очень силен.
Для того тесты пишут, и собственно сам вопрос тут — modx.pro/help/10813/
П.С. Ещё и 1-е и 2-е освободилось.
это к таму чтобы не запоминать длинные названия и не выдумывать новый функции.
Реально кто поймет откуда эти функции запускаются
Кроме того на некоторых хостингах $users = users()->profile()->select('User.username, Profile.email')->where(['Profile.blocked'=>true])->get(); Таки конструкции будут ошибку выдавать в случае если попробуешь вывести массив.
Понравились функции проверка на существовани юзера и отправки почты!
И за документацию развёрнутую спасибо!
Вот и ты пополнил ряды любителей бесполезных вещей. :)
А если подключалось бы в виде приложения еще круче было бы.
Документация занимает в разы больше времени, чем разработка. А чтобы сделать в виде пакета, нужно перевести её на английский. Мне легче застрелиться. Могу сделать только для ru сегмента в modstore.
Ну а для платных, да — английские доки в этом году будут обязательны, если автор захочет продавать их на весь мир.
Т.е. в modstore будет опция кому продавать пакет?
Будет английская версия магазина и выбор — выставлять ли в ней своё дополнение. Для этого нужно будет перевести свою документацию на англ. язык и мочь отвечать на вопросы иностранцев.
Сейчас это всё в разработке, в первом квартале очень надеюсь запустить.
А описание каждой функции отличное, это меня прям подкупило))
Где-то читал, что разработчики MODX просят не использовать в названии компонентов приставку mod. Типа и так ясно, что дополнение для MODX — и без приставки.
А в ядре эта приставка отделяет собственно MODX от остального:
Может, сделать это неписанным правилом магазина и предлагать разработчикам поменять такое название? Например, сделать просто Helpers — нормальное название для компонента. Понятно, что в самом коде поменять название будет сложнее, но в репозитории будет отображаться нормально.
Fi1osofНу и еще в своей практике по-моему с modEvent сконфликтовал.
P.S. Сорри, да, я тоже этим грешу. Но пытаюсь исправляться.
Думаю пока хватит. Жду ваших предложений. Одна голова хорошо…
Мега респект.