<?php /* * Получаем данные только моделей товаров * То есть по товару находим модель, и для модели получаем только одну вариацию товара */ require_once dirname(__FILE__).'/getdata.class.php'; class modWebCatalogProductsGetmodeldataProcessor extends modWebCatalogProductsGetdataProcessor{ protected $modelsIDs = array(); public function initialize() { $this->setDefaultProperties(array( 'sort' => "Models.menuindex", )); return parent::initialize(); } // Готовим запрос на выборку уникальных объектов // Нам надо вернуть товары с приоритетом на наличие картинки protected function PrepareUniqObjectsQuery(xPDOQuery &$query) { $query = parent::PrepareUniqObjectsQuery($query); /* * Без изврата с подзапросом не обошлось, так как group by parent не учитывает * сортировку по картинке. */ $IDs = array(); $sub_query = clone $query; $sub_query->select(array( "{$this->classKey}.parent", )); // Сортируем по картинкам, а то могут попасть без картинки $sub_query->leftJoin('modTemplateVarResource', 'image', "image.contentid = {$this->classKey}.id and image.tmplvarid=8 and image.value != ''"); $sub_query->sortby('image.id', "DESC"); // Сбрасываем лимиты, так как нам нужные все возможные ID-шники, так как у нас нет группировки в // этом запросе $sub_query->query['offset'] = 0; $sub_query->query['limit'] = 0; if($sub_query->prepare() AND $sub_query->stmt->execute() AND $rows = $sub_query->stmt->fetchAll(PDO::FETCH_ASSOC)){ $parents = array(); foreach($rows as $row){ // Фиксируем только по одному ID на модель if(in_array($row['parent'], $parents)){ continue; } $parents[] = $row['parent']; $IDs[] = $row['id']; } $query->where(array( "id:IN" => $IDs, )); } // Группируем по родителям $query->groupby("{$this->classKey}.parent"); return $query; } /* * Подсчитываем количество товаров именно по ID-шникам их предков (то есть именно моделей), * так как нам нужны уникальные модели */ protected function countTotal($className, xPDOQuery &$criteria) { $count= 0; if ($query= $this->modx->newQuery($className, $criteria)) { if (isset($query->query['columns'])) $query->query['columns'] = array(); $query->select(array ("COUNT(DISTINCT {$this->classKey}.parent)")); if ($stmt= $query->prepare()) { if ($stmt->execute()) { if ($results= $stmt->fetchAll(PDO::FETCH_COLUMN)) { $count= reset($results); $count= intval($count); } } } } return $count; } public function prepareQueryBeforeCount(xPDOQuery $c){ $c = parent::prepareQueryBeforeCount($c); $c->innerJoin('modResource', 'Models', "Models.id = {$this->classKey}.parent"); return $c; } public function setSelection(xPDOQuery $c) { $c = parent::setSelection($c); $c->select(array( 'Models.id as model_id', 'Models.pagetitle as model_title', )); return $c; } } return 'modWebCatalogProductsGetmodeldataProcessor';
var smCart = function(options){ var self = this; this.options = options || {}; this.data = { color: null, design: null, size: null }; this.cart_variants = this.options.cart_variants; var c = console.log; this.IDs = []; // ID-шники возможных товаров по условиям выбора this.items = $('.product_var'); this.lastUsed = null; /* * Фиксируем все допустимые варианты **/ this.setAvailables = function(){ this.available = []; for(var i in this.data){ this.available[i] = []; if(!this.data[i]){ for(var x in this.cart_variants[i]){ this.ArrayMergeUnique(this.available[i], this.cart_variants[i][x]); } } else{ var el = $('[name='+i+']:checked'); this.ArrayMergeUnique(this.available[i], this.cart_variants[i][el.val()]); } } return; } this.checkAllowed = function(activeItem){ // c($(activeItem).parent().attr('class')); if($(activeItem).parent().hasClass('disabled')){ $(':checked').each(function(){ if(activeItem[0] == this){ return; }; var item = $(this); item.parent().removeClass('disabled'); self.unsetData(item.attr('name')); }); self.setAvailables(); } var elements = $('.product_var'); elements.parent().removeClass('disabled'); elements.each(function(i){ var el = $(this); // Если это текущий элемент, прерываем процесс if(activeItem[0] == this){ return; } var debug = false; var name = el.attr('name'); // design|color|size var value = el.val(); var IDs = self.cart_variants[name][value]; // Надо проверить каждый ID во всех массивах, кроме текущего var exists = false; var searched = false; var finded = false; $(IDs).each(function(y){ var id = IDs[y]; // Проходим каждый ID по порядку. // Найден должен быть во всех разделах // Проверяем для конкретного id var id_finded = false; for(var x in self.available){ if(!self.available[x].length || x == name // || !self.data[x] ){ continue; } id_finded = false; if($.inArray(id, self.available[x]) == -1){ id_finded = false; break; } id_finded = true; } if(id_finded == true){ finded = true; return false; } }); if(finded == false){ // Если это отмеченный ранее элемен, снимаем значение if(el.attr('checked')){ self.unsetData(name); self.setAvailables(); self.checkAllowed(activeItem); return; } else{ el.parent().addClass('disabled'); } } }); return; } this.onChange = function(e){ var item = $(this); var name = item.attr('name'); var value = item.val(); // Фиксируем новое значение поля self.data[name] = value; // Набиваем массив всех допустимых вариантов self.setAvailables(); self.checkAllowed(item); return; }; // Мержим уникальный массив this.ArrayMergeUnique = function(array1, array2){ $(array2).each(function(i){ if($.inArray(array2[i], array1) == -1){ array1.push(array2[i]); } }); return array1; } // Снимаем отметку с элемена this.unsetData = function(name){ $('[name='+ name +']:checked').attr('checked', false); this.data[name] = null; } this.items.bind('change', this.onChange); };
$q->where(array( "моя длинная строка-запрос вместе с > и т.п.", ));
$q = $modx->newQuery('modResource'); $q->select(array( 'modResource.id', 'modResource.pagetitle', '`TVlat`.`value` as `lat`', '`TVlng`.`value` as `lng`', '`TVprice`.`value` as `price`', '((ACOS(SIN(53.2242846 * PI() / 180) * SIN(`TVlat`.`value` * PI() / 180) + COS(53.2242846 * PI() / 180) * COS(`TVlat`.`value` * PI() / 180) * COS((50.197219700000005 - `TVlng`.`value`) * PI() / 180)) * 180 / PI()) * 60 * 1.1515 * 1.609344 * 1000) AS `radius`' )); $q->leftJoin('modTemplateVarResource', 'TVlat', 'TVlat.contentid=modResource.id AND TVlat.tmplvarid=15'); $q->leftJoin('modTemplateVarResource', 'TVlng', 'TVlng.contentid=modResource.id AND TVlng.tmplvarid=16'); $q->leftJoin('modTemplateVarResource', 'TVprice', 'TVprice.contentid=modResource.id AND TVprice.tmplvarid=3'); $q->where(array( '`TVprice`.`value`' => 5000, '((ACOS(SIN(53.2242846 * PI() / 180) * SIN(`TVlat`.`value` * PI() / 180) + COS(53.2242846 * PI() / 180) * COS(`TVlat`.`value` * PI() / 180) * COS((50.197219700000005 - `TVlng`.`value`) * PI() / 180)) * 180 / PI()) * 60 * 1.1515 * 1.609344 * 1000):<=' => 1500 // расстояние меньше полутора километра )); $q->prepare(); return $q->toSQL();
SELECT modResource.id, modResource.pagetitle, `TVlat`.`value` as `lat`, `TVlng`.`value` as `lng`, `TVprice`.`value` as `price`, ((ACOS(SIN(53.2242846 * PI() / 180) * SIN(`TVlat`.`value` * PI() / 180) + COS(53.2242846 * PI() / 180) * COS(`TVlat`.`value` * PI() / 180) * COS((50.197219700000005 - `TVlng`.`value`) * PI() / 180)) * 180 / PI()) * 60 * 1.1515 * 1.609344 * 1000) AS `radius` FROM `modx_do_dbsite_content` AS `modResource` LEFT JOIN `modx_do_dbsite_tmplvar_contentvalues` `TVlat` ON TVlat.contentid=modResource.id AND TVlat.tmplvarid=15 LEFT JOIN `modx_do_dbsite_tmplvar_contentvalues` `TVlng` ON TVlng.contentid=modResource.id AND TVlng.tmplvarid=16 LEFT JOIN `modx_do_dbsite_tmplvar_contentvalues` `TVprice` ON TVprice.contentid=modResource.id AND TVprice.tmplvarid=3 WHERE ( `((ACOS(SIN(53`.`2242846 * PI() / 180) * SIN(`TVlat` <= '1500' AND `TVprice`.`value` = '5000' )
WHERE (`((ACOS(SIN(53`.`2242846 * PI() / 180) * SIN(`TVlat` <= '1500' AND `TVprice`.`value` = '5000' )
$q = $modx->newQuery('modResource'); $q->select(array( 'modResource.id', 'modResource.pagetitle', '`TVlat`.`value` as `lat`', '`TVlng`.`value` as `lng`', '`TVprice`.`value` as `price`', '((ACOS(SIN(53.2242846 * PI() / 180) * SIN(`TVlat`.`value` * PI() / 180) + COS(53.2242846 * PI() / 180) * COS(`TVlat`.`value` * PI() / 180) * COS((50.197219700000005 - `TVlng`.`value`) * PI() / 180)) * 180 / PI()) * 60 * 1.1515 * 1.609344 * 1000) AS `radius`' )); $q->leftJoin('modTemplateVarResource', 'TVlat', 'TVlat.contentid=modResource.id AND TVlat.tmplvarid=15'); $q->leftJoin('modTemplateVarResource', 'TVlng', 'TVlng.contentid=modResource.id AND TVlng.tmplvarid=16'); $q->leftJoin('modTemplateVarResource', 'TVprice', 'TVprice.contentid=modResource.id AND TVprice.tmplvarid=3'); $q->where(array( '`TVprice`.`value`' => 5000, )); $q->having(array( '`radius`:<=' => 1500 // расстояние меньше полутора километра )); $q->prepare(); return $q->toSQL();
SELECT modResource.id, modResource.pagetitle, `TVlat`.`value` as `lat`, `TVlng`.`value` as `lng`, `TVprice`.`value` as `price`, ((ACOS(SIN(53.2242846 * PI() / 180) * SIN(`TVlat`.`value` * PI() / 180) + COS(53.2242846 * PI() / 180) * COS(`TVlat`.`value` * PI() / 180) * COS((50.197219700000005 - `TVlng`.`value`) * PI() / 180)) * 180 / PI()) * 60 * 1.1515 * 1.609344 * 1000) AS `radius` FROM `modx_do_dbsite_content` AS `modResource` LEFT JOIN `modx_do_dbsite_tmplvar_contentvalues` `TVlat` ON TVlat.contentid=modResource.id AND TVlat.tmplvarid=15 LEFT JOIN `modx_do_dbsite_tmplvar_contentvalues` `TVlng` ON TVlng.contentid=modResource.id AND TVlng.tmplvarid=16 LEFT JOIN `modx_do_dbsite_tmplvar_contentvalues` `TVprice` ON TVprice.contentid=modResource.id AND TVlng.tmplvarid=3 WHERE `TVprice`.`value` = '5000' HAVING `modResource`.`radius` <= '1500'
WHERE `TVprice`.`value` = '5000' HAVING `modResource`.`radius` <= '1500'
public static function findByIp(xPDO $xpdo, $ip = 'auto'){ if(!$c = self::newQuery($xpdo, $ip)){ return false; } $c->leftJoin('GeoipLocation', 'Location'); $c->leftJoin('GeoipCountry', 'Country'); $c->select(array( "Country.*", "Location.*", "Geoip.*", "ip_end-ip_start as distance", )); $c->sortby('distance'); $c->limit(1); return $xpdo->getObject("Geoip", $c); }
Array ( [0] => Array ( [Geoip_id] => 11206 [Geoip_ip_start] => -734667007 [Geoip_ip_end] => -734666752 [Geoip_city_index] => 2097 [Geoip_country_index] => 1 ) )
var fieldsSer = $('Form').serializeArray(); // Собираем все поля формы var fields = {}; var name; for(var i in fieldsSer){ el = fieldsSer[i]; name = el.name fields[name] = el; // Находим лейбл для поля (у всех полей id совпадало с name, потому было просто найти лейблы для них) label = $('[for='+ name +']') text = label.text(); fields[name].label = text; } // Собираем полученный объект в JSON JSON.stringify(fields);
<?php $className = 'myClass'; $fields = array(); $fieldMeta = array(); // Формируем путь до map-файла, в который будем записывать конечные данные $file = MODX_CORE_PATH .'components/mypackage/model/mypackage/mysql/myclass.map.inc.php'; $arr = $modx->fromJSON($JSON); // Преобразуем JSON-строку в массив // Обрабатываем все поля foreach($arr as $field => $meta){ $value = $meta['value']; $dbtype = "varchar"; $phptype = "string"; $precision = 255; $null = true; $required = false; if(is_numeric( $value)){ $dbtype = "int"; $phptype = "integer"; $precision = 11; } if($value == ''){ $value = NULL; } $fields[$field] = $value; $label = trim($meta['label']); $label = preg_replace("/[\r\n]+/", "", $label); $label = preg_replace("/ {2,}/", " ", $label); if(!empty($label) && strpos($label, '*')){ $required = true; } $fieldMeta[$field] = array( 'comment' => $label, 'dbtype' => $dbtype, 'precision' => $precision, 'phptype' => $phptype, 'null' => $null, 'default' => $value, 'required' => $required, 'in_form' => true, ); } /* Готовим и записываем конечное описание объекта */ $xpdo_meta_map = array ( 'package' => 'myPackage', 'version' => '1.1', 'table' => 'mytable', 'extends' => 'xPDOSimpleObject', 'fields' => $fields, 'fieldMeta' => $fieldMeta, ); // Обратите внимание на функцию var_export - очень важная и полезная штука $fileContent= "<?php\n\$xpdo_meta_map['$className']= " . var_export($xpdo_meta_map, true) . ";\n"; // Записываем полученный массив в файл $modx->cacheManager->writeFile($file, $fileContent);
$manager = $modx->getManager(); // Создаем таблицу объекта // Таблицы не должно быть изначально, этот метод только создает новую таблицу, // не обновляет и не грохает имеющуюся $manager->createObjectContainer('myClass');