Итак, создайте новый TV-параметр, назначьте его одному из шаблонов и у какого-нибудь ресурса установите значение этого параметра.
Думаю, вы уже догадались, что TV-параметры — это тоже объекты) У TV-параметров класс modTemplateVarResource.
Давайте посмотрим, как же выглядят эти объекты:
$tvs = $modx->getCollection('modTemplateVarResource'); foreach ($tvs as $k => $tv) { $tvs[$k] = $tv->toArray(); } print '<pre>'; print_r($tvs);Если хоть у одного из ресурсов заполнено хоть одно из дополнительных полей, вы увидите это значение в результате выполнения скрипта.
У объектов класса modTemplateVarResource есть поля: id, tmplvarid, contentid и value.
tmplvarid — id самого дополнительного поля (во вкладке «Элементы» рядом с названием TV),Соответственно, чтобы узнать значение TV у какого-то ресурса надо найти объект modTemplateVarResource, у которого значение contentid соответствует id ресурса, а tmplvarid — id нужного нам TV:
contentid — id ресурса,
value — соответственно, значение данного TV-параметра у данного ресурса.
$where = array( 'contentid' => 16 , 'tmplvarid' => 4 ); $tv = $modx->getObject('modTemplateVarResource', $where); return $tv->get('value');
Мы с вами познакомились со связью между объектами: в данных одного объекта указаны параметры другого (в объекте modTemplateVarResource есть поле, в котором указано значение поля id объекта modResource). И это не просто так. Объекты modResource и modTemplateVarResource связаны друг с другом. О типах связей мы поговорим в другой раз, я сейчас покажу, как можно использовать связи, чтобы упростить наш код.
У объектов xPDO есть методы getOne и getMany
getOne() — метод, который возвращает связанный объектДавайте, попробуем получить TV-параметр используя его связь с документом:
getMany() — метод, который возвращает несколько связанных объектов
$res = $modx->getObject('modResource', 16); $tvs = $res->getMany('TemplateVarResources'); foreach ($tvs as $k => $tv) { $tvs[$k] = $tv->toArray(); } print '<pre>'; print_r($tvs);Этот код выведет нам значения всех TV-параметров указанного документа. Посмотрите внимательно на параметр, который передается в метод getMany(). Это не название класса (мы знаем, что у TV класс modTemplateVarResource). Это псевдоним или, другими словами, алиас связи. Давайте посмотрим, как выглядит для MODX связь между ресурсом и TV-параметрами:
[composites] [TemplateVarResources] [class] => modTemplateVarResource [local] => id [foreign] => contentid [cardinality] => many [owner] => localcomposites — в этом массиве перечислены жесткие связи (помимо TV там есть и другие связи). Это означает, что при удалении ресурса удаляются и все связанные объекты.
TemplateVarResources — это тот самый псевдоним связи.
class — это класс связанного объекта. Вот здесь мы видим, что указан класс modTemplateVarResource.
local, foreign — здесь указано, по какому полю связаны объекты. В local указывается, какое поле нашего объекта используется в связи, а в foreign указывается, какое поле в связанном объекте соответствует указанному в local.
cardinality — может быть many или one. Если many, значит связь «Один — ко многим», а если one — «Один — к одному». В данном случае один — ко многим. То есть у каждого ресурса может быть много TV-параметров.
owner — указывает, какой объект в связи главный. То есть, если мы удалим ресурс, TV-параметры тоже удалятся, но если мы удалим TV, то ресурс останется.
MODX смотрит в этот массив связей каждый раз, когда выполняет getOne или getMany. Можно представить это так:
$res = $modx->getObject('modResource', 16); $tvs = $res->getMany('TemplateVarResources'); // ищем связь, у которой в алиасе указано TemplateVarResources // смотрим сначала class - о, класс modTemplateVarResource $class = 'modTemplateVarResource'; // смотрим, по каким полям связаны объекты $local = 'id'; $foreign = 'contentid'; // формируем условие выборки - должен получиться такой массив: // $where = array('contentid' => $res->get('id')); $where = array($foreign => $res->get($local)); // и возвращаем объекты (используем getCollection, так как // вызван метод getMany, а не getOne): $output = $modx-getCollection($class, $where);
Как вы поняли, объектов в MODX много и у каждого свои поля, кроме того многие объекты связаны друг с другом. MODX-то знает все эти объекты и связи. А как нам-то узнать, например, правильный алиас связи, который надо передать в метод getOne? Или, например, по каким полям связаны объекты? Или вообще, какие поля у объекта есть? Тут надо либо заучить, либо добавить себе в закладки эту страничку: bobsguides.com/modx-object-full-reference.html
Там вы найдете все объекты MODX, у объектов перечислены все поля, указано, в какой таблице хранятся данные объекта, и перечислены все связи объектов (пункты aggregates и composites).
Например, если посмотрим объект modUser, то увидим, что он связан с объектом modUserProfile и связь там один — к одному ([cardinality] => one), соответственно мы можем получить профиль пользователя без всяких дополнительных условий, так:
$user = $modx->getObject('modUser',1); // Не забываем, что указывается АЛИАС СВЯЗИ, а не класс $profile = $user->getOne('Profile');
Ну и напоследок хочу добавить, что у ресурсов (у объектов класса modResource) есть метод getTVValue, который выдает значение связанного TV-параметра:
$res = $modx->getObject('modResource', 16); $tv = $res->getTVValue(4); return $tv;
Но он может возвращать значение не только по id TV-параметра, но и по его названию:
$res = $modx->getObject('modResource', 16); $tv = $res->getTVValue('image'); return $tv;
Да, материал сегодня получился посложнее, чем обычно, так что по этому материалу практическое задание надо обязательно постараться выполнить самостоятельно.
Задание 1. Написать сниппет, который будет выводить на страницу заголовки, аннотации и даты публикации только тех ресурсов, у которых значение TV-параметра «Выводить на главной» равно 1. Или если таких ресурсов больше 10 будет выводить сообщение «Найдено больше 10 ресурсов»P. S. Я жду вопросов от новичков, потому что после такого материала вопросы возникнуть должны. Не бойтесь спрашивать, в этом топике вас даже за глупые вопросы никто не заминусует. Все учимся. По отсутствию вопросов создается впечатление, что никто эти топики не читает и никому это не надо — xPDO все прекрасно и так знают.
Задание 2. Напишите сниппет, который будет при каждом просмотре страницы увеличивать значение TV-параметра «Просмотры» на 1. А потом напишите второй сниппет, который выведет общее количество просмотров всех страниц, созданных пользователем. Подсказка — текущего пользователя можно получить так:$user = $modx->userи в переменной $user у нас будет объект класса modUser с полями текущего пользователя.
Решение задания для тех, кто не совсем понял тему или для тех, кому просто интересно.
Оригинал статьи: community.modx-cms.ru/blog/modx-xpdo/10268.html
Спасибо.
Если все сниппеты вызываются кешируемыми и изменения на сайте вносятся не очень часто (например, только раз в день), то никакой лишней нагрузки не будет. А для остальных случаев в любом случае придется писать что-то свое.
Посмотрите на сайт fsknmsk.ru/ — там все сделано стандартно для MODX. У каждой новости могут быть заполнены ТВ-параметры: Картинка, большое изображение для слайдера на главной, галочка — показывать ли на главной, список фотографий для генерации галереи, ссылка на файл видео-записи, ссылка на аудио-запись, список прикрепленных файлов (MIGX). У страниц с обращениями вообще каждый пункт из этой формы — это отдельный TV. Но сайт работает довольно быстро, на обычном аккаунте shared-хостинга и не выдает даже 50% позволенной нагрузки.
И как? Будет ли их модерация в админке?
Все документы уже создал.
Спасибо.
Как практическое задание решил написать такой сниппет:
У меня есть TV (тип недвижимости, id=2) со значениями Дом||Квартира||…
Хочу написать сниппет, который выводит все ресурсы у которого этот TV со значением — Дом. Вот код:
Результат:
Всего найдено 1 записей.
ID=3. Название=Дом 1 // выводит не все, таких ресурсов 3 — Дом 1, Дом 2, Дом 3.
Помогите решить.
Спасибо!
P.S. жду новых статей по xPDO о ООП.
Мне нужно сделать похожие документы к ресурсу.
Создал TV-параметр «same», он должен содержать id похожих ресурсов через запятую.
Скажите, как вывести информацию о всех документах, id которых содержаться в TV-параметре?
Пока есть такой код, но он выводит информацию только в том случае, если в значении TV-параметра содержится id только одного похожего документа.
Надеюсь, что внятно объяснил.
Заранее спасибо.
Так мы наоборот отказываемся от всех сниппетов.
Говорят, что getResources глючный и лучше писать свои сниппеты.
А в связке с TV пишут, что getResources — это смерть, так как делает какие-то подзапросы, и производительность теряется в разы.
Мы уже весь Wayfinder заменили своими сниппетами.
Хотим сэкономить ресурсы и выиграть в скорости. Уже выиграли 0,3 сек.
А вот без TV как вообще обойтись…
И по вашему коду есть еще комментарий.
$modx->resource это уже объект (текущий ресурс) и можно было написать так: И кроме того, при использовании getResources будет всего один запрос (мы же не указываем &includeTVs=`1`).
Я пробовал ваш метод, спасибо вам за него. Но, когда у меня всё кешируется — то не переводится :)
Я пробовал и решение Валентина
modx.im/blog/research/643.html
modx.im/blog/addons/663.html
Это просто супер, но не для меня. Мультиязычность.
Плюс ко всему стоит LikeDislike, HitsPage, modxTalks. То есть, некоторые блоки нельзя кешировать.
Я общался с пользователем Vanchelo (Ваня Брежнев, очень хороший паренёк) и читал мнения F1losofa по поводу getResources.
Они говорят, что нужно писать свои сниппеты.
Поверьте, это никак не моё мнение. Просто читаю, слушаю бывалых. Вас, конечно же, тоже слушаю.
Я поставил Wayfinder, getResources, и т.п. Скорость загрузки страницы отвратная. Бывает и 7 секунд простреливает. Всё кеширую, что можно. Уже напрягает. Отказался от Wayfinder — увидел, что реально выиграл в скорости. Надо пробовать.
А вот Сайт Вани (Vanchelo).
Посмотрите, летает же. А у него только свои сниппеты.
Или Thai, его тоже Ваня делал. Свои сниппеты. Вот это — класс.
Вот к таким сайтам, я считаю нужно стремится.
Ведь, посудите, в тех Wayfinder и getResources для простых сайтов дофига лишней фигни, которая просто не нужна. НАпример, для меню мне просто нужно вывести 5 пунктов ссылками. Всё. А там и параметры для исключения и кучу всего.
Если вы заметили разницу в загрузке страниц после перехода на самописные сниппеты, тогда да, используйте их.
LikeDislike, HitsPage и ModxTalks ненагруженные сниппеты, они и разрабатывались, чтобы вызываться некешированными. Попробуйте те блоки, которые одинаковыы для всех страниц кешировать с добавлением языка к ключу и отпишитесь, поможет или нет)
Ещё хотел узнать, а если свои сниппеты + ваш метод кеширования блоков, то вообще летать будет?
Попробовал — всё как и было, не переключаются между языками. Только русский.
Пробовал и некешированным вызывать, и кешированным.
Подскажите, где ошибка…
Давайте посмотрим на вторую и третью строчки. Вы используете метод getCollection, который возвращает массив, соответственно к этому массиву нельзя применить метод getOne — он применяется только к объекту. Давайте попробуем пройтись по массиву и применить этот метод к первому попавшемуся объекту (написать $tvs[0] мы не можем, так как в массиве id элемента будет таким же, как и его id в базе данных): Получилось. Давайте смотреть дальше — зачем вы берете метод getCollection, если нужен только один объект — это только лишняя нагрузка? Поменяем getCollection на getObject: Так, а зачем мы вообще идем от объекта modTemplateVarResource? А если наш ТВ еще не заполнен ни у одного ресурса — тогда мы не узнаем ничего об этом ТВ. Давайте работать сразу с объектом modTemplateVar: А так как мы производим поиск по id, то можно записать еще проще:
Спасибо Вам, за статьи и ответы.
Скажите, когда будут новые материалы, очень жду. newQuery(), select()…
и результат является в таком виде: «name1:10;name2:11;name3:12»
как мне отсюда вытащить значение name1 равное 10?
Если сделать так так:
выводится md5 пути, а нужно именно файла.
Отлично считает!
Только в «Console» кучу ошибок пишет:
и
Подозреваю, что это из-за настроек кэширования, так ли это?
<?php
$criteria=array('tmplvarid'=>2,'value'=>'Дом');
$tvs=$modx->getCollection('modTemplateVarResource',$criteria);
$output='';
$output.='Всего найдено '.count($tvs).' записей.
';
foreach ($tvs as $tv) {
$resource=$tv->getOne('Resource');
$output.='ID='.$resource->get('id').'. Название='.$resource->get('pagetitle');
}
return $output;
Приведенный выше код работает отлично в связке в GetRecources, но только по одному параметру TV, а как сделать выборку по двум и более параметрам? (чтобы между значениями Tv параметров стояло не ||, а AND )?
Заранее спасибо за помощь!
Скажем у меня есть еще один tv ресурс с
'tmplvarid'=>5,'value'=>'здесь значение из формы'.
Мне нужно, чтобы у меня выдавало ресурсы, когда первый параметр = Дом и второй параметр = значению из формы. Вот как-то так. Надеюсь, смог объяснить. У меня идет выборка из формы вот такого вида:
Код, который обрабатывает, этот выбор, вот такой:
Я не могу сообразить, как добавить второй параметр в массив, так чтобы шла проверка по обеим параметрам и если в случае успеха и в первом случае и во втором, то выводится объект.
А каким образом, например, сюда:
можно передать условие AND? Ну, допустим, сравнить два параметра? Как передать «больше», «меньше» и т д?
Добавить условие OR можно так:
Больше/меньше, LIKE:
Вот подсказочка: http://rtfm.modx.com/xpdo/2.x/class-reference/xpdoquery/xpdoquery.where
Прошу подсказать реализацию.
Найти все TV ресурса, которые находятся в определенной категории (сами TV находятся в категории, не ресурсы), а потом вывести их названия и значения (можно еще и порядок сортировки). В таблице все это есть (поля: category, caption, rank), а вот как все это вывести не знаю.
Подскажи, пожалуйста.
Код к сожалению не работает. Выводит просто «Array ( )»
В сниппете А вызываю снипет Welcome и передаю ему параметры:
$output = $modx->runSnippet('Welcome',array(
'name' => 'John'
));
Как в сниппете А принять параметр 'name' в переменную?
метод, который возвращает несколько связанных объектовДавайте, попробуем получить TV-параметр используя его связь с документом:
Раньше, когда все пользовались сниппетом getResources, проблема была — при большом количестве ТВ-шек вывод сильно подтормаживал. А теперь есть pdoResources — он выбирает все ТВ-параметры ресурса за один запрос.
Конечно, 20-30 ТВ-параметров могут повлиять и на скорость pdoResources, но если настроить кеширование, то тормозить будет только первый раз.
modx.pro/solutions/7198-simplify-work-with-tv/#comment-50483
Эта статья мне тоже очень понравилась. Решает не только вопрос скорости, но и другой минус ТВ-шек — то, что значения по умолчанию в базу данных не вносятся. В этом случае очень сложно сортировать и фильтровать по ТВ.
В общем совсем я уже устал искать ответ на свой вопрос. Нигде нет описания как правильно через pdoResources вызывать тв поле с url
Вот как вызываю я
[[pdoResources? &parents=`5` &includeTVs=`newurl` &tpl=`new`]]
Тв поле «newurl» с параметром ввода url и с параметром вывода url (ставил и параметр вывода -текст)
В чанке «new» вызываю это поле так В результате имею вместо сторонней ссылки на внешний сайт ссылку вида
мойсайт.ру/[[+tv.newurl]]
Илья, что я делаю не так?
Вот решился несколько строк кода написать, вероятно, очень корявых. Надеюсь, дальше пойдёт веселее.
Задание 1:
Буду очень благодарен за любые советы.
1 первое задание
То есть я в админке распределил поля (их довольно много) по категориям и хочу выводить в при разных условиях разные поля, по принципу «если id_ресурса=11, то показываем поля из id_категории=2».
Понимаю, что нужно обращаться через getCollection(), getMany() или getOne(), но не получается (
Вот здесь можно посмотреть, какие поля есть у того или иного объекта: Список объектов MODX
Пробовал так, не удаляет
В виде таблицы нужно вывести tv-параметры ресурса, разбитые на категории. То есть в одном месте ресурса tv одной категории, в другом tv другой категории. В каждой категории tv-параметры еще будут добавляться, поэтому у каждого из них устанавливаю цифру в поле «Сортировка», чтобы в админке, в ресурсе, в дополнительных полях видеть их в нужном порядке (ну и в шаблоне, где tv привязаны — тоже установлена сортировка).
Пользуюсь вот таким сниппетом.
Естественно, он мне выводит в таблицу tv-параметры, отсортированные по tv.id
1 вопрос — как отсортировать их по значению в поле Сортировка tv-параметра
2 вопрос — как сделать, чтобы категорию задавать при вызове сниппета
и может быть кто-то подскажет более простое решение…
изначально в шаблоне вызывала чанк в который передавала имя Tv и его значение. Но если разделов несколько и в них несколько tv-параметров, не хочется следить, все вывела через чанк, или что-то забыла.
Спасибо всем, кто откликнется.
Это сказывается и на pdoTools, например следующий код не возвращает ничего:
Иногда (хотя не всегда) выручает феномовский модификатор:
Например сейчас в Console следующий код возвращает пустоту:
А через ID вернёт нужное мне значение:
Есть мысли отчего так происходит? И как лучше вывести значение TV, если есть только его название, а не id?
Подскажи пожалуйста?!
Теперь просьба подсказать, как его еще можно корректно вычленить и убрать из системы?)
Адрес: http://s14720.h10.modhost.pro/manager/
Логин: s14720
Пароль: PEDAUw2xoGgq
Попробуй повторить, если не затруднит, должно так же глюкануть ;)
Удали строчку из таблицы modx_transport_packages — должно заработать.
Спасибо!)
Сейчас попробую второй плагин)
Лучше попробовать выйти на связь с автором и попросить его исправить ошибку. Или официально отдать другому разработчику.
Судя по дате обновления, которая, полагаю, и дата выхода плагина — 2011, и ошибках, которые в нем присутствуют, автор его давно забросил. А плагин то хороший, жаль что так пропадает.