Я согласен поддержать рублем, но опять месяц близится к концу :)
Очень подробная инструкция о том, как с нуля создать новый LAMP-сервер под MODX и установить собственно сам MODX Revolution на digitalocean.com Там все на буржуйском, но в целом не сложнее любой другой технической документации. Зато очень подробно и пошагово.
Всем, кто ждет с нетерпением новой сборки ShopModxBox, на которую был анонсирован сбор средств: есть две новости (хорошая и плохая). Плохая: скорее всего выпуск сборки задержится на пару-тройку дней. Хорошая: основная причина — более обширный функционал, чем был анонсирован в топике. Я реанимировал свой давний самый крупный проект (что интересно, я уже там использовал Smarty, хотя это был конец 11-го года). В том проекте было много интересных плюшек, которые я и решил перенести в эту сборку. В частности, там была оплата не только через платежные системы (можно было даже использовать несколько штук одной и той же системы, к примеру несколько робокасс (зачем? Там у нас была мультидоменность и партнерская программа, и надо было чтобы на разных доменах оплата проходила через разные робокассы для разных владельцев)), но и оплата с баланса. А так же не только продажа, но и подписки (при чем на подписки можно было завести сколько угодно тарифных планов, с различными сроками действия, количеством включенной в пакет внутренней валютой и т.п.). В общем, там был полноценный биллинг. И вот этот биллинг я и решил перенести на ShopModxBox. Само собой там тоже не было все идеально, в связи с чем это не пятиминутный перенос, а по сути переписка всего с нуля, просто тот проект помогает вспомнить какие ошибки были допущены и что можно было улучшить. В итоге сразу хочу отметить, что новая сборка полностью переделана и обратной совместимости не имеет вообще. О таких вариантах говорилось изначально, но в данном случае хочу это отметить особенно, так как не только структура изменения претерпела, но и база данных. Еще об изменениях: изменения в сборке реально кардинальные, и коснулись вообще всего, и главным образом корзины. Раньше корзина хранилась только в сессии, и в базу попадал только оформленный заказ. Здесь сразу несколько минусов есть, и главный для маркетологов — они не знают какие товары вызывали интерес, сколько было оформлено заказов, сколько не оформлено, какова конверсия и т.п. Так же если по какой-то причине сессия слетела (даже у авторизованного пользователя), то и корзина слетала. Сейчас есть куча вариантов в этом направлении, в том числе даже найти корзину не авторизованного пользователя, и передать ее ему, если он авторизовался. А если это был авторизованный пользователь, то он найдет свою корзину в личном кабинете в любой момент. И вот как раз в этом и кроется причина многих изменений. Во-первых, чисто идеологически. Я долго думал над тем, чем же на самом деле является корзина, и пришел к выводу, что это по сути своей Заказ, только еще не оформленный (то есть статус у него Новый). И Корзину (с товарами) от полноценного Заказа отличает только статус Оформлен. При этом не следует плодить сущности и выполнять всякие метаморфозы (то есть, к примеру, в момент оформления заказа перекидывать товары из Корзины в Заказ и т.п.). И очистка Корзины — это смена статуса на Отменен. То есть сам заказ никуда не деется, он просто отменяется (меняется статус). Для маркетологов это опять-таки полезная информация, так как для оценки поведения клиентов важно понимать что они делают, чтобы потом понять почему они так делают. В связи с этим, хочу сразу отметить, что мы берем курс на очень серьезное решение, в котором очень много всего будет уделено именно маркетингу. Это все равно как некоторые ЦМСки выделяют именно как SEO-friendly, потому что они не только управляют контентом, но и имеют какие-то инструменты для только, чтобы делать сайт более индексируемым. А мы вот плюс к этому будем пытаться делать так, чтобы магазин не просто работал (показывал товары), а имел серьезную маркетинговую составляющую. А вот сейчас полезная информация в плане идеологической структуры сайта. Главное: появляется новый компонент Billing, в котором содержится все, что связано с оплатами, счетами, заказами, контрагентами и т.п. Итак, мы определили базовую сущность — Заказ (Order). У заказа есть Статусы (OrderStatus). Есть связка Заказ-Товар (OrderProduct). Вот с этим как раз и работает корзина. Сама корзина осталась отдельным компонентом Basket, но процессоры она вызывает из компонента Billing. Далее, на заказ уже может быть сформирован счет (Invoice). Счета так же имею статусы (InvoiceStatus). Оплата (Payment). Это один из самых сложных моментов, и не буду грузить сейчас всеми тонкостями проводок, оплатой сразу по нескольким счетам и т.п. В общем, пока делаем попроще (один платеж — один счет, без всяких там транзакций и т.д. и т.п.), но в дальнейшем будем биллинг постепенно развивать. Так же Payment содержит информацию о том, через какую платежную систему был совершен платеж, ID счета в платежной системе и т.п. В общем, все это — очень большой объем работ, и лучше подождать пару дней, и получить более комплексную сборку сразу, чем потом пытаться докинуть доработки (так как это будет сделать очень сложно, ибо все это — основа, и очень сложная. Там много изменений будет в самой базе данных и т.п.). А чтобы оценить примерно объем работы, покажу пару скринов. Это основная модель (скрин 1) и процессоры основного компонента (скрин 2.) с того моего проекта. ? ? А в ShopModxBox я постепенно хочу сделать еще больше функционала (само собой буду стараться, чтобы объем кода не был очень большой, и все было структурировано). Так что, кому все это интересно, не стесняйте поддерживать рублем. Работы будет много и постоянно, а кушать надо :-)
Но к слову, там не все классно в этом плане (сортировок). Сортировка по одному полю — это запросто. А вот сортировка по нескольким полям — это уже не просто так. Поэтому буду думать еще в этом направлении. Чисто из-за того, что там по сути два запроса выполняется и используется два объекта запросов, там сложности в плане вызова единого метода на формирования сортировок. Дело в том, что подсчет надо выполнять без сортировки, а конечный запрос с сортировкой, и на практике там много бывает вариантов, когда единый вариант сложно найти. Но это обязательно будет доработано.
Здесь у тебя все ОК с SQLем, но ты не там это используешь. Подсчет должен выполняться без всяких order by rand(). А тебя метод prepareQueryBeforeCount. Правильней в initialize() указывать $this->setDefaultProperties(array(
'sort' => 'RAND()',
)); Или просто в вызов передавать sort=RAND()
Разобрался. дастаточно было указать sort=RAND(), ничего не надо править в процессоре :)
В процессоре: //-------------------------------------------------------------- public function prepareQueryBeforeCount(xPDOQuery $c) { $c->where(array( 'parent' => $this->getProperty('parent'), ));
if($this->getProperty('sort')=='rand')
$c->sortBy('RAND()');
$s = $c->prepare(); print $c->toSQL();
$s->execute();
print '<pre>';
print_r($s->errorInfo());
return $c;
}
} выдает SELECT modResource
.id
AS modResource_id
, modResource
.type
AS modResource_type
, modResource
.contentType
AS modResource_contentType
, modResource
.pagetitle
AS modResource_pagetitle
, modResource
.longtitle
AS modResource_longtitle
, modResource
.description
AS modResource_description
, modResource
.alias
AS modResource_alias
, modResource
.link_attributes
AS modResource_link_attributes
, modResource
.published
AS modResource_published
, modResource
.pub_date
AS modResource_pub_date
, modResource
.unpub_date
AS modResource_unpub_date
, modResource
.parent
AS modResource_parent
, modResource
.isfolder
AS modResource_isfolder
, modResource
.introtext
AS modResource_introtext
, modResource
.content
AS modResource_content
, modResource
.richtext
AS modResource_richtext
, modResource
.template
AS modResource_template
, modResource
.menuindex
AS modResource_menuindex
, modResource
.searchable
AS modResource_searchable
, modResource
.cacheable
AS modResource_cacheable
, modResource
.createdby
AS modResource_createdby
, modResource
.createdon
AS modResource_createdon
, modResource
.editedby
AS modResource_editedby
, modResource
.editedon
AS modResource_editedon
, modResource
.deleted
AS modResource_deleted
, modResource
.deletedon
AS modResource_deletedon
, modResource
.deletedby
AS modResource_deletedby
, modResource
.publishedon
AS modResource_publishedon
, modResource
.publishedby
AS modResource_publishedby
, modResource
.menutitle
AS modResource_menutitle
, modResource
.donthit
AS modResource_donthit
, modResource
.privateweb
AS modResource_privateweb
, modResource
.privatemgr
AS modResource_privatemgr
, modResource
.content_dispo
AS modResource_content_dispo
, modResource
.hidemenu
AS modResource_hidemenu
, modResource
.class_key
AS modResource_class_key
, modResource
.context_key
AS modResource_context_key
, modResource
.content_type
AS modResource_content_type
, modResource
.uri
AS modResource_uri
, modResource
.uri_override
AS modResource_uri_override
, modResource
.hide_children_in_tree
AS modResource_hide_children_in_tree
, modResource
.show_in_tree
AS modResource_show_in_tree
, modResource
.properties
AS modResource_properties
FROM modx_site_content
AS modResource
WHERE modResource
.parent
= 9 ORDER BY RAND() ASC
Array ( [0] => 00000 [1] => [2] => ) и на выходе процессора пусто.