modxcloud только у меня поттупливает или у вас тоже есть проблемы?
Привет!
Создал ms с basePath и baseUrl равными "/images/"
Если basePathRelative не установлено в false, но не надо ставить слеш в начале. Потом получается в пути двойной слеш: //images/inner_folder/picture.jpg
И получаю ничего не значащую ошибку: syntax error:
Пропиши в файле connectors/index.php
error_reporting(E_ALL ^ E_NOTICE); ini_set('display_errors', 1);
и будешь получать что-то значащие сообщения (только не забывай на продакшене убирать это).
Лезу вот сюда… WTF????
Ты методы разных объектов спутал :-) Внимательно перечитывай эту статью: community.modx-cms.ru/blog/modx-xpdo/9611.html Ты смотришь класс modMediaSource, а надо modFileMediaSource (у нас же файловый медиасурс).
А по сабжу (по проблемам с путями), вот этот твой вариант правильный:
// 8 - это id tv $tv = $modx->getObject('modTemplateVar', 8); // 4 - id ресурса, в котором выбирали картинку return $tv->renderOutput(4);
Просто ты наверняка забыл сделать $modx->switchContext('web');, а TV-параметры имеют отдельные настройки сурсов для разных контекстов, и так как для контекста mgr не настроен медиасурс, то он и возвращает этот путь.
Николай, сейчас вот начал разбираться с медиасурсами и наткнулся на этот топик (getSourcePath). Пытаюсь понять как правильно сформировать адрес. Для начал решил проверить вот это:
Когда мы через объект TV работаем, тогда вопросов нет, TV-шка сама вызывает медиасурс и формирует конечный путь
Создал ms с basePath и baseUrl равными "/images/". Потом создал tv, привязал к этому ms. В документе выбрал картинку через этот tv. Итоговый урл должен быть "/images/inner_folder/picture.jpg"
Затем пишу в консольке (спасибо за неё, кстати)):
// 8 - это id tv $tv = $modx->getObject('modTemplateVar', 8); // 4 - id ресурса, в котором выбирали картинку // return $tv->getValue(4); return $tv->renderOutput(4);
И получаю вот это (и посредством renderOutput и getValue — одно и то же):
inner_folder/picture.jpg
Хм. Пишу в контенте документа [[*tvname]], проверяю:
//images/inner_folder/picture.jpg
Первая мысль — WTF?? Это было 1е не понятное :-(
Дальше пробую получить путь, как у вас в сниппете:
$ms = $modx->getObject('sources.modMediaSource', 3); $props = $ms->getPropertyList(); $basePath = $ms->getBasePath(); return $basePath; //$baseUrl = $ms->getBaseUrl(); //return $baseUrl;
И получаю ничего не значащую ошибку:
syntax error:
Да, вот таким вот прямым текстом.
Лезу вот сюдаWTF????
Я понимаю, что оффтопик злостный, но блин, вообще не знаю что делать( Помогите, пожалуйста! Уже моск нагреваться начинает перед кипением(
Сразу уточню, что материал рассчитан в основном на тех, что уже использует процессоры, знает что это такое и как их готовить. И вообще этот материал многим может показаться сухим и не интересным. Но кто программирует (Илья, это тебя особенно касается;-)), обязательно надо изучить материал. Поверьте на слово, что это очень мощный инструментарий.
Я не раз уже поднимал тему подгрузки файлов-процессоров средствами API MODX. Раньше, когда у нас процессоры были просто php-файлами, нас это вообще не интересовало, мы просто выполняли $modx->runProcessor($action) и все. MODX делал require этого файла и все, возвращал полученный результат. Сейчас же у нас процессоры стали гораздо умнее — их можно расширять другими процесс-классами и т.п. Процессоры сегодня могут содержать очень мощный функционал, и это часто полностью законченные, самостоятельные классы. Так зачем нам писать кучу лишнего кода, когда мы можем использовать уже готовые классы, переопределить их и заставить работать под свои нужды?
Рассмотрим стандартный механизм работы процессора (здесь и далее будем рассматривать только «классные» процессоры). Мы выполняем $response = $modx->runProcessor($action, $params, $options); MODX в методе modX::runProcessor определяет путь до файла процессора, и если это класс, то он его инициализирует и возвращает результат выполнения (по сути это всегда результат метода modProcessor::process()). Но что, если мы не хотим получить результат метода processor::process(), а хотим просто получить результат какого-то внутреннего метода класса? То есть нам нужен просто класс? Для этого мы просто подгружаем файл процессора require_once $processor_absolute_path. И тогда нам доступен сам класс процессора.
Но в чем здесь проблема? Во-первых, элементарно не удобно. То есть каждый раз нам надо писать актуальный путь до процессора. А если мы его переместили, и вообще в другой пакет? Идти высчитывать кол-во методов dirname(), писать папки и т.п.
Во-вторых, отсутствие стандартного метода и единых проверок может даже привести к фатальным ошибкам.
В общем, я и с Джейсоном пытался этот вопрос обсуждать, но как-то мы не пришли к какому-то единому знаменателю (я Джейсона пытался убедить в необходимости ввести метод типа modX::loadProcessor()). А вот Марк Mark-H мне сегодня подкинул очевидную идею — использовать $modx->loadClass(); Не могу даже понять почему я раньше до этого не догадался, но его подсказки хватило, чтобы сразу увидеть удобство этого подхода и решение моих проблем.
Суть метода xPDO::loadClass заключается в том, что он ищет указанный класс во всех указанных папках подключенных пакетов (если не передан параметр, запрещающий делать это). То есть вы один раз можете выполнить $modx->addPackage($packName, $path); и далее уже выполнять подгрузку файла процессора так: $modx->loadClass($classname, '', false, true); (третий параметр false указывает на то, что не надо игнорировать подключенные пакеты, и надо искать по их папкам, а четвертый параметр true указывает на то, что надо игнорировать класс работы с базой данных (ведь у нас это просто процессор)). Все. Теперь не надо высчитывать пути.
Как этот процесс максимально оптимизировать? Каждый раз писать $modx->addPackage() мягко выражаясь — не очень удобно. Потому лучше само собой добавить это в extensionPackages. Но надо учитывать две задачи: 1. Уникальность имен пакетов (то есть нельзя два пакета назвать processors, при этом именно название пакета плюсуется к конечному пути пакета). А ведь нам очень желательно, чтобы процессоры лежали в папке processors, чтобы не рушить стандарты (тот же processor-плагин пакета modxSmarty ищет процессоры именно в папке processors). 2. Возможность указывать несколько пакетов с процессорами.
В общем, обычно экстеншены ведут к папке component/model/packageName/. Нам этот путь не подходит, так как противоречит вышеизложенным правилам. Значит делаем два пакета. Один ведет в component/model/packageName/ (он нам нужен для хранения основных классов, в том числе и тех, которые работают с базой данных), а второй в component/processors/packageName/. Через консоль выполняем два запроса:
$modx->addExtensionPackage('myPackage', '[[++core_path]]components/myPackage/model/',array( "serviceName" => "myservice", "serviceClass" => "myClass", ));
В этом запросе мы не просто добавили свой пакет. Указав serviceName и serviceClass, у нас каждый раз при инициализации MODX будет выполнять еще и $modx->getService($name, $class); То есть у нас всегда в MODX будет свой объект $modx->myservice, который будет инстансом класса myClass.
$modx->addExtensionPackage('myProcessors', '[[++core_path]]components/myPackage/processors/');
А вот это уже мы добавили папку для наших процессоров. То есть надо будет создать папку myPackage в [[++core_path]]components/myPackage/processors/, и там создавать наши процессоры. Код нашего сервис-класса будет выглядеть так:
class myClass{ public $modx = null; function __construct(modX & $modx) { $this->modx = & $modx; } public function loadProcessor($fqn){ return $this->modx->loadClass($fqn, '', false, true); } }
То есть теперь, чтобы не писать каждый раз эти лишние 3 параметра, можно просто выполнять $modx->myservice->loadProcessor($classname); Кстати, не забывайте, что в $classname знак точки — это разделитель директорий, то есть.
И вот теперь один небольшой пример:
$modx->myservice->loadProcessor('path.myclass'); if($instance = myclass::getInstance($modx, 'myclass' )){ $response = $instance->run(); print_r($response->getResponse()); }
В данном случае мы могли не только стандартный метод processs выполнить, но и любой другой дозволенный.
Так же если вы свои процессоры пишите, и какие-то зависят от других, то теперь не обязательно писать require_once, а можно использовать этот метод, выполняя в начале кода $this->myservice->loadProcessor();
Я сейчас включу этот функционал в обновленную сборку и выложу новый снимок.
UPD: В этом методе есть один неприятный момент. xPDO::loadClass не подгрузит два одинаковых по названию файла в разных папках, и не возвращает реальные имена классов процессоров. Переписал этот метод в классе modxsite: gist.github.com/Fi1osof/a87522b0b0ea9e60a2ed/revisions
Но это временное решение. Разговаривал с Джейсоном. Нас скоро ждут кардинальные перемены в ядре MODX-а, в том числе и автоподгрузка классов. И вообще он смотрит в сторону удаления метода loadClass. Это все классно, но мне некоторых плюшек не хватает уже сегодня, потому добавляю это в новую сборку (чуть попозже выложу). Основной метод: $modx->modxsite->loadProcessor(), возвращающий реальное название процесор-класса. Обкатывать это будет уже в процессе.
UPD2: Обновленная сборка с новым методом $modx->modxsite->loadProcessor(); Так же в сборку были добавлены два пакета:
  • PackMan (для быстрой сборки пакетов их имеющегося на сайте)
  • CMPgenerator (для генерации моделей пакетов из таблиц в базе данных)
Если кому-то эти пакеты не известны, изучите в обязательном порядке.
UPD3: Данный метод изначально не предполагался как идеальный, а только временное решение, но вот нашелся в нем большой минус, который накладывает серьезные ограничения — область видимость. Традиционно файлы классов подгружаются самим MODX-ом, и в самом файле (за пределами описания класса) $this — это текущая инстанция MODX-а. При вызове же через $modx->modxsite->loadProcessor $this — это $modx->modxsite, который ни в коем случае не является инстанцией MODX. Ввиду этого не получается использовать $this в этих классах. Понятно, что мало кто этот хук вообще использует, но тем не менее. Можно было бы использовать $this->loadProcessor() для подгрузки других процессоров, но это сопровождается теми же проблемами, плюс к этому еще и мешает использовать этот процессор штатными средствами. По этой причине придется все так же использовать require, а $modx->loadProcessor() использовать исключительно для подгрузки только тех процессоров, которые не используют переменную $this. Можно использовать в файлах классов так:
if($this instanceof modX){ $modxsite = & $this->modxsite; } else{ $modxsite = & $this; } $modxsite->loadProcessor('class');
Но учтите, что хотя если вы про это и забудете, оно будет работать, но по хорошему, лучше этим не злоупотреблять. Только если у вас стабильная выработанная методология. В принципе по мне, так это меньшее зло, чем require_once abs_path;
Илья, пока не берись за modAccessibleSimpleObject. Я вот только сейчас победил эту тему, и смог для своего объекта прописать проверку прав. Плюс там огромные заморочки с производительностью (много запросов к БД и т.п., часть инфы в сессию пользователя сохраняется). Я несколько переиначил этот механизм под свои нужды, кеширование прикрутил. В общем, пакет когда опубликую, скачаешь, посмотришь, но тема невероятно сложная по объему и количеству сопутствующих багов. Но справедливости ради стоит заметить, что оно того стоит…
Вот сборочка: modxclub.ru/downloads/sborki/webim/webim-1.0.zip Кнопка для диалога прям на главной странице. Панель для оператора: assets/components/webim/ В этой же папочке весь скрипт лежит. Конфиг там libs/config.php подхватывается из MODX-а. Пароль для оператора через phpmyadmin смените в таблице operators (там простой MD5 по-моему).
Сорри, но это сборка для членов клуба. Вот проявите себя, станете полноценным членом клуба, тогда вам будут доступны все файлы клуба.
Ну вроде да. Только я вот помню, что такое обещание было давно, когда поле uri ввели. Но вот поле то ввели, а кэш как был так и остался. А так конечно было бы очень неплохо.