обновился до PHP 5.4.19 (cli) (built: Aug 22 2013 08:04:21) Copyright © 1997-2013 The PHP Group Zend Engine v2.4.0, Copyright © 1998-2013 Zend Technologies полет нормальный — такая же шустрая как и 5.4.17

Отлично, ждём :-)

О, поступила инфа от виновника, что он уже давно это пофиксил, но просто чтобы нам жизнь медом не казалась, он забыл отправить пулреквест. Ждем обновления.

Я бы мог даже ткнуть пальцем в того, что это сделал)))) (да простит он мне эту злую шутку))). Честно — мне пока лень. Если что-то скопировать надо, то просто в файрбаге копирую. Но в первой версии как раз все копировалось, так что вы можете это поправить, и все будут вам благодарны. Проект: github.com/Fi1osof/modx-console

Наткнулся сегодня на странное поведение xPDO при попытке извлечения записи объекта из базы данных не со всеми колонками. Вот запрос для примера $q = $modx->newQuery('modResource'); $q->select(array( 'modResource.id',
)); $q->where(array( 'id' => 2
)); if($o = $modx->getObject('modResource', $q)){ print_r($o->toArray());
} И вот что интересно: здесь мы формируем запрос так, что из базы данных мы извлекаем только одну колонку — id. То есть наш конечный объект должен содержать только значение id, а все остальные поля должны были содержать дефолтовые значения из мета-описания объекта. Но при этом, когда мы выводим данные объекта через $o->toArray(), то видим все значения из базы данных. В чем подвох? Может запрос полный со всеми колонками, а не только с id? Посмотрим. print $q->toSQL(); SELECT modResource.id FROM modx_site_content AS modResource WHERE modResource.id = 2 Нет, в запросе только одна колонка id… А прикол весь в том, что xPDO четко следит за тем, все ли «колонки» объекта заполнены (получены из базы данных). Но это довольно сложный и запутанный механизм. Итак, у xPDO-объектов есть свойство $this->_lazy, которое содержит массив всех колонок, которые не были получены из базы данных. Изначально этот массив пустой, и наполняется только в методе xPDOObject::_loadInstance, и только тогда, когда не все колонки объекта запрошены из базы данных. Давайте внимательней взглянем на эту строку $instance->_lazy= $actualClass !== $className ? array_keys($xpdo->getFieldMeta($actualClass)) : array_keys($instance->_fieldMeta); То есть в этот массив попадают или все колонки актуального класса (этот механизм я расписывал здесь), или массив колонок из мета-описания этого объекта, не содержащихся в массиве запрошенных колонок. В нашем случае в этот массив попали все колонки, кроме id. А что происходит дальше и на все влияет этот массив ->lazy? Для этого стоит посмотреть методы xPDOObject::get(), xPDOObject::toArray() и xPDOObject::toArray(). В методе xPDOObject::get() есть строки: $lazy = array_intersect($k, $this->_lazy); if ($lazy) { $this->_loadFieldData($lazy); } То есть если это поле — lazy (дословно «ленивое»), то он пытается подгрузить значение через метод $this->_loadFieldData. А что там? protected function _loadFieldData($fields) { if (!is_array($fields)) $fields= array($fields); else $fields= array_values($fields); $criteria= $this->xpdo->newQuery($this->_class, $this->getPrimaryKey()); $criteria->select($fields); if ($rows= xPDOObject :: _loadRows($this->xpdo, $this->_class, $criteria)) { $row= $rows->fetch(PDO::FETCH_ASSOC); $rows->closeCursor(); $this->fromArray($row, '', false, true); $this->_lazy= array_diff($this->_lazy, $fields); } } А там, как видно, формируется новый запрос к БД. Примерно тоже самое видно и в методе xPDOObject::toArray() if (!$excludeLazy && $this->isLazy()) { $this->_loadFieldData($this->_lazy); } То есть, если вы решили сократить запрос к БД, указав меньшее количество колонок в запросе (в xPDOCriteria), то на первых порах вы получите небольшую экономию, но в дальнейшем можно автоматом наплодить новые запросы к БД при попытке получить значения объекта. Но в чем еще казусы? В методе xPDOObject::fromArray происходит перезапись ->_lazy (полученные из массива колонки отмечаются как «не ленивые») if ($this->isLazy($key)) { $this->_lazy = array_diff($this->_lazy, array($key)); } А вот в методе xPDOObject::set (который по сути делает тоже самое, что и :fromArray(), только для одного поля) — нифига. К чему это приводит? Вот такая конструкция: $q = $modx->newQuery('modResource'); $q->select(array( 'modResource.id',
)); $q->where(array( 'id' => 2
)); if($o = $modx->getObject('modResource', $q)){ $o->set('pagetitle', 'new pagetitle'); print "<br />Pagetitle 1: ". $o->pagetitle; print "<br />Pagetitle 2: ". $o->get('pagetitle');
} То есть мы получили объект практически без данных. Затем установили ему pagetitle 'new pagetitle'. Вот если после этого мы получаем pagetitle как свойство объекта, то мы получим установленное значение. А вот если попытаемся получить через метод ->get('pagetitle');, то так как поле pagetitle _lazy, то он получит данные из БД и перетрет это значение. Так же это значение будет затерто, если мы выполним ->toArray(). Не буду писать все, что хотел бы, но общая картина нарисована…

Вот, кстати, давно хотел попросить — нельзя ли как-нибудь сделать так, чтобы консольный вывод можно было копировать? Сейчас вот нельзя( Это люто неудобно и просто напросто мешает.

Так а никто и не заставляет использовать мои процессоры. Используйте свои процессоры. Вот потому я выше и сказал, что правильней использовать запросы на коннекторы, потому что коннекторы вызывают процессоры, а процессоры возвращают стандартизированные ответы. Простейший процессор, которые вернет успешный ответ: class myProcessor extends modProcessor{ // Эта функция автоматически выполняется MODX-ом и является основной public function process(){ $error = false; if($error){ return $this->error("Сообщение об ошибке"); }

    // else
    return $this->success("Успешно выполнено");
}

}

return "myProcessor"; Вызывайте этот процессор через коннектор, и будет вам счастье. MODX сам сформирует правильный JSON-ответ. Вот информация в помощь: modxclub.ru/blog/voprosy-spetsyalistov/136.html

Простите, если надоел своими вопросами. У меня такой вопрос, я посмотрел пример который вы привели и в целом по ему всё более менее понятно. Вот только класс ShopmodxWebGetlistProcessor расширяет встроенный класс modObjectGetListProcessor и переопределяет его методы. То бишь использует его алгоритм работы. Но мне нужно не используя стандартных процессоров исполнить действие. Может я не совсем правильно объяснил ситуацию по этому опишу что мне нужно сделать, так будет проще меня понять. У меня есть меню в админке (сделано на основании Doodles), в нем открывается список в виде таблицы, при вызове контекстного меню на элементе этой таблицы появляется пункт меню «Ответить» который отправляет письмо по адресу пункта выбранного элемента. Я проверял пост запрос который отправляется там есть все что мне нужно, но для того чтобы все работало нормально мне нужно возвратить событие success чтобы все работало нормально. Думаю итак понятно но я уточню, используется Ajax запрос.

но я так и не понял как мне вернуть: $modx->error->success(''); А что вернуть? Эту функцию вообще не принято самостоятельно вызывать. Она используется самим объектом $modx->error. И она не отдает какие-либо переменные собственного объекта, а возвращает обработанные параметры. К примеру можно вот так вызывать: <?php print '<pre>'; print_r($modx->error->success('', $modx->getObject('modResource', 1))); То есть здесь будет получен объект первого документа, но на выходе мы получим не сам объект, а массив данных этого объекта (в общем массиве ответа). Мне кажется, вы в принципе не в том направлении роете. Изучайте стандартную конструкцию и все: gist.github.com/Fi1osof/328469331b5258ff009a И ещё один вопрос я для того чтобы использовать такие методы как getObgect() и newObject() использую вот такой код: Можно и так. Но в большинстве случаев правильно использовать коннекторы (которые в свою очередь уже вызывают процессоры). То, как показано у вас — это простой подход, но он не стандартизированный. Там нет стандартизированных проверок прав, форматов ответов и т.п.

Я перечитал предоставленный вами материал, информация полезная так что добавил в избранное, но я так и не понял как мне вернуть: $modx->error->success(''); , в пользовательских скриптах. И ещё один вопрос я для того чтобы использовать такие методы как getObgect() и newObject() использую вот такой код: define('MODX_API_MODE', true); require_once '/путь_к_фалу/index.php'; Это правильно или нужно по-другому как то это делать?