Commit b519af228167867d15d4e91e1113387838daed3f
1 parent
9d33ce37
Base-product functional
Showing
29 changed files
with
1218 additions
and
133 deletions
Show diff stats
common/components/artboxtree/ArtboxTreeBehavior.php
| @@ -20,6 +20,7 @@ class ArtboxTreeBehavior extends Behavior { | @@ -20,6 +20,7 @@ class ArtboxTreeBehavior extends Behavior { | ||
| 20 | public $keyNameGroup = 'group'; | 20 | public $keyNameGroup = 'group'; |
| 21 | public $keyNamePath = 'path_int'; | 21 | public $keyNamePath = 'path_int'; |
| 22 | public $keyNameDepth = 'depth'; // @todo -> $keyNameDepth; | 22 | public $keyNameDepth = 'depth'; // @todo -> $keyNameDepth; |
| 23 | + public $primaryKeyMode = true; | ||
| 23 | 24 | ||
| 24 | /** | 25 | /** |
| 25 | * @var string | 26 | * @var string |
| @@ -88,8 +89,31 @@ class ArtboxTreeBehavior extends Behavior { | @@ -88,8 +89,31 @@ class ArtboxTreeBehavior extends Behavior { | ||
| 88 | * get all-level children items | 89 | * get all-level children items |
| 89 | * use MP-method | 90 | * use MP-method |
| 90 | */ | 91 | */ |
| 91 | - public function getAllChildren($depth = null) { | ||
| 92 | - return $this->getAllChildrenMP($depth); | 92 | + public function getAllChildren($depth = null, $where = []) { |
| 93 | + return $this->getAllChildrenMP($depth)->where($where); | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | + /* | ||
| 97 | + * get all-level children items | ||
| 98 | + * use MP-method | ||
| 99 | + */ | ||
| 100 | + public function getAllChildrenTree($depth = null, $where = []) { | ||
| 101 | + return $this->buildTree($this->getAllChildrenMP($depth, $where)->all(), $this->owner->getAttribute($this->keyNameId)); | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + protected function buildTree(array $data, $parentId = 0) { | ||
| 105 | + $result = []; | ||
| 106 | + foreach ($data as $key => $element) { | ||
| 107 | + if ($element->getAttribute($this->keyNameParentId) == $parentId) { | ||
| 108 | + unset($data[$key]); | ||
| 109 | + $children = $this->buildTree($data, $element->getAttribute($this->keyNameId)); | ||
| 110 | + $result[] = [ | ||
| 111 | + 'item' => $element, | ||
| 112 | + 'children' => $children | ||
| 113 | + ]; | ||
| 114 | + } | ||
| 115 | + } | ||
| 116 | + return $result; | ||
| 93 | } | 117 | } |
| 94 | 118 | ||
| 95 | 119 | ||
| @@ -103,9 +127,30 @@ class ArtboxTreeBehavior extends Behavior { | @@ -103,9 +127,30 @@ class ArtboxTreeBehavior extends Behavior { | ||
| 103 | * Full-path (use MP-method) | 127 | * Full-path (use MP-method) |
| 104 | */ | 128 | */ |
| 105 | public function getParentsMP($depth = null) { | 129 | public function getParentsMP($depth = null) { |
| 130 | + $tableName = $this->owner->tableName(); | ||
| 131 | + $path = $this->owner->getAttribute($this->keyNamePath); | ||
| 132 | + $query = $this->owner->find() | ||
| 133 | + ->andWhere(['<@', "{$tableName}.[[{$this->keyNamePath}]]", $path]); | ||
| 134 | + if ($depth > 0) { | ||
| 135 | + $query->andWhere(['>=', "{$tableName}.[[{$this->keyNameDepth}]]", $this->owner->getAttribute($this->keyNameDepth) - $depth]); | ||
| 136 | + } | ||
| 137 | + $query->andWhere(['<', "{$tableName}.[[{$this->keyNameDepth}]]", $this->owner->getAttribute($this->keyNameDepth)]); | ||
| 138 | + | ||
| 139 | + $orderBy = []; | ||
| 140 | + $orderBy["{$tableName}.[[{$this->keyNameDepth}]]"] = SORT_ASC; | ||
| 141 | + $orderBy["{$tableName}.[[{$this->keyNameId}]]"] = SORT_ASC; | ||
| 142 | + | ||
| 143 | + $query | ||
| 144 | + ->andWhere($this->groupWhere()) | ||
| 145 | + ->addOrderBy($orderBy); | ||
| 146 | + $query->multiple = true; | ||
| 147 | + | ||
| 148 | + return $query; | ||
| 149 | + } | ||
| 150 | + /*public function getParentsMP($depth = null) { | ||
| 106 | $path = $this->getParentPath(); | 151 | $path = $this->getParentPath(); |
| 107 | if ($path !== null) { | 152 | if ($path !== null) { |
| 108 | - $paths = str_replace(['{', '}'], '', explode(',', $path)); | 153 | + $paths = explode(',', trim($path, '{}')); |
| 109 | if (!$this->primaryKeyMode) { | 154 | if (!$this->primaryKeyMode) { |
| 110 | $path = null; | 155 | $path = null; |
| 111 | $paths = array_map( | 156 | $paths = array_map( |
| @@ -123,7 +168,6 @@ class ArtboxTreeBehavior extends Behavior { | @@ -123,7 +168,6 @@ class ArtboxTreeBehavior extends Behavior { | ||
| 123 | } | 168 | } |
| 124 | 169 | ||
| 125 | $tableName = $this->owner->tableName(); | 170 | $tableName = $this->owner->tableName(); |
| 126 | - $condition = ['and']; | ||
| 127 | if ($this->primaryKeyMode) { | 171 | if ($this->primaryKeyMode) { |
| 128 | $condition[] = ["{$tableName}.[[{$this->keyNameId}]]" => $paths]; | 172 | $condition[] = ["{$tableName}.[[{$this->keyNameId}]]" => $paths]; |
| 129 | } else { | 173 | } else { |
| @@ -132,12 +176,12 @@ class ArtboxTreeBehavior extends Behavior { | @@ -132,12 +176,12 @@ class ArtboxTreeBehavior extends Behavior { | ||
| 132 | 176 | ||
| 133 | $query = $this->owner->find() | 177 | $query = $this->owner->find() |
| 134 | ->andWhere($condition) | 178 | ->andWhere($condition) |
| 135 | - ->andWhere($this->treeCondition()) | 179 | + ->andWhere($this->groupWhere()) |
| 136 | ->addOrderBy(["{$tableName}.[[{$this->keyNamePath}]]" => SORT_ASC]); | 180 | ->addOrderBy(["{$tableName}.[[{$this->keyNamePath}]]" => SORT_ASC]); |
| 137 | $query->multiple = true; | 181 | $query->multiple = true; |
| 138 | 182 | ||
| 139 | return $query; | 183 | return $query; |
| 140 | - } | 184 | + }*/ |
| 141 | 185 | ||
| 142 | /** | 186 | /** |
| 143 | * @param bool $asArray = false | 187 | * @param bool $asArray = false |
| @@ -147,14 +191,26 @@ class ArtboxTreeBehavior extends Behavior { | @@ -147,14 +191,26 @@ class ArtboxTreeBehavior extends Behavior { | ||
| 147 | { | 191 | { |
| 148 | return static::getParentPathInternal($this->owner->getAttribute($this->keyNamePath), $asArray); | 192 | return static::getParentPathInternal($this->owner->getAttribute($this->keyNamePath), $asArray); |
| 149 | } | 193 | } |
| 194 | + /** | ||
| 195 | + * @return array | ||
| 196 | + */ | ||
| 197 | + protected function groupWhere() | ||
| 198 | + { | ||
| 199 | + $tableName = $this->owner->tableName(); | ||
| 200 | + if ($this->keyNameGroup === null) { | ||
| 201 | + return []; | ||
| 202 | + } else { | ||
| 203 | + return ["{$tableName}.[[{$this->keyNameGroup}]]" => $this->owner->getAttribute($this->keyNameGroup)]; | ||
| 204 | + } | ||
| 205 | + } | ||
| 206 | + | ||
| 150 | 207 | ||
| 151 | public function getAllChildrenMP($depth = null) | 208 | public function getAllChildrenMP($depth = null) |
| 152 | { | 209 | { |
| 153 | $tableName = $this->owner->tableName(); | 210 | $tableName = $this->owner->tableName(); |
| 154 | $path = $this->owner->getAttribute($this->keyNamePath); | 211 | $path = $this->owner->getAttribute($this->keyNamePath); |
| 155 | $query = $this->owner->find() | 212 | $query = $this->owner->find() |
| 156 | - ->andWhere(['@>', "{$tableName}.[[{$this->keyNamePath}]]", $this->getLike($path), false]); | ||
| 157 | - | 213 | + ->andWhere(['@>', "{$tableName}.[[{$this->keyNamePath}]]", $path]); |
| 158 | 214 | ||
| 159 | if ($depth > 0) { | 215 | if ($depth > 0) { |
| 160 | $query->andWhere(['<=', "{$tableName}.[[{$this->keyNameDepth}]]", $this->owner->getAttribute($this->keyNameDepth) + $depth]); | 216 | $query->andWhere(['<=', "{$tableName}.[[{$this->keyNameDepth}]]", $this->owner->getAttribute($this->keyNameDepth) + $depth]); |
| @@ -165,7 +221,7 @@ class ArtboxTreeBehavior extends Behavior { | @@ -165,7 +221,7 @@ class ArtboxTreeBehavior extends Behavior { | ||
| 165 | $orderBy["{$tableName}.[[{$this->keyNameId}]]"] = SORT_ASC; | 221 | $orderBy["{$tableName}.[[{$this->keyNameId}]]"] = SORT_ASC; |
| 166 | 222 | ||
| 167 | $query | 223 | $query |
| 168 | - ->andWhere($this->treeCondition()) | 224 | + ->andWhere($this->groupWhere()) |
| 169 | ->addOrderBy($orderBy); | 225 | ->addOrderBy($orderBy); |
| 170 | $query->multiple = true; | 226 | $query->multiple = true; |
| 171 | 227 | ||
| @@ -186,7 +242,13 @@ class ArtboxTreeBehavior extends Behavior { | @@ -186,7 +242,13 @@ class ArtboxTreeBehavior extends Behavior { | ||
| 186 | $parent_id = $this->owner->getAttribute($this->keyNameParentId); | 242 | $parent_id = $this->owner->getAttribute($this->keyNameParentId); |
| 187 | if (empty($parent_id)) | 243 | if (empty($parent_id)) |
| 188 | return null; | 244 | return null; |
| 189 | - return $this->owner->find()->where([$this->keyNameId => $parent_id, $this->keyNameGroup => $this->owner->getAttribute($this->keyNameGroup)])->one(); | 245 | + |
| 246 | + $where = [$this->keyNameId => $parent_id]; | ||
| 247 | + if ($this->keyNameGroup) { | ||
| 248 | + $where[$this->keyNameGroup] = $this->owner->getAttribute($this->keyNameGroup); | ||
| 249 | + } | ||
| 250 | + | ||
| 251 | + return $this->owner->find()->where($where)->one(); | ||
| 190 | } | 252 | } |
| 191 | 253 | ||
| 192 | /* | 254 | /* |
| @@ -216,7 +278,11 @@ class ArtboxTreeBehavior extends Behavior { | @@ -216,7 +278,11 @@ class ArtboxTreeBehavior extends Behavior { | ||
| 216 | * @return ActiveQuery | 278 | * @return ActiveQuery |
| 217 | */ | 279 | */ |
| 218 | public function getChildrenAL() { | 280 | public function getChildrenAL() { |
| 219 | - return $this->owner->find()->where([$this->keyNameParentId => $this->owner->getAttribute($this->keyNameId), $this->keyNameGroup => $this->owner->getAttribute($this->keyNameGroup)]); | 281 | + $where = [$this->keyNameParentId => $this->owner->getAttribute($this->keyNameId)]; |
| 282 | + if ($this->keyNameGroup) { | ||
| 283 | + $where[$this->keyNameGroup] = $this->owner->getAttribute($this->keyNameGroup); | ||
| 284 | + } | ||
| 285 | + return $this->owner->find()->where($where); | ||
| 220 | } | 286 | } |
| 221 | 287 | ||
| 222 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 288 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| @@ -271,7 +337,7 @@ class ArtboxTreeBehavior extends Behavior { | @@ -271,7 +337,7 @@ class ArtboxTreeBehavior extends Behavior { | ||
| 271 | */ | 337 | */ |
| 272 | protected static function getParentPathInternal($path, $asArray = false) | 338 | protected static function getParentPathInternal($path, $asArray = false) |
| 273 | { | 339 | { |
| 274 | - $path = str_replace(['{', '}'], '', explode(',', $path)); | 340 | + $path = explode(',', trim($path, '{}')); |
| 275 | array_pop($path); | 341 | array_pop($path); |
| 276 | if ($asArray) { | 342 | if ($asArray) { |
| 277 | return $path; | 343 | return $path; |
| @@ -348,7 +414,7 @@ class ArtboxTreeBehavior extends Behavior { | @@ -348,7 +414,7 @@ class ArtboxTreeBehavior extends Behavior { | ||
| 348 | // $this->keyNamePath => $path | 414 | // $this->keyNamePath => $path |
| 349 | // ]); | 415 | // ]); |
| 350 | 416 | ||
| 351 | - $this->owner->setAttribute('path_int', $path); | 417 | + $this->owner->setAttribute($this->keyNamePath, $path); |
| 352 | // $this->owner->setAttribute($this->keyNamePath, $path); | 418 | // $this->owner->setAttribute($this->keyNamePath, $path); |
| 353 | $this->owner->setAttribute($this->keyNameDepth, $depth); | 419 | $this->owner->setAttribute($this->keyNameDepth, $depth); |
| 354 | } | 420 | } |
common/components/artboxtree/ArtboxTreeQueryTrait.php
| @@ -23,18 +23,17 @@ trait ArtboxTreeQueryTrait { | @@ -23,18 +23,17 @@ trait ArtboxTreeQueryTrait { | ||
| 23 | return self::$model; | 23 | return self::$model; |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | - public function getTree($group, $cached = true) { | ||
| 27 | - if ($cached && isset(self::$cache_tree[$group])) | ||
| 28 | - return self::$cache_tree[$group]; | ||
| 29 | - | 26 | + public function getTree($group = null) { |
| 30 | $model = $this->getModel(); | 27 | $model = $this->getModel(); |
| 31 | - $data = $this->andWhere([$model->keyNameGroup => $group])->all(); | 28 | + if ($group !== null) { |
| 29 | + $data = $this->andWhere([$model->keyNameGroup => $group])->all(); | ||
| 30 | + } else { | ||
| 31 | + $data = $this->all(); | ||
| 32 | + } | ||
| 32 | if (empty($data)) | 33 | if (empty($data)) |
| 33 | return []; | 34 | return []; |
| 34 | 35 | ||
| 35 | - self::$cache_tree[$group] = $this->buildTree($data); | ||
| 36 | - | ||
| 37 | - return self::$cache_tree[$group]; | 36 | + return $this->buildTree($data); |
| 38 | } | 37 | } |
| 39 | 38 | ||
| 40 | private function _recursiveRebuild($tree, $parentPath = null, $depth = 0) { | 39 | private function _recursiveRebuild($tree, $parentPath = null, $depth = 0) { |
common/config/main.php
| @@ -86,16 +86,13 @@ return [ | @@ -86,16 +86,13 @@ return [ | ||
| 86 | 'linked_key' => 'product_id', | 86 | 'linked_key' => 'product_id', |
| 87 | ], | 87 | ], |
| 88 | 'entity2' => [ | 88 | 'entity2' => [ |
| 89 | - 'model' => '\common\modules\rubrication\models\TaxOption', | 89 | + 'model' => '\common\modules\product\models\Category', |
| 90 | 'label' => 'Category', | 90 | 'label' => 'Category', |
| 91 | - 'listField' => 'ValueRenderFlash', | ||
| 92 | - 'key' => 'tax_option_id', | 91 | + 'listField' => 'name', |
| 92 | + 'key' => 'category_id', | ||
| 93 | 'linked_key' => 'category_id', | 93 | 'linked_key' => 'category_id', |
| 94 | - 'where' => [ | ||
| 95 | - 'tax_group_id' => 1 | ||
| 96 | - ], | ||
| 97 | 'hierarchy' => [ | 94 | 'hierarchy' => [ |
| 98 | - 'key' => 'tax_option_id', | 95 | + 'key' => 'category_id', |
| 99 | 'parentKey' => 'parent_id', | 96 | 'parentKey' => 'parent_id', |
| 100 | ] | 97 | ] |
| 101 | ], | 98 | ], |
| @@ -103,6 +100,33 @@ return [ | @@ -103,6 +100,33 @@ return [ | ||
| 103 | 'model' => '\common\modules\product\models\ProductCategory', | 100 | 'model' => '\common\modules\product\models\ProductCategory', |
| 104 | ] | 101 | ] |
| 105 | ], | 102 | ], |
| 103 | + 'tax_group_to_category' => [ | ||
| 104 | + 'name' => Yii::t('product', 'Характеристики по категориям'), | ||
| 105 | + 'field' => 'option_to_category', | ||
| 106 | + 'entity1' => [ | ||
| 107 | + 'model' => '\common\modules\rubrication\models\TaxGroup', | ||
| 108 | + 'label' => 'Group', | ||
| 109 | + 'listField' => 'name', | ||
| 110 | + 'key' => 'tax_group_id', | ||
| 111 | + 'linked_key' => 'entity1_id', | ||
| 112 | + ], | ||
| 113 | + 'entity2' => [ | ||
| 114 | + 'model' => '\common\modules\product\models\Category', | ||
| 115 | + 'label' => 'Category', | ||
| 116 | + 'listField' => 'name', | ||
| 117 | + 'key' => 'category_id', | ||
| 118 | + 'linked_key' => 'entity2_id', | ||
| 119 | + 'hierarchy' => [ | ||
| 120 | + 'key' => 'category_id', | ||
| 121 | + 'parentKey' => 'parent_id', | ||
| 122 | + ] | ||
| 123 | + ], | ||
| 124 | + 'via' => [ | ||
| 125 | + 'model' => '\common\modules\relation\models\Relation', | ||
| 126 | + 'alias' => 'alias', | ||
| 127 | + ] | ||
| 128 | + ], | ||
| 129 | + /* | ||
| 106 | 'relation_categories' => [ | 130 | 'relation_categories' => [ |
| 107 | 'name' => Yii::t('relation', 'Relation categories'), | 131 | 'name' => Yii::t('relation', 'Relation categories'), |
| 108 | 'field' => 'categories', | 132 | 'field' => 'categories', |
| @@ -194,7 +218,7 @@ return [ | @@ -194,7 +218,7 @@ return [ | ||
| 194 | 'model' => 'common\modules\rubrication\models\TaxOptionRelation', | 218 | 'model' => 'common\modules\rubrication\models\TaxOptionRelation', |
| 195 | 'alias' => 'alias', | 219 | 'alias' => 'alias', |
| 196 | ] | 220 | ] |
| 197 | - ] | 221 | + ]*/ |
| 198 | ] | 222 | ] |
| 199 | ], | 223 | ], |
| 200 | 'comment' => [ | 224 | 'comment' => [ |
common/modules/product/controllers/ManageController.php
| @@ -2,6 +2,9 @@ | @@ -2,6 +2,9 @@ | ||
| 2 | 2 | ||
| 3 | namespace common\modules\product\controllers; | 3 | namespace common\modules\product\controllers; |
| 4 | 4 | ||
| 5 | +use common\modules\product\helpers\ProductHelper; | ||
| 6 | +use common\modules\product\models\Category; | ||
| 7 | +use common\modules\product\models\ProductVariant; | ||
| 5 | use Yii; | 8 | use Yii; |
| 6 | use common\modules\product\models\Product; | 9 | use common\modules\product\models\Product; |
| 7 | use common\modules\product\models\ProductSearch; | 10 | use common\modules\product\models\ProductSearch; |
| @@ -29,6 +32,38 @@ class ManageController extends Controller | @@ -29,6 +32,38 @@ class ManageController extends Controller | ||
| 29 | ]; | 32 | ]; |
| 30 | } | 33 | } |
| 31 | 34 | ||
| 35 | + public function actionTest() { | ||
| 36 | + $categories = Category::find()->where(['depth' => 2])->all(); | ||
| 37 | + $cats_ids = []; | ||
| 38 | + foreach($categories as $cat) { | ||
| 39 | + $cats_ids[] = $cat->category_id; | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + $brands = ProductHelper::getBrands()->all(); | ||
| 43 | + $brands_ids = []; | ||
| 44 | + foreach($brands as $brand) { | ||
| 45 | + $brands_ids[] = $brand->brand_id; | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + for($i=1;$i<=1000;$i++) { | ||
| 49 | + $uniqid = uniqid(); | ||
| 50 | + $model = new Product(); | ||
| 51 | + $model->name = 'Test '. $uniqid; | ||
| 52 | + $model->brand_id = $brands_ids[array_rand($brands_ids, 1)]; | ||
| 53 | + $model->categories = [$cats_ids[array_rand($cats_ids, 1)]]; | ||
| 54 | + $model->save(); | ||
| 55 | + | ||
| 56 | + $variantModel = new ProductVariant(); | ||
| 57 | + $variantModel->product_id = $model->product_id; | ||
| 58 | + $variantModel->name = 'test-'. $uniqid; | ||
| 59 | + $variantModel->sku = $variantModel->name; | ||
| 60 | + $variantModel->price = rand(5, 200000); | ||
| 61 | + $variantModel->price_old = rand(0, 5) > 3 ? $variantModel->price* (1+rand(0, 10) / 10) : $variantModel->price; | ||
| 62 | + $variantModel->product_unit_id = rand(1, 5); | ||
| 63 | + $variantModel->save(); | ||
| 64 | + } | ||
| 65 | + } | ||
| 66 | + | ||
| 32 | /** | 67 | /** |
| 33 | * Lists all Product models. | 68 | * Lists all Product models. |
| 34 | * @return mixed | 69 | * @return mixed |
common/modules/product/helpers/ProductHelper.php
| @@ -2,23 +2,16 @@ | @@ -2,23 +2,16 @@ | ||
| 2 | 2 | ||
| 3 | namespace common\modules\product\helpers; | 3 | namespace common\modules\product\helpers; |
| 4 | 4 | ||
| 5 | -use common\modules\rubrication\models\TaxOption; | 5 | +use common\modules\product\models\Brand; |
| 6 | +use common\modules\product\models\Category; | ||
| 6 | use yii\base\Object; | 7 | use yii\base\Object; |
| 7 | 8 | ||
| 8 | class ProductHelper extends Object { | 9 | class ProductHelper extends Object { |
| 9 | - public static function getCategoryGroupId() { | ||
| 10 | - return \Yii::$app->getModule('product')->params['category_group']; | ||
| 11 | - } | ||
| 12 | - | ||
| 13 | - public static function getBrandGroupId() { | ||
| 14 | - return \Yii::$app->getModule('product')->params['brand_group']; | ||
| 15 | - } | ||
| 16 | - | ||
| 17 | public static function getCategories() { | 10 | public static function getCategories() { |
| 18 | - return TaxOption::find()->getTree(self::getCategoryGroupId()); | 11 | + return Category::find()->getTree(); |
| 19 | } | 12 | } |
| 20 | 13 | ||
| 21 | public static function getBrands() { | 14 | public static function getBrands() { |
| 22 | - return TaxOption::find()->where(['tax_group_id' => self::getBrandGroupId()]); | 15 | + return Brand::find(); |
| 23 | } | 16 | } |
| 24 | } | 17 | } |
| 25 | \ No newline at end of file | 18 | \ No newline at end of file |
common/modules/product/models/Category.php
| @@ -4,6 +4,7 @@ namespace common\modules\product\models; | @@ -4,6 +4,7 @@ namespace common\modules\product\models; | ||
| 4 | 4 | ||
| 5 | use common\behaviors\Slug; | 5 | use common\behaviors\Slug; |
| 6 | use common\components\artboxtree\ArtboxTreeBehavior; | 6 | use common\components\artboxtree\ArtboxTreeBehavior; |
| 7 | +use common\modules\relation\relationBehavior; | ||
| 7 | use common\modules\rubrication\behaviors\ArtboxSynonymBehavior; | 8 | use common\modules\rubrication\behaviors\ArtboxSynonymBehavior; |
| 8 | use Yii; | 9 | use Yii; |
| 9 | 10 | ||
| @@ -53,6 +54,12 @@ class Category extends \yii\db\ActiveRecord | @@ -53,6 +54,12 @@ class Category extends \yii\db\ActiveRecord | ||
| 53 | 'valueFields' => [ // postKey => DBFieldName | 54 | 'valueFields' => [ // postKey => DBFieldName |
| 54 | 'name' => 'value' | 55 | 'name' => 'value' |
| 55 | ] | 56 | ] |
| 57 | + ], | ||
| 58 | + [ | ||
| 59 | + 'class' => relationBehavior::className(), | ||
| 60 | + 'relations' => [ | ||
| 61 | + 'product_categories' => 'entity2' // Products of category | ||
| 62 | + ] | ||
| 56 | ] | 63 | ] |
| 57 | ]; | 64 | ]; |
| 58 | } | 65 | } |
common/modules/product/models/Product.php
| @@ -11,13 +11,18 @@ use yii\db\ActiveQuery; | @@ -11,13 +11,18 @@ use yii\db\ActiveQuery; | ||
| 11 | * This is the model class for table "{{%product}}". | 11 | * This is the model class for table "{{%product}}". |
| 12 | * | 12 | * |
| 13 | * @property string $name | 13 | * @property string $name |
| 14 | - * @property integer $tax_brand_id | 14 | + * @property integer $brand_id |
| 15 | * @property integer $product_id | 15 | * @property integer $product_id |
| 16 | - * | ||
| 17 | - * @property TaxOption $categories | 16 | + * @property Category $category |
| 17 | + * @property array $categories | ||
| 18 | + * @property ProductVariant $variant | ||
| 19 | + * @property ProductImage $image | ||
| 20 | + * @property array $images | ||
| 18 | */ | 21 | */ |
| 19 | class Product extends \yii\db\ActiveRecord | 22 | class Product extends \yii\db\ActiveRecord |
| 20 | { | 23 | { |
| 24 | + /** @var array $variants */ | ||
| 25 | + public $_variants = []; | ||
| 21 | /** | 26 | /** |
| 22 | * @inheritdoc | 27 | * @inheritdoc |
| 23 | */ | 28 | */ |
| @@ -47,9 +52,9 @@ class Product extends \yii\db\ActiveRecord | @@ -47,9 +52,9 @@ class Product extends \yii\db\ActiveRecord | ||
| 47 | public function rules() | 52 | public function rules() |
| 48 | { | 53 | { |
| 49 | return [ | 54 | return [ |
| 50 | - [['tax_brand_id'], 'integer'], | 55 | + [['brand_id'], 'integer'], |
| 51 | [['name'], 'string', 'max' => 150], | 56 | [['name'], 'string', 'max' => 150], |
| 52 | - [['categories'], 'safe'], | 57 | + [['categories', 'variants'], 'safe'], |
| 53 | // [['product_id'], 'exist', 'skipOnError' => true, 'targetClass' => Product::className(), 'targetAttribute' => ['product_id' => 'product_id']], | 58 | // [['product_id'], 'exist', 'skipOnError' => true, 'targetClass' => Product::className(), 'targetAttribute' => ['product_id' => 'product_id']], |
| 54 | ]; | 59 | ]; |
| 55 | } | 60 | } |
| @@ -60,11 +65,11 @@ class Product extends \yii\db\ActiveRecord | @@ -60,11 +65,11 @@ class Product extends \yii\db\ActiveRecord | ||
| 60 | public function attributeLabels() | 65 | public function attributeLabels() |
| 61 | { | 66 | { |
| 62 | return [ | 67 | return [ |
| 63 | - 'product_id' => Yii::t('product', 'Product ID'), | 68 | + 'product_id' => Yii::t('product', 'ID'), |
| 64 | 'name' => Yii::t('product', 'Name'), | 69 | 'name' => Yii::t('product', 'Name'), |
| 65 | - 'tax_brand_id' => Yii::t('product', 'Brand'), | ||
| 66 | - 'brand' => Yii::t('product', 'Brand'), | 70 | + 'brand_id' => Yii::t('product', 'Brand'), |
| 67 | 'categories' => Yii::t('product', 'Categories'), // relation behavior field | 71 | 'categories' => Yii::t('product', 'Categories'), // relation behavior field |
| 72 | + 'category' => Yii::t('product', 'Category'), // relation behavior field | ||
| 68 | ]; | 73 | ]; |
| 69 | } | 74 | } |
| 70 | 75 | ||
| @@ -73,17 +78,63 @@ class Product extends \yii\db\ActiveRecord | @@ -73,17 +78,63 @@ class Product extends \yii\db\ActiveRecord | ||
| 73 | */ | 78 | */ |
| 74 | public function getBrand() | 79 | public function getBrand() |
| 75 | { | 80 | { |
| 76 | - return $this->hasOne(TaxOption::className(), ['tax_option_id' => 'tax_brand_id']); | 81 | + return $this->hasOne(Brand::className(), ['brand_id' => 'brand_id']); |
| 77 | } | 82 | } |
| 78 | 83 | ||
| 79 | - public function getFullName() | 84 | + /** |
| 85 | + * @return \yii\db\ActiveQuery | ||
| 86 | + */ | ||
| 87 | + public function getImage() | ||
| 88 | + { | ||
| 89 | + return $this->hasOne(ProductImage::className(), ['product_id' => 'product_id']); | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + /** | ||
| 93 | + * @return \yii\db\ActiveQuery | ||
| 94 | + */ | ||
| 95 | + public function getImages() | ||
| 80 | { | 96 | { |
| 81 | - return $this->brandname .' '. $this->name; | 97 | + return $this->hasMany(ProductImage::className(), ['product_id' => 'product_id']); |
| 82 | } | 98 | } |
| 83 | 99 | ||
| 84 | - public function getBrandName() | 100 | + /** |
| 101 | + * @return \yii\db\ActiveQuery | ||
| 102 | + */ | ||
| 103 | + public function getVariant() | ||
| 85 | { | 104 | { |
| 86 | - return $this->getBrand()->one()->valueRenderHTML; | 105 | + return $this->hasOne(ProductVariant::className(), ['product_id' => 'product_id']); |
| 106 | + } | ||
| 107 | + | ||
| 108 | + public function getVariantPrice() { | ||
| 109 | + return $this->variant->price; | ||
| 110 | + } | ||
| 111 | + /** | ||
| 112 | + * @return \yii\db\ActiveQuery | ||
| 113 | + */ | ||
| 114 | + public function getVariants() | ||
| 115 | + { | ||
| 116 | + return $this->hasMany(ProductVariant::className(), ['product_id' => 'product_id']); | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + public function setVariants($variants) { | ||
| 120 | + $this->_variants = $variants; | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + public function getFullName() | ||
| 124 | + { | ||
| 125 | + return $this->brand->name .' '. $this->name; | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + public function getCategories() { | ||
| 129 | + return $this->getRelations('product_categories'); | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + public function getCategoriesNames() { | ||
| 133 | + $result = []; | ||
| 134 | + foreach($this->categories as $category) { | ||
| 135 | + $result[] = $category->name; | ||
| 136 | + } | ||
| 137 | + return $result; | ||
| 87 | } | 138 | } |
| 88 | 139 | ||
| 89 | public function getCategory() { | 140 | public function getCategory() { |
| @@ -91,8 +142,8 @@ class Product extends \yii\db\ActiveRecord | @@ -91,8 +142,8 @@ class Product extends \yii\db\ActiveRecord | ||
| 91 | $categories = $this->getRelations('product_categories'); | 142 | $categories = $this->getRelations('product_categories'); |
| 92 | $count = $categories->count(); | 143 | $count = $categories->count(); |
| 93 | if ($count == 0) | 144 | if ($count == 0) |
| 94 | - return 'None'; | ||
| 95 | - return $categories->one()->ValueRenderFlash . ($count > 1 ? ' + '. $count : ''); | 145 | + return; |
| 146 | + return $categories->one(); | ||
| 96 | } | 147 | } |
| 97 | 148 | ||
| 98 | /** | 149 | /** |
| @@ -103,4 +154,28 @@ class Product extends \yii\db\ActiveRecord | @@ -103,4 +154,28 @@ class Product extends \yii\db\ActiveRecord | ||
| 103 | { | 154 | { |
| 104 | return new ProductQuery(get_called_class()); | 155 | return new ProductQuery(get_called_class()); |
| 105 | } | 156 | } |
| 157 | + | ||
| 158 | + public function afterSave($insert, $changedAttributes) | ||
| 159 | + { | ||
| 160 | + parent::afterSave($insert, $changedAttributes); | ||
| 161 | + | ||
| 162 | + $todel = []; | ||
| 163 | + foreach ($this->variants ? : [] as $_variant) { | ||
| 164 | + $todel[$_variant->product_variant_id] = $_variant->product_variant_id; | ||
| 165 | + } | ||
| 166 | + foreach ($this->_variants as $_variant) { | ||
| 167 | + if (!empty($_variant['product_variant_id'])) { | ||
| 168 | + unset($todel[$_variant['product_variant_id']]); | ||
| 169 | + $model = ProductVariant::findOne($_variant['product_variant_id']); | ||
| 170 | + } else { | ||
| 171 | + $model = new ProductVariant(); | ||
| 172 | + } | ||
| 173 | + $_variant['product_id'] = $this->product_id; | ||
| 174 | + $model->load(['ProductVariant' => $_variant]); | ||
| 175 | + $model->save(); | ||
| 176 | + } | ||
| 177 | + if (!empty($todel)) { | ||
| 178 | + ProductVariant::deleteAll(['product_variant_id' => $todel]); | ||
| 179 | + } | ||
| 180 | + } | ||
| 106 | } | 181 | } |
common/modules/product/models/ProductCategory.php
| @@ -26,15 +26,14 @@ class ProductCategory extends Relation | @@ -26,15 +26,14 @@ class ProductCategory extends Relation | ||
| 26 | return 'product_category'; | 26 | return 'product_category'; |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | - | ||
| 30 | /** | 29 | /** |
| 31 | * @inheritdoc | 30 | * @inheritdoc |
| 32 | */ | 31 | */ |
| 33 | public function rules() | 32 | public function rules() |
| 34 | { | 33 | { |
| 35 | return [ | 34 | return [ |
| 36 | - [['product_id', 'dev_category_id'], 'integer'], | ||
| 37 | - [['dev_category_id'], 'exist', 'skipOnError' => true, 'targetClass' => TaxOption::className(), 'targetAttribute' => ['dev_category_id' => 'tax_option_id']], | 35 | + [['product_id', 'category_id'], 'integer'], |
| 36 | + [['category_id'], 'exist', 'skipOnError' => true, 'targetClass' => Category::className(), 'targetAttribute' => ['category_id' => 'category_id']], | ||
| 38 | [['product_id'], 'exist', 'skipOnError' => true, 'targetClass' => Product::className(), 'targetAttribute' => ['product_id' => 'product_id']], | 37 | [['product_id'], 'exist', 'skipOnError' => true, 'targetClass' => Product::className(), 'targetAttribute' => ['product_id' => 'product_id']], |
| 39 | ]; | 38 | ]; |
| 40 | } | 39 | } |
| @@ -46,7 +45,7 @@ class ProductCategory extends Relation | @@ -46,7 +45,7 @@ class ProductCategory extends Relation | ||
| 46 | { | 45 | { |
| 47 | return [ | 46 | return [ |
| 48 | 'product_id' => Yii::t('product', 'Product'), | 47 | 'product_id' => Yii::t('product', 'Product'), |
| 49 | - 'dev_category_id' => Yii::t('product', 'Category'), | 48 | + 'category_id' => Yii::t('product', 'Category'), |
| 50 | ]; | 49 | ]; |
| 51 | } | 50 | } |
| 52 | 51 |
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +namespace common\modules\product\models; | ||
| 4 | + | ||
| 5 | +use Yii; | ||
| 6 | +use yii\web\UploadedFile; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * This is the model class for table "product_image". | ||
| 10 | + * | ||
| 11 | + * @property integer $product_image_id | ||
| 12 | + * @property integer $product_id | ||
| 13 | + * @property string $image | ||
| 14 | + * @property string $alt | ||
| 15 | + * @property string $title | ||
| 16 | + * | ||
| 17 | + * @property Product $product | ||
| 18 | + */ | ||
| 19 | +class ProductImage extends \yii\db\ActiveRecord | ||
| 20 | +{ | ||
| 21 | + public $image; | ||
| 22 | + /** | ||
| 23 | + * @inheritdoc | ||
| 24 | + */ | ||
| 25 | + public static function tableName() | ||
| 26 | + { | ||
| 27 | + return 'product_image'; | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * @inheritdoc | ||
| 32 | + */ | ||
| 33 | + public function rules() | ||
| 34 | + { | ||
| 35 | + return [ | ||
| 36 | + [['product_image_id', 'product_id'], 'required'], | ||
| 37 | + [['product_image_id', 'product_id'], 'integer'], | ||
| 38 | + [['alt', 'title'], 'string', 'max' => 255], | ||
| 39 | + [['image'], 'safe'], | ||
| 40 | + [['product_id'], 'exist', 'skipOnError' => true, 'targetClass' => Product::className(), 'targetAttribute' => ['product_id' => 'product_id']], | ||
| 41 | + [['image'], 'file', 'extensions'=>'jpg, gif, png'], | ||
| 42 | + ]; | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + /** | ||
| 46 | + * @inheritdoc | ||
| 47 | + */ | ||
| 48 | + public function attributeLabels() | ||
| 49 | + { | ||
| 50 | + return [ | ||
| 51 | + 'product_image_id' => Yii::t('product', 'Product Image ID'), | ||
| 52 | + 'product_id' => Yii::t('product', 'Product ID'), | ||
| 53 | + 'image' => Yii::t('product', 'Image'), | ||
| 54 | + 'alt' => Yii::t('product', 'Alt'), | ||
| 55 | + 'title' => Yii::t('product', 'Title'), | ||
| 56 | + ]; | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + /** | ||
| 60 | + * @return \yii\db\ActiveQuery | ||
| 61 | + */ | ||
| 62 | + public function getProduct() | ||
| 63 | + { | ||
| 64 | + return $this->hasOne(Product::className(), ['product_id' => 'product_id']); | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + /** | ||
| 68 | + * @inheritdoc | ||
| 69 | + * @return ProductImageQuery the active query used by this AR class. | ||
| 70 | + */ | ||
| 71 | + public static function find() | ||
| 72 | + { | ||
| 73 | + return new ProductImageQuery(get_called_class()); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + /** | ||
| 77 | + * fetch stored image file name with complete path | ||
| 78 | + * @return string | ||
| 79 | + */ | ||
| 80 | + public function getImageFile() | ||
| 81 | + { | ||
| 82 | + return isset($this->image) ? Yii::$app->params['uploadPath'] . $this->image : null; | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + /** | ||
| 86 | + * fetch stored image url | ||
| 87 | + * @return string | ||
| 88 | + */ | ||
| 89 | + public function getImageUrl() | ||
| 90 | + { | ||
| 91 | + // return a default image placeholder if your source image is not found | ||
| 92 | + $image = isset($this->image) ? $this->image : 'default.jpg'; | ||
| 93 | + return Yii::$app->params['uploadUrl'] . $image; | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | + /** | ||
| 97 | + * Process upload of image | ||
| 98 | + * | ||
| 99 | + * @return mixed the uploaded image instance | ||
| 100 | + */ | ||
| 101 | + public function uploadImage() { | ||
| 102 | + // get the uploaded file instance. for multiple file uploads | ||
| 103 | + // the following data will return an array (you may need to use | ||
| 104 | + // getInstances method) | ||
| 105 | + $image = UploadedFile::getInstance($this, 'image'); | ||
| 106 | + | ||
| 107 | + // if no image was uploaded abort the upload | ||
| 108 | + if (empty($image)) { | ||
| 109 | + return false; | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + // store the source file name | ||
| 113 | + $this->filename = $image->name; | ||
| 114 | + $ext = end((explode(".", $image->name))); | ||
| 115 | + | ||
| 116 | + // generate a unique file name | ||
| 117 | + $this->image = Yii::$app->security->generateRandomString().".{$ext}"; | ||
| 118 | + | ||
| 119 | + // the uploaded image instance | ||
| 120 | + return $image; | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + /** | ||
| 124 | + * Process deletion of image | ||
| 125 | + * | ||
| 126 | + * @return boolean the status of deletion | ||
| 127 | + */ | ||
| 128 | + public function deleteImage() { | ||
| 129 | + $file = $this->getImageFile(); | ||
| 130 | + | ||
| 131 | + // check if file exists on server | ||
| 132 | + if (empty($file) || !file_exists($file)) { | ||
| 133 | + return false; | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + // check if uploaded file can be deleted on server | ||
| 137 | + if (!unlink($file)) { | ||
| 138 | + return false; | ||
| 139 | + } | ||
| 140 | + | ||
| 141 | + // if deletion successful, reset your file attributes | ||
| 142 | + $this->image = null; | ||
| 143 | + $this->filename = null; | ||
| 144 | + | ||
| 145 | + return true; | ||
| 146 | + } | ||
| 147 | +} |
common/modules/product/models/ProductImageQuery.php
0 → 100644
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +namespace common\modules\product\models; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * This is the ActiveQuery class for [[ProductImage]]. | ||
| 7 | + * | ||
| 8 | + * @see ProductImage | ||
| 9 | + */ | ||
| 10 | +class ProductImageQuery extends \yii\db\ActiveQuery | ||
| 11 | +{ | ||
| 12 | + /*public function active() | ||
| 13 | + { | ||
| 14 | + return $this->andWhere('[[status]]=1'); | ||
| 15 | + }*/ | ||
| 16 | + | ||
| 17 | + /** | ||
| 18 | + * @inheritdoc | ||
| 19 | + * @return ProductImage[]|array | ||
| 20 | + */ | ||
| 21 | + public function all($db = null) | ||
| 22 | + { | ||
| 23 | + return parent::all($db); | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + /** | ||
| 27 | + * @inheritdoc | ||
| 28 | + * @return ProductImage|array|null | ||
| 29 | + */ | ||
| 30 | + public function one($db = null) | ||
| 31 | + { | ||
| 32 | + return parent::one($db); | ||
| 33 | + } | ||
| 34 | +} |
common/modules/product/models/ProductQuery.php
| @@ -31,4 +31,15 @@ class ProductQuery extends \yii\db\ActiveQuery | @@ -31,4 +31,15 @@ class ProductQuery extends \yii\db\ActiveQuery | ||
| 31 | { | 31 | { |
| 32 | return parent::one($db); | 32 | return parent::one($db); |
| 33 | } | 33 | } |
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * Select category by alias | ||
| 37 | + * @param $slug | ||
| 38 | + * @return $this | ||
| 39 | + */ | ||
| 40 | + public function byAlias($alias) | ||
| 41 | + { | ||
| 42 | + $this->andFilterWhere(['alias' => $alias]); | ||
| 43 | + return $this; | ||
| 44 | + } | ||
| 34 | } | 45 | } |
common/modules/product/models/ProductSearch.php
| @@ -67,4 +67,16 @@ class ProductSearch extends Product | @@ -67,4 +67,16 @@ class ProductSearch extends Product | ||
| 67 | 67 | ||
| 68 | return $dataProvider; | 68 | return $dataProvider; |
| 69 | } | 69 | } |
| 70 | + | ||
| 71 | + public static function findByAlias($alias) { | ||
| 72 | + /** @var ProductQuery $query */ | ||
| 73 | + $query = Category::find(); | ||
| 74 | + $query->byAlias($alias); | ||
| 75 | + if (($model = $query->one()) !== null) { | ||
| 76 | + return $model; | ||
| 77 | + } else { | ||
| 78 | + throw new NotFoundHttpException('The requested product does not exist.'); | ||
| 79 | + } | ||
| 80 | + } | ||
| 81 | + | ||
| 70 | } | 82 | } |
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +namespace common\modules\product\models; | ||
| 4 | + | ||
| 5 | +use Yii; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * This is the model class for table "product_variant". | ||
| 9 | + * | ||
| 10 | + * @property integer $product_variant_id | ||
| 11 | + * @property integer $product_id | ||
| 12 | + * @property string $name | ||
| 13 | + * @property string $sku | ||
| 14 | + * @property double $price | ||
| 15 | + * @property double $price_old | ||
| 16 | + * @property double $stock | ||
| 17 | + * @property integer $product_unit_id | ||
| 18 | + * | ||
| 19 | + * @property ProductUnit $productUnit | ||
| 20 | + */ | ||
| 21 | +class ProductVariant extends \yii\db\ActiveRecord | ||
| 22 | +{ | ||
| 23 | + /** | ||
| 24 | + * @inheritdoc | ||
| 25 | + */ | ||
| 26 | + public static function tableName() | ||
| 27 | + { | ||
| 28 | + return 'product_variant'; | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + /** | ||
| 32 | + * @inheritdoc | ||
| 33 | + */ | ||
| 34 | + public function rules() | ||
| 35 | + { | ||
| 36 | + return [ | ||
| 37 | + [['product_id', 'name', 'sku', 'product_unit_id'], 'required'], | ||
| 38 | + [['product_id', 'product_unit_id'], 'integer'], | ||
| 39 | + [['price', 'price_old', 'stock'], 'number'], | ||
| 40 | + [['name', 'sku'], 'string', 'max' => 255], | ||
| 41 | + [['product_unit_id'], 'exist', 'skipOnError' => true, 'targetClass' => ProductUnit::className(), 'targetAttribute' => ['product_unit_id' => 'product_unit_id']], | ||
| 42 | + ]; | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + /** | ||
| 46 | + * @inheritdoc | ||
| 47 | + */ | ||
| 48 | + public function attributeLabels() | ||
| 49 | + { | ||
| 50 | + return [ | ||
| 51 | + 'product_variant_id' => Yii::t('product', 'Product Variant ID'), | ||
| 52 | + 'product_id' => Yii::t('product', 'Product ID'), | ||
| 53 | + 'name' => Yii::t('product', 'Name'), | ||
| 54 | + 'sku' => Yii::t('product', 'Sku'), | ||
| 55 | + 'price' => Yii::t('product', 'Price'), | ||
| 56 | + 'price_old' => Yii::t('product', 'Price Old'), | ||
| 57 | + 'stock' => Yii::t('product', 'Stock'), | ||
| 58 | + 'product_unit_id' => Yii::t('product', 'Product Unit ID'), | ||
| 59 | + ]; | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + /** | ||
| 63 | + * @return \yii\db\ActiveQuery | ||
| 64 | + */ | ||
| 65 | + public function getProductUnit() | ||
| 66 | + { | ||
| 67 | + return $this->hasOne(ProductUnit::className(), ['product_unit_id' => 'product_unit_id']); | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + /** | ||
| 71 | + * @inheritdoc | ||
| 72 | + * @return ProductVariantQuery the active query used by this AR class. | ||
| 73 | + */ | ||
| 74 | + public static function find() | ||
| 75 | + { | ||
| 76 | + return new ProductVariantQuery(get_called_class()); | ||
| 77 | + } | ||
| 78 | +} |
common/modules/product/models/ProductVariantQuery.php
0 → 100644
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +namespace common\modules\product\models; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * This is the ActiveQuery class for [[ProductVariant]]. | ||
| 7 | + * | ||
| 8 | + * @see ProductVariant | ||
| 9 | + */ | ||
| 10 | +class ProductVariantQuery extends \yii\db\ActiveQuery | ||
| 11 | +{ | ||
| 12 | + /*public function active() | ||
| 13 | + { | ||
| 14 | + return $this->andWhere('[[status]]=1'); | ||
| 15 | + }*/ | ||
| 16 | + | ||
| 17 | + /** | ||
| 18 | + * @inheritdoc | ||
| 19 | + * @return ProductVariant[]|array | ||
| 20 | + */ | ||
| 21 | + public function all($db = null) | ||
| 22 | + { | ||
| 23 | + return parent::all($db); | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + /** | ||
| 27 | + * @inheritdoc | ||
| 28 | + * @return ProductVariant|array|null | ||
| 29 | + */ | ||
| 30 | + public function one($db = null) | ||
| 31 | + { | ||
| 32 | + return parent::one($db); | ||
| 33 | + } | ||
| 34 | +} |
common/modules/product/views/manage/_form.php
| @@ -5,6 +5,9 @@ use yii\widgets\ActiveForm; | @@ -5,6 +5,9 @@ use yii\widgets\ActiveForm; | ||
| 5 | use yii\helpers\ArrayHelper; | 5 | use yii\helpers\ArrayHelper; |
| 6 | use common\components\artboxtree\ArtboxTreeHelper; | 6 | use common\components\artboxtree\ArtboxTreeHelper; |
| 7 | use common\modules\product\helpers\ProductHelper; | 7 | use common\modules\product\helpers\ProductHelper; |
| 8 | +use kartik\file\FileInput; | ||
| 9 | +use unclead\widgets\MultipleInput; | ||
| 10 | +use unclead\widgets\MultipleInputColumn; | ||
| 8 | 11 | ||
| 9 | /* @var $this yii\web\View */ | 12 | /* @var $this yii\web\View */ |
| 10 | /* @var $model common\modules\product\models\Product */ | 13 | /* @var $model common\modules\product\models\Product */ |
| @@ -17,23 +20,76 @@ use common\modules\product\helpers\ProductHelper; | @@ -17,23 +20,76 @@ use common\modules\product\helpers\ProductHelper; | ||
| 17 | 20 | ||
| 18 | <?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?> | 21 | <?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?> |
| 19 | 22 | ||
| 20 | - <?= $form->field($model, 'tax_brand_id')->dropDownList( | ||
| 21 | - ArrayHelper::map(ProductHelper::getBrands()->all(), 'tax_option_id', 'ValueRenderFlash'), | 23 | + <?= $form->field($model, 'brand_id')->dropDownList( |
| 24 | + ArrayHelper::map(ProductHelper::getBrands()->all(), 'brand_id', 'name'), | ||
| 22 | [ | 25 | [ |
| 23 | 'prompt' => Yii::t('product', 'Select brand') | 26 | 'prompt' => Yii::t('product', 'Select brand') |
| 24 | ] | 27 | ] |
| 25 | ) ?> | 28 | ) ?> |
| 26 | - <?php | ||
| 27 | -// var_dump($model->categories); | ||
| 28 | - ?> | 29 | + |
| 29 | <?= $form->field($model, 'categories')->dropDownList( | 30 | <?= $form->field($model, 'categories')->dropDownList( |
| 30 | - ArtboxTreeHelper::treeMap(ProductHelper::getCategories(), 'tax_option_id', 'ValueRenderFlash'), | 31 | + ArtboxTreeHelper::treeMap(ProductHelper::getCategories(), 'category_id', 'name'), |
| 31 | [ | 32 | [ |
| 32 | // 'prompt' => Yii::t('product', 'Select category'), | 33 | // 'prompt' => Yii::t('product', 'Select category'), |
| 33 | 'multiple' => true | 34 | 'multiple' => true |
| 34 | ] | 35 | ] |
| 35 | ) ?> | 36 | ) ?> |
| 36 | 37 | ||
| 38 | + <?php /*= $form->field($model, 'images[]')->widget(FileInput::classname(), [ | ||
| 39 | + 'options' => [ | ||
| 40 | + 'accept' => 'image/*', | ||
| 41 | + 'multiple' => true, | ||
| 42 | + ], | ||
| 43 | + 'pluginOptions' => [ | ||
| 44 | +// 'uploadUrl' => \yii\helpers\Url::to(['/site/file-upload']), | ||
| 45 | + ] | ||
| 46 | + ]); | ||
| 47 | + */?> | ||
| 48 | + | ||
| 49 | + <?= $form->field($model, 'variants')->widget(MultipleInput::className(), [ | ||
| 50 | + 'columns' => [ | ||
| 51 | + [ | ||
| 52 | + 'name' => 'product_variant_id', | ||
| 53 | + 'type' => MultipleInputColumn::TYPE_HIDDEN_INPUT, | ||
| 54 | + ], | ||
| 55 | + [ | ||
| 56 | + 'name' => 'name', | ||
| 57 | + 'type' => MultipleInputColumn::TYPE_TEXT_INPUT, | ||
| 58 | + 'title' => 'Name', | ||
| 59 | + ], | ||
| 60 | + [ | ||
| 61 | + 'name' => 'sku', | ||
| 62 | + 'type' => MultipleInputColumn::TYPE_TEXT_INPUT, | ||
| 63 | + 'title' => 'SKU', | ||
| 64 | + ], | ||
| 65 | + [ | ||
| 66 | + 'name' => 'price', | ||
| 67 | + 'type' => MultipleInputColumn::TYPE_TEXT_INPUT, | ||
| 68 | + 'title' => 'Price', | ||
| 69 | + ], | ||
| 70 | + [ | ||
| 71 | + 'name' => 'price_old', | ||
| 72 | + 'type' => MultipleInputColumn::TYPE_TEXT_INPUT, | ||
| 73 | + 'title' => 'Old Price', | ||
| 74 | + ], | ||
| 75 | + [ | ||
| 76 | + 'name' => 'product_unit_id', | ||
| 77 | + 'type' => MultipleInputColumn::TYPE_DROPDOWN, | ||
| 78 | + 'title' => 'Unit', | ||
| 79 | + 'items' => ArrayHelper::map(\common\modules\product\models\ProductUnit::find()->all(), 'product_unit_id', 'name'), | ||
| 80 | + ], | ||
| 81 | + [ | ||
| 82 | + 'name' => 'stock', | ||
| 83 | + 'type' => MultipleInputColumn::TYPE_TEXT_INPUT, | ||
| 84 | + 'title' => 'Stock', | ||
| 85 | + 'options' => [ | ||
| 86 | + 'placeholder' => '∞' | ||
| 87 | + ], | ||
| 88 | + ], | ||
| 89 | + ], | ||
| 90 | + ]); | ||
| 91 | + ?> | ||
| 92 | + | ||
| 37 | <div class="form-group"> | 93 | <div class="form-group"> |
| 38 | <?= Html::submitButton($model->isNewRecord ? Yii::t('product', 'Create') : Yii::t('product', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> | 94 | <?= Html::submitButton($model->isNewRecord ? Yii::t('product', 'Create') : Yii::t('product', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> |
| 39 | </div> | 95 | </div> |
common/modules/product/views/manage/_search.php
| @@ -17,7 +17,7 @@ use yii\widgets\ActiveForm; | @@ -17,7 +17,7 @@ use yii\widgets\ActiveForm; | ||
| 17 | 17 | ||
| 18 | <?= $form->field($model, 'name') ?> | 18 | <?= $form->field($model, 'name') ?> |
| 19 | 19 | ||
| 20 | - <?= $form->field($model, 'tax_brand_id') ?> | 20 | + <?= $form->field($model, 'brand_id') ?> |
| 21 | 21 | ||
| 22 | <?= $form->field($model, 'product_id') ?> | 22 | <?= $form->field($model, 'product_id') ?> |
| 23 | 23 |
common/modules/product/views/manage/index.php
| @@ -22,11 +22,10 @@ $this->params['breadcrumbs'][] = $this->title; | @@ -22,11 +22,10 @@ $this->params['breadcrumbs'][] = $this->title; | ||
| 22 | 'filterModel' => $searchModel, | 22 | 'filterModel' => $searchModel, |
| 23 | 'columns' => [ | 23 | 'columns' => [ |
| 24 | ['class' => 'yii\grid\SerialColumn'], | 24 | ['class' => 'yii\grid\SerialColumn'], |
| 25 | - | ||
| 26 | -// 'product_id', | ||
| 27 | - 'fullname', | ||
| 28 | - 'brandname', | ||
| 29 | - 'category', | 25 | + 'product_id', |
| 26 | + 'name', | ||
| 27 | + 'brand.name', | ||
| 28 | + 'category.name', | ||
| 30 | 29 | ||
| 31 | ['class' => 'yii\grid\ActionColumn'], | 30 | ['class' => 'yii\grid\ActionColumn'], |
| 32 | ], | 31 | ], |
common/modules/product/views/manage/view.php
| @@ -28,9 +28,11 @@ $this->params['breadcrumbs'][] = $this->title; | @@ -28,9 +28,11 @@ $this->params['breadcrumbs'][] = $this->title; | ||
| 28 | <?= DetailView::widget([ | 28 | <?= DetailView::widget([ |
| 29 | 'model' => $model, | 29 | 'model' => $model, |
| 30 | 'attributes' => [ | 30 | 'attributes' => [ |
| 31 | - 'name', | ||
| 32 | - 'tax_brand_id', | ||
| 33 | 'product_id', | 31 | 'product_id', |
| 32 | + 'name', | ||
| 33 | + 'fullname', | ||
| 34 | + 'brand.name', | ||
| 35 | + 'category.name', | ||
| 34 | ], | 36 | ], |
| 35 | ]) ?> | 37 | ]) ?> |
| 36 | 38 |
common/modules/product/widgets/views/submenu.php
| 1 | <div class="menu_item"> | 1 | <div class="menu_item"> |
| 2 | - <?= \yii\helpers\Html::a($rootCategory->name, ['product/category', 'alias' => $rootCategory->alias], ['class' => 'submenu_button '. $rootClass])?> | 2 | + <?= \yii\helpers\Html::a($rootCategory->name, ['catalog/category', 'alias' => $rootCategory->alias], ['class' => 'submenu_button '. $rootClass])?> |
| 3 | <div class="submenu"> | 3 | <div class="submenu"> |
| 4 | <ul class="categories"> | 4 | <ul class="categories"> |
| 5 | <li class="sub_cat"><span>Популярные категории</span> | 5 | <li class="sub_cat"><span>Популярные категории</span> |
| @@ -7,7 +7,7 @@ | @@ -7,7 +7,7 @@ | ||
| 7 | <div class="sub_cat_content"> | 7 | <div class="sub_cat_content"> |
| 8 | <div class="content_items"> | 8 | <div class="content_items"> |
| 9 | <?php foreach($populary as $_item) :?> | 9 | <?php foreach($populary as $_item) :?> |
| 10 | - <div class="content_item"><a href="<?= \yii\helpers\Url::to(['product/category', 'alias' => $_item->alias])?>"> | 10 | + <div class="content_item"><a href="<?= \yii\helpers\Url::to(['catalog/category', 'alias' => $_item->alias])?>"> |
| 11 | <div valign="top" class="picture"><img valign="top" src="<?= $_item->image?>"></div> | 11 | <div valign="top" class="picture"><img valign="top" src="<?= $_item->image?>"></div> |
| 12 | <div class="title"><?= $_item->name?></div> | 12 | <div class="title"><?= $_item->name?></div> |
| 13 | </a></div> | 13 | </a></div> |
| @@ -23,7 +23,7 @@ | @@ -23,7 +23,7 @@ | ||
| 23 | <div class="sub_cat_content"> | 23 | <div class="sub_cat_content"> |
| 24 | <div class="content_items"> | 24 | <div class="content_items"> |
| 25 | <?php foreach($item['children'] as $_item) :?> | 25 | <?php foreach($item['children'] as $_item) :?> |
| 26 | - <div class="content_item"><a href="<?= \yii\helpers\Url::to(['/catalog/' .$_item['item']->alias])?>"> | 26 | + <div class="content_item"><a href="<?= \yii\helpers\Url::to(['/catalog/category', 'alias' => $_item['item']->alias])?>"> |
| 27 | <div valign="top" class="picture"><img valign="top" src="<?= $_item['item']->image?>"></div> | 27 | <div valign="top" class="picture"><img valign="top" src="<?= $_item['item']->image?>"></div> |
| 28 | <div class="title"><?= $_item['item']->name?></div> | 28 | <div class="title"><?= $_item['item']->name?></div> |
| 29 | </a></div> | 29 | </a></div> |
common/modules/relation/relationQueryTrait.php
| @@ -21,7 +21,13 @@ trait relationQueryTrait { | @@ -21,7 +21,13 @@ trait relationQueryTrait { | ||
| 21 | return self::$model; | 21 | return self::$model; |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | - public function getRelations($relationKey) { | 24 | + /*public function getRelations($relation) { |
| 25 | + $model = $this->getModel(); | ||
| 25 | 26 | ||
| 26 | - } | 27 | + $relation = $model->_getRelation($relation); |
| 28 | + return | ||
| 29 | + $model->owner | ||
| 30 | + ->hasMany($relation['outer']['model'], [$relation['outer']['key'] => $relation['outer']['linked_key']]) | ||
| 31 | + ->viaTable($relation['linked_table'], [$relation['inner']['linked_key'] => $relation['inner']['key']]); | ||
| 32 | + }*/ | ||
| 27 | } | 33 | } |
| 28 | \ No newline at end of file | 34 | \ No newline at end of file |
common/modules/rubrication/Module.php
| @@ -8,7 +8,7 @@ use Yii; | @@ -8,7 +8,7 @@ use Yii; | ||
| 8 | */ | 8 | */ |
| 9 | class Module extends \yii\base\Module | 9 | class Module extends \yii\base\Module |
| 10 | { | 10 | { |
| 11 | - public $types; | 11 | + public $types = []; |
| 12 | /** | 12 | /** |
| 13 | * @inheritdoc | 13 | * @inheritdoc |
| 14 | */ | 14 | */ |
| @@ -22,7 +22,5 @@ class Module extends \yii\base\Module | @@ -22,7 +22,5 @@ class Module extends \yii\base\Module | ||
| 22 | public function init() | 22 | public function init() |
| 23 | { | 23 | { |
| 24 | parent::init(); | 24 | parent::init(); |
| 25 | - | ||
| 26 | - // custom initialization code goes here | ||
| 27 | } | 25 | } |
| 28 | } | 26 | } |
common/modules/rubrication/models/TaxGroup.php
| @@ -35,6 +35,12 @@ class TaxGroup extends \yii\db\ActiveRecord | @@ -35,6 +35,12 @@ class TaxGroup extends \yii\db\ActiveRecord | ||
| 35 | // 'tax_option_to_group' => 'entity2', | 35 | // 'tax_option_to_group' => 'entity2', |
| 36 | ] | 36 | ] |
| 37 | ], | 37 | ], |
| 38 | + 'slug' => [ | ||
| 39 | + 'class' => 'common\behaviors\Slug', | ||
| 40 | + 'in_attribute' => 'name', | ||
| 41 | + 'out_attribute' => 'alias', | ||
| 42 | + 'translit' => true | ||
| 43 | + ], | ||
| 38 | ]; | 44 | ]; |
| 39 | } | 45 | } |
| 40 | 46 | ||
| @@ -52,7 +58,7 @@ class TaxGroup extends \yii\db\ActiveRecord | @@ -52,7 +58,7 @@ class TaxGroup extends \yii\db\ActiveRecord | ||
| 52 | public function rules() | 58 | public function rules() |
| 53 | { | 59 | { |
| 54 | return [ | 60 | return [ |
| 55 | - [['alias', 'name', 'module'], 'required'], | 61 | + [['name', 'module'], 'required'], |
| 56 | [['description', 'settings'], 'string'], | 62 | [['description', 'settings'], 'string'], |
| 57 | [['hierarchical'], 'boolean'], | 63 | [['hierarchical'], 'boolean'], |
| 58 | [['alias', 'module'], 'string', 'max' => 50], | 64 | [['alias', 'module'], 'string', 'max' => 50], |
common/modules/rubrication/models/TaxOption.php
| @@ -53,13 +53,6 @@ class TaxOption extends \yii\db\ActiveRecord | @@ -53,13 +53,6 @@ class TaxOption extends \yii\db\ActiveRecord | ||
| 53 | ]; | 53 | ]; |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | - public function events() { | ||
| 57 | - return $this->events(); | ||
| 58 | - return [ | ||
| 59 | -// ActiveRecord::EVENT_BEFORE_DELETE => 'beforeDelete', | ||
| 60 | - ]; | ||
| 61 | - } | ||
| 62 | - | ||
| 63 | /** | 56 | /** |
| 64 | * @inheritdoc | 57 | * @inheritdoc |
| 65 | */ | 58 | */ |
| @@ -226,6 +219,7 @@ class TaxOption extends \yii\db\ActiveRecord | @@ -226,6 +219,7 @@ class TaxOption extends \yii\db\ActiveRecord | ||
| 226 | 219 | ||
| 227 | private function getValueModelName() { | 220 | private function getValueModelName() { |
| 228 | $group = $this->getTaxGroup()->one(); | 221 | $group = $this->getTaxGroup()->one(); |
| 222 | +// var_dump($group);exit; | ||
| 229 | $valueClass = '\common\modules\rubrication\models\TaxValue'. ucfirst($group->module); | 223 | $valueClass = '\common\modules\rubrication\models\TaxValue'. ucfirst($group->module); |
| 230 | return class_exists($valueClass) ? $valueClass : FALSE; | 224 | return class_exists($valueClass) ? $valueClass : FALSE; |
| 231 | } | 225 | } |
console/migrations/m160323_234304_product_image.php
0 → 100644
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +use yii\db\Migration; | ||
| 4 | + | ||
| 5 | +class m160323_234304_product_image extends Migration | ||
| 6 | +{ | ||
| 7 | + public function up() | ||
| 8 | + { | ||
| 9 | + $tableOptions = null; | ||
| 10 | + if ($this->db->driverName === 'mysql') { | ||
| 11 | + // Only for MySQL | ||
| 12 | + $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; | ||
| 13 | + | ||
| 14 | + // @todo https://habrahabr.ru/post/138947/ | ||
| 15 | + } elseif ($this->db->driverName === 'pgsql') { | ||
| 16 | + // Only for PostgreSQL | ||
| 17 | + // @todo use intarray field for tax_options | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | + $this->createTable('{{%product_image}}', [ | ||
| 21 | + 'product_image_id' => $this->integer()->notNull(), | ||
| 22 | + 'product_id' => $this->integer()->notNull(), | ||
| 23 | + 'image' => $this->string(255), | ||
| 24 | + 'alt' => $this->string(255), | ||
| 25 | + 'title' => $this->string(255), | ||
| 26 | + ], $tableOptions); | ||
| 27 | + $this->addForeignKey('product_image_product_fkey', 'product_image', 'product_id', 'product', 'product_id', 'CASCADE', 'CASCADE'); | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + public function down() | ||
| 31 | + { | ||
| 32 | + $this->dropTable('{{%product_image}}'); | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + /* | ||
| 36 | + // Use safeUp/safeDown to run migration code within a transaction | ||
| 37 | + public function safeUp() | ||
| 38 | + { | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + public function safeDown() | ||
| 42 | + { | ||
| 43 | + } | ||
| 44 | + */ | ||
| 45 | +} |
frontend/controllers/CatalogController.php
| @@ -2,9 +2,17 @@ | @@ -2,9 +2,17 @@ | ||
| 2 | 2 | ||
| 3 | namespace frontend\controllers; | 3 | namespace frontend\controllers; |
| 4 | 4 | ||
| 5 | +use common\modules\product\models\Brand; | ||
| 5 | use common\modules\product\models\Category; | 6 | use common\modules\product\models\Category; |
| 6 | use common\modules\product\models\CategorySearch; | 7 | use common\modules\product\models\CategorySearch; |
| 7 | use common\modules\product\models\Product; | 8 | use common\modules\product\models\Product; |
| 9 | +use common\modules\product\models\ProductCategory; | ||
| 10 | +use common\modules\product\models\ProductSearch; | ||
| 11 | +use common\modules\product\models\ProductVariant; | ||
| 12 | +use yii\data\ActiveDataProvider; | ||
| 13 | +use yii\data\Pagination; | ||
| 14 | +use yii\data\Sort; | ||
| 15 | +use yii\db\ActiveQuery; | ||
| 8 | use yii\web\HttpException; | 16 | use yii\web\HttpException; |
| 9 | 17 | ||
| 10 | class CatalogController extends \yii\web\Controller | 18 | class CatalogController extends \yii\web\Controller |
| @@ -12,6 +20,9 @@ class CatalogController extends \yii\web\Controller | @@ -12,6 +20,9 @@ class CatalogController extends \yii\web\Controller | ||
| 12 | public function actionCategory($alias) | 20 | public function actionCategory($alias) |
| 13 | { | 21 | { |
| 14 | $category = CategorySearch::findByAlias($alias); | 22 | $category = CategorySearch::findByAlias($alias); |
| 23 | + if (empty($category->category_id)) { | ||
| 24 | + throw new HttpException(404 ,'Page not found'); | ||
| 25 | + } | ||
| 15 | if ($category->depth < 2) { | 26 | if ($category->depth < 2) { |
| 16 | return $this->render( | 27 | return $this->render( |
| 17 | 'categories', | 28 | 'categories', |
| @@ -20,11 +31,62 @@ class CatalogController extends \yii\web\Controller | @@ -20,11 +31,62 @@ class CatalogController extends \yii\web\Controller | ||
| 20 | ] | 31 | ] |
| 21 | ); | 32 | ); |
| 22 | } else { | 33 | } else { |
| 34 | +// $products = $category->getRelations('product_categories')->all(); | ||
| 35 | + | ||
| 36 | + $per_page = 24; | ||
| 37 | + | ||
| 38 | + $sort = new Sort([ | ||
| 39 | + 'attributes' => [ | ||
| 40 | + 'name' => [ | ||
| 41 | + 'asc' => ['name' => SORT_ASC], | ||
| 42 | + 'desc' => ['name' => SORT_DESC], | ||
| 43 | + 'default' => SORT_DESC, | ||
| 44 | + 'label' => 'имени', | ||
| 45 | + ], | ||
| 46 | + 'price' => [ | ||
| 47 | + 'asc' => [ProductVariant::tableName() .'.price' => SORT_ASC], | ||
| 48 | + 'desc' => [ProductVariant::tableName() .'.price' => SORT_DESC], | ||
| 49 | + 'default' => SORT_DESC, | ||
| 50 | + 'label' => 'цене', | ||
| 51 | + ], | ||
| 52 | + ], | ||
| 53 | + ]); | ||
| 54 | + /** @var ActiveQuery $query */ | ||
| 55 | + $query = $category->getRelations('product_categories') | ||
| 56 | + ->joinWith([ | ||
| 57 | + 'variants' | ||
| 58 | + ]); | ||
| 59 | + $pages = new Pagination(['totalCount' => $query->count(), 'pageSize' => $per_page]); | ||
| 60 | + $count = $query->count(); | ||
| 61 | + | ||
| 62 | +// $priceQuery = clone $query; | ||
| 63 | + $priceMin = $query->min(ProductVariant::tableName() .'.price'); | ||
| 64 | + $priceMax = $query->max(ProductVariant::tableName() .'.price'); | ||
| 65 | + | ||
| 66 | + $query->offset($pages->offset) | ||
| 67 | + ->orderBy($sort->orders) | ||
| 68 | + ->limit($pages->limit); | ||
| 69 | + $products = $query->all(); | ||
| 70 | + | ||
| 71 | + $brandsQuery = Brand::find()->innerJoinWith('products')->innerJoin(ProductCategory::tableName(), ProductCategory::tableName() .'.product_id='. Product::tableName() .'.product_id')->where([ | ||
| 72 | + ProductCategory::tableName() .'.category_id' => $category->category_id | ||
| 73 | + ])->groupBy(Brand::tableName() .'.brand_id'); | ||
| 74 | + $brands = $brandsQuery->all(); | ||
| 75 | + $brands_count = $brandsQuery->count(); | ||
| 23 | 76 | ||
| 24 | return $this->render( | 77 | return $this->render( |
| 25 | 'products', | 78 | 'products', |
| 26 | [ | 79 | [ |
| 27 | 'category' => $category, | 80 | 'category' => $category, |
| 81 | + 'products' => $products, | ||
| 82 | + 'product_count' => $count, | ||
| 83 | + 'sort' => $sort, | ||
| 84 | + 'pages' => $pages, | ||
| 85 | + 'per_page' => $per_page, | ||
| 86 | + 'priceMin' => $priceMin, | ||
| 87 | + 'priceMax' => $priceMax, | ||
| 88 | + 'brands' => $brands, | ||
| 89 | + 'brands_count' => $brands_count, | ||
| 28 | ] | 90 | ] |
| 29 | ); | 91 | ); |
| 30 | } | 92 | } |
| @@ -32,10 +94,9 @@ class CatalogController extends \yii\web\Controller | @@ -32,10 +94,9 @@ class CatalogController extends \yii\web\Controller | ||
| 32 | 94 | ||
| 33 | public function actionProduct($alias) | 95 | public function actionProduct($alias) |
| 34 | { | 96 | { |
| 35 | - $product = Product::find()->where('like', ['alias' => $alias]); | 97 | + $product = ProductSearch::findByAlias($alias); |
| 36 | if (empty($product->product_id)) { | 98 | if (empty($product->product_id)) { |
| 37 | -// throw new HttpException(404 ,'Page not found'); | ||
| 38 | -// return $this->redirect('/', 301); | 99 | + throw new HttpException(404 ,'Page not found'); |
| 39 | } | 100 | } |
| 40 | return $this->render('product'); | 101 | return $this->render('product'); |
| 41 | } | 102 | } |
| 1 | +<?php | ||
| 2 | +/** @var \common\modules\product\models\Product $product */ | ||
| 3 | +?> | ||
| 4 | +<div class="item" data-id="<?= $product->product_id?>"> | ||
| 5 | + <!--<div class="new">АКЦИЯ</div> | ||
| 6 | + <div class="top">Toп</div>--> | ||
| 7 | + <a href="#" class="item_link"><div class="pic"><img src="/images/items/01.jpg"></div> | ||
| 8 | + <div class="title_item"><?= $product->name?></div></a> | ||
| 9 | + <div class="brand">Бренд: <span><?= $product->brand->name?></span></div> | ||
| 10 | + <div class="type"><?= implode(', ', $product->categoriesNames)?></div> | ||
| 11 | + <div class="price"><?= $product->variant->price?> <span>грн.</span></div> | ||
| 12 | + <button class="basket_add_but" data-id="<?= $product->variant->product_variant_id?>">в корзину</button> | ||
| 13 | + <a href="#" class="compare_add_but" data-id="<?= $product->product_id?>"><span>добавить к сравнению</span></a> | ||
| 14 | + <img class="item_bottom_img" src="/images/nc_item_bottom.png" alt=""> | ||
| 15 | +</div> | ||
| 0 | \ No newline at end of file | 16 | \ No newline at end of file |
frontend/views/catalog/products.php
| @@ -6,40 +6,434 @@ $this->title = $category->name; | @@ -6,40 +6,434 @@ $this->title = $category->name; | ||
| 6 | foreach($category->getParents()->all() as $parent) { | 6 | foreach($category->getParents()->all() as $parent) { |
| 7 | $this->params['breadcrumbs'][] = ['label' => $parent->name, 'url' => ['catalog/category', 'alias' => $parent->alias]]; | 7 | $this->params['breadcrumbs'][] = ['label' => $parent->name, 'url' => ['catalog/category', 'alias' => $parent->alias]]; |
| 8 | } | 8 | } |
| 9 | -$this->params['breadcrumbs'][] = $this->title; | 9 | +$this->params['breadcrumbs'][] = $category->name; |
| 10 | ?> | 10 | ?> |
| 11 | -<h1 class="category_page_main_title"><?= $this->title ?></h1> | ||
| 12 | - | ||
| 13 | -<div class="category_wrap"> | ||
| 14 | - | ||
| 15 | - <div class="category_wrap_3_colum"><!-- 3 colons for items ================================== 1rst colum --> | ||
| 16 | - | ||
| 17 | - <?php foreach($category->getAllChildrenTree(2) as $category) :?> | ||
| 18 | - <div class="wrap"> | ||
| 19 | - <div class="cat_li_cont"> | ||
| 20 | - <?php if (!empty($category['item']->image)) :?> | ||
| 21 | - <img src="<?= $category['item']->image?>" alt="<?= $category['item']->name?>"> | ||
| 22 | - <?php else :?> | ||
| 23 | - <img src="/images/category/1.png" alt=""> | ||
| 24 | - <?php endif;?> | ||
| 25 | - <div class="desc"><?= $category['item']->name?><!-- (133)--></div> | ||
| 26 | - <?php if(!empty($category['children'])) :?> | ||
| 27 | - <span class="arrow"></span> | ||
| 28 | - <?php endif?> | ||
| 29 | - </div> | ||
| 30 | - <?php if(!empty($category['children'])) :?> | ||
| 31 | - <div class="cat_li_sub_ul"> | ||
| 32 | - <ul> | ||
| 33 | - <?php foreach($category['children'] as $_category) :?> | ||
| 34 | - <li><a href="<?= \yii\helpers\Url::to(['catalog/category', 'alias' => $_category['item']->alias])?>"><?= $_category['item']->name?><!-- (18)--></a></li> | ||
| 35 | - <?php endforeach?> | ||
| 36 | - </ul> | 11 | +<script type="text/javascript"> |
| 12 | + $(document).ready(function() { | ||
| 13 | + // price rangeslider (filter price slider) | ||
| 14 | + $("#price_interval").ionRangeSlider({ | ||
| 15 | + type: "double", | ||
| 16 | + min: <?= $priceMin?>, | ||
| 17 | + max: <?= $priceMax?>, | ||
| 18 | + from: <?= $priceMin?>, | ||
| 19 | + to: <?= $priceMax?>, | ||
| 20 | + grid: false | ||
| 21 | + }); | ||
| 22 | + }); | ||
| 23 | +</script> | ||
| 24 | +<div class="w_960"> | ||
| 25 | + <!-- side bar with all filters --> | ||
| 26 | + <div class="cat_p_filter_bar"> | ||
| 27 | + <div class="title">ФИЛЬТРЫ</div> | ||
| 28 | + <div class="filter_list"> | ||
| 29 | + <form action="#" name="filter_catalog_page_form"> | ||
| 30 | + <ul> | ||
| 31 | + <li>Цена: | ||
| 32 | + <div class="arrow"><img src="/images/head_up.png" alt=""></i></div> | ||
| 33 | + <div class="price_filter first_price_li"> | ||
| 34 | + <div class="price_slider"> | ||
| 35 | + <input type="text" id="price_interval" name="price_interval" value="" /> | ||
| 36 | + </div> | ||
| 37 | + <!--<div class="checkbox"> | ||
| 38 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 39 | + <a href="#">Акции</a> | ||
| 40 | + </div> | ||
| 41 | + <div class="checkbox"> | ||
| 42 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 43 | + <a href="#">Товар в наличии</a> | ||
| 44 | + </div> | ||
| 45 | + <div class="checkbox"> | ||
| 46 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 47 | + <a href="#">Хит продаж</a> | ||
| 48 | + </div>--> | ||
| 49 | + </div> | ||
| 50 | + </li> | ||
| 51 | + | ||
| 52 | + <?php if ($brands_count) :?> | ||
| 53 | + <li>Бренд | ||
| 54 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 55 | + <div class="price_filter"> | ||
| 56 | + <?php foreach($brands as $brand) :?> | ||
| 57 | + <div class="checkbox"> | ||
| 58 | + <label><input type="checkbox" name="think" value="ruuki" /></label> | ||
| 59 | + <a href="<?= \yii\helpers\Url::to(['catalog/brand', 'alias' => $brand->alias])?>"><?= $brand->name?> (<?= $brand->getProducts()->count()?>)</a> | ||
| 60 | + </div> | ||
| 61 | + <?php endforeach?> | ||
| 62 | + <!--<div class="checkbox see_all"> | ||
| 63 | + <i class="fa fa-plus-circle"></i> | ||
| 64 | + <a href="#">посмотреть все</a> | ||
| 65 | + </div>--> | ||
| 66 | + </div> | ||
| 67 | + </li> | ||
| 68 | + <?php endif?> | ||
| 69 | + | ||
| 70 | + <div class="title_2">ПОДБОР ПО ПАРАМЕТРАМ</div> | ||
| 71 | + | ||
| 72 | + <li>Толщина металла, мм | ||
| 73 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 74 | + <div class="price_filter"> | ||
| 75 | + <div class="checkbox"> | ||
| 76 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 77 | + <a href="#">0,4</a> | ||
| 78 | + </div> | ||
| 79 | + <div class="checkbox"> | ||
| 80 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 81 | + <a href="#">0,45</a> | ||
| 82 | + </div> | ||
| 83 | + <div class="checkbox"> | ||
| 84 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 85 | + <a href="#">0,5</a> | ||
| 86 | + </div> | ||
| 87 | + </div> | ||
| 88 | + </li> | ||
| 89 | + | ||
| 90 | + <li>Покрытие | ||
| 91 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 92 | + <div class="price_filter"> | ||
| 93 | + <div class="checkbox"> | ||
| 94 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 95 | + <a href="#">RUUKI(3)</a> | ||
| 96 | + </div> | ||
| 97 | + <div class="checkbox"> | ||
| 98 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 99 | + <a href="#">Venecia(10)</a> | ||
| 100 | + </div> | ||
| 101 | + </div> | ||
| 102 | + </li> | ||
| 103 | + | ||
| 104 | + <li>Металл | ||
| 105 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 106 | + <div class="price_filter"> | ||
| 107 | + <div class="checkbox"> | ||
| 108 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 109 | + <a href="#">RUUKI(3)</a> | ||
| 110 | + </div> | ||
| 111 | + <div class="checkbox"> | ||
| 112 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 113 | + <a href="#">Venecia(10)</a> | ||
| 114 | + </div> | ||
| 115 | + </div> | ||
| 116 | + </li> | ||
| 117 | + | ||
| 118 | + <li>Производитель | ||
| 119 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 120 | + <div class="price_filter"> | ||
| 121 | + <div class="checkbox"> | ||
| 122 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 123 | + <a href="#">RUUKI(3)</a> | ||
| 124 | + </div> | ||
| 125 | + <div class="checkbox"> | ||
| 126 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 127 | + <a href="#">Venecia(10)</a> | ||
| 128 | + </div> | ||
| 129 | + </div> | ||
| 130 | + </li> | ||
| 131 | + | ||
| 132 | + <li>Профиль | ||
| 133 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 134 | + <div class="price_filter"> | ||
| 135 | + <div class="checkbox"> | ||
| 136 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 137 | + <a href="#">RUUKI(3)</a> | ||
| 138 | + </div> | ||
| 139 | + <div class="checkbox"> | ||
| 140 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 141 | + <a href="#">Venecia(10)</a> | ||
| 142 | + </div> | ||
| 143 | + </div> | ||
| 144 | + </li> | ||
| 145 | + | ||
| 146 | + <li>Вес 1 м2 на кг | ||
| 147 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 148 | + <div class="price_filter"> | ||
| 149 | + <div class="checkbox"> | ||
| 150 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 151 | + <a href="#">RUUKI(3)</a> | ||
| 152 | + </div> | ||
| 153 | + <div class="checkbox"> | ||
| 154 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 155 | + <a href="#">Venecia(10)</a> | ||
| 156 | + </div> | ||
| 157 | + </div> | ||
| 158 | + </li> | ||
| 159 | + | ||
| 160 | + <li><span class="width_li_filter">Общая высота профиля, мм</span> | ||
| 161 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 162 | + <div class="price_filter"> | ||
| 163 | + <div class="checkbox"> | ||
| 164 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 165 | + <a href="#">RUUKI(3)</a> | ||
| 166 | + </div> | ||
| 167 | + <div class="checkbox"> | ||
| 168 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 169 | + <a href="#">Venecia(10)</a> | ||
| 170 | + </div> | ||
| 171 | + </div> | ||
| 172 | + </li> | ||
| 173 | + | ||
| 174 | + <li><span>Общая ширина, мм</span> | ||
| 175 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 176 | + <div class="price_filter"> | ||
| 177 | + <div class="checkbox"> | ||
| 178 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 179 | + <a href="#">RUUKI(3)</a> | ||
| 180 | + </div> | ||
| 181 | + <div class="checkbox"> | ||
| 182 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 183 | + <a href="#">Venecia(10)</a> | ||
| 184 | + </div> | ||
| 185 | + </div> | ||
| 186 | + </li> | ||
| 187 | + | ||
| 188 | + <li>Шаг волны, мм | ||
| 189 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 190 | + <div class="price_filter"> | ||
| 191 | + <div class="checkbox"> | ||
| 192 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 193 | + <a href="#">RUUKI(3)</a> | ||
| 194 | + </div> | ||
| 195 | + <div class="checkbox"> | ||
| 196 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 197 | + <a href="#">Venecia(10)</a> | ||
| 198 | + </div> | ||
| 199 | + </div> | ||
| 200 | + </li> | ||
| 201 | + | ||
| 202 | + <li>Полезная ширина, мм | ||
| 203 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 204 | + <div class="price_filter"> | ||
| 205 | + <div class="checkbox"> | ||
| 206 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 207 | + <a href="#">RUUKI(3)</a> | ||
| 208 | + </div> | ||
| 209 | + <div class="checkbox"> | ||
| 210 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 211 | + <a href="#">Venecia(10)</a> | ||
| 212 | + </div> | ||
| 213 | + </div> | ||
| 214 | + </li> | ||
| 215 | + | ||
| 216 | + <li><span class="width_li_filter">Количества цинка, г/м2</span> | ||
| 217 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 218 | + <div class="price_filter"> | ||
| 219 | + <div class="checkbox"> | ||
| 220 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 221 | + <a href="#">RUUKI(3)</a> | ||
| 222 | + </div> | ||
| 223 | + <div class="checkbox"> | ||
| 224 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 225 | + <a href="#">Venecia(10)</a> | ||
| 226 | + </div> | ||
| 227 | + </div> | ||
| 228 | + </li> | ||
| 229 | + | ||
| 230 | + <li>Гарантия | ||
| 231 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 232 | + <div class="price_filter"> | ||
| 233 | + <div class="checkbox"> | ||
| 234 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 235 | + <a href="#">RUUKI(3)</a> | ||
| 236 | + </div> | ||
| 237 | + <div class="checkbox"> | ||
| 238 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
| 239 | + <a href="#">Venecia(10)</a> | ||
| 240 | + </div> | ||
| 241 | + </div> | ||
| 242 | + </li> | ||
| 243 | + | ||
| 244 | + </ul> | ||
| 245 | + | ||
| 246 | + <div class="filter_accept_bloc"> | ||
| 247 | + <button type="submit" class="filter_accept_btn">применить</button> | ||
| 248 | + <a href="#" class="form_checkbox_reset">сбросить фильтры</a> | ||
| 37 | </div> | 249 | </div> |
| 250 | + </form> | ||
| 251 | + <!--<div class="product_list"> | ||
| 252 | + <h2 class="title">КАТАЛОГ ТОВАРОВ</h2> | ||
| 253 | + <ul> | ||
| 254 | + <li>Битумная черепица | ||
| 255 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 256 | + <div class="price_filter"> | ||
| 257 | + <a href="#">RUUKI</a> | ||
| 258 | + <a href="#">Venecia</a> | ||
| 259 | + </div> | ||
| 260 | + </li> | ||
| 261 | + | ||
| 262 | + <li>Комплектация кровли | ||
| 263 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 264 | + <div class="price_filter"> | ||
| 265 | + <a href="#">RUUKI</a> | ||
| 266 | + <a href="#">Venecia</a> | ||
| 267 | + </div> | ||
| 268 | + </li> | ||
| 269 | + | ||
| 270 | + <li>Водосточные системы | ||
| 271 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 272 | + <div class="price_filter"> | ||
| 273 | + <a href="#">RUUKI</a> | ||
| 274 | + <a href="#">Venecia</a> | ||
| 275 | + </div> | ||
| 276 | + </li> | ||
| 277 | + | ||
| 278 | + <li>Чердачные лестницы | ||
| 279 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 280 | + <div class="price_filter"> | ||
| 281 | + <a href="#">RUUKI</a> | ||
| 282 | + <a href="#">Venecia</a> | ||
| 283 | + </div> | ||
| 284 | + </li> | ||
| 285 | + | ||
| 286 | + <li>Мансардные окна | ||
| 287 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 288 | + <div class="price_filter"> | ||
| 289 | + <a href="#">RUUKI</a> | ||
| 290 | + <a href="#">Venecia</a> | ||
| 291 | + </div> | ||
| 292 | + </li> | ||
| 293 | + | ||
| 294 | + <li>Металлочерепица | ||
| 295 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 296 | + <div class="price_filter"> | ||
| 297 | + <a href="#">RUUKI</a> | ||
| 298 | + <a href="#">Venecia</a> | ||
| 299 | + </div> | ||
| 300 | + </li> | ||
| 301 | + | ||
| 302 | + <li>Плоская кровля | ||
| 303 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 304 | + <div class="price_filter"> | ||
| 305 | + <a href="#">RUUKI</a> | ||
| 306 | + <a href="#">Venecia</a> | ||
| 307 | + </div> | ||
| 308 | + </li> | ||
| 309 | + | ||
| 310 | + <li>Профнастил | ||
| 311 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 312 | + <div class="price_filter"> | ||
| 313 | + <a href="#">RUUKI</a> | ||
| 314 | + <a href="#">Venecia</a> | ||
| 315 | + </div> | ||
| 316 | + </li> | ||
| 317 | + | ||
| 318 | + <li>Ондулин | ||
| 319 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 320 | + <div class="price_filter"> | ||
| 321 | + <a href="#">RUUKI</a> | ||
| 322 | + <a href="#">Venecia</a> | ||
| 323 | + </div> | ||
| 324 | + </li> | ||
| 325 | + | ||
| 326 | + <li>OSB плиты | ||
| 327 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
| 328 | + <div class="price_filter"> | ||
| 329 | + <a href="#">RUUKI</a> | ||
| 330 | + <a href="#">Venecia</a> | ||
| 331 | + </div> | ||
| 332 | + </li> | ||
| 333 | + | ||
| 334 | + </ul> | ||
| 335 | + </div>--> | ||
| 336 | + </div> | ||
| 337 | + | ||
| 338 | + | ||
| 339 | + </div> | ||
| 340 | + | ||
| 341 | + <!-- catalog list with all item cards --> | ||
| 342 | + <div class="cat_p_catalog_list"> | ||
| 343 | + <div class="title"><?= $category->name?> <span>(<?= $product_count?>)</span></div> | ||
| 344 | + | ||
| 345 | + <!-- sort menu --> | ||
| 346 | + <div class="sort_menu"> | ||
| 347 | + | ||
| 348 | + <div class="sort_price"> | ||
| 349 | + <span>Сортировка:</span> | ||
| 350 | + <?= \yii\widgets\LinkSorter::widget([ | ||
| 351 | + 'sort' => $sort, | ||
| 352 | + 'attributes' => [ | ||
| 353 | + 'name', | ||
| 354 | + 'price', | ||
| 355 | + ] | ||
| 356 | + ]); | ||
| 357 | + ?> | ||
| 358 | + <!-- | ||
| 359 | + <select name="sort_price" id="" class="sort_price_select"> | ||
| 360 | + <option value="price">по цене</option> | ||
| 361 | + <option value="popular">новые</option> | ||
| 362 | + <option value="sale">по акции</option> | ||
| 363 | + </select> | ||
| 364 | + <i class="fa fa-angle-down"></i>--> | ||
| 365 | + </div> | ||
| 366 | + | ||
| 367 | + <div class="show"> | ||
| 368 | + <!--<span>Показывать по:</span> | ||
| 369 | + <ul> | ||
| 370 | + <li><a class="active" href="#">24</a></li> | ||
| 371 | + <li><a href="#">48</a></li> | ||
| 372 | + <li><a href="#">96</a></li> | ||
| 373 | + </ul>--> | ||
| 374 | + </div> | ||
| 375 | + | ||
| 376 | + <div class="show_pages"> | ||
| 377 | + <?php if ($pages->totalCount > $pages->pageSize) :?> | ||
| 378 | + <span>Страница:</span> | ||
| 379 | + <?= \yii\widgets\LinkPager::widget([ | ||
| 380 | + 'pagination' => $pages, | ||
| 381 | + 'options' => ['class' => 'pagination pull-right'], | ||
| 382 | + ]); | ||
| 383 | + ?> | ||
| 384 | + <!--<i class="fa fa-caret-right"></i>--> | ||
| 38 | <?php endif?> | 385 | <?php endif?> |
| 39 | </div> | 386 | </div> |
| 40 | - <!-- $this->params['breadcrumbs'][] = ['label' => $parent->name, 'url' => ['catalog/category', 'alias' => $parent->alias]];--> | ||
| 41 | - <?php endforeach?> | ||
| 42 | 387 | ||
| 43 | - </div><!-- end of 3 colons for items --> | 388 | + </div> |
| 389 | + | ||
| 390 | + | ||
| 391 | + <div class="cat_p_item_card_list"> | ||
| 392 | + <div class="novelty"> | ||
| 393 | + <div class="content"> | ||
| 394 | + <div class="novelty_cont"> | ||
| 395 | + <?php foreach($products as $product) :?> | ||
| 396 | + <?php require(__DIR__ .'/product_item.php')?> | ||
| 397 | + <?php endforeach?> | ||
| 398 | + </div> | ||
| 399 | + | ||
| 400 | + <?php if ($pages->totalCount > $pages->pageSize) :?> | ||
| 401 | + <!-- LOAD MORE BUTTON --> | ||
| 402 | + <button class="load_more_btn">Загрузить еще <?= $per_page?> товара</button> | ||
| 403 | + | ||
| 404 | + <div class="show_pages"> | ||
| 405 | + Страница: | ||
| 406 | + <?= \yii\widgets\LinkPager::widget([ | ||
| 407 | + 'pagination' => $pages, | ||
| 408 | + 'options' => ['class' => 'pagination pull-right'], | ||
| 409 | + ]); | ||
| 410 | + ?> | ||
| 411 | + <!--<i class="fa fa-caret-right"></i>--> | ||
| 412 | + </div> | ||
| 413 | + <?php endif?> | ||
| 414 | + <hr> | ||
| 415 | + | ||
| 416 | + <div class="description"> | ||
| 417 | + <h2>Преимущества металлочерепицы:</h2> | ||
| 418 | + <p> | ||
| 419 | + На рынке стройматериалов представлено множество кровельных покрытий, от привычного всем рубероида до современной гибкой черепицы на основе стекловолоконных композитов. Все они имеют свои преимущества и сферы применения. Но металлочерепица на протяжении многих лет удерживает лидерские позиции по уровню продаж, и этzо объясняется несколькими причинами: | ||
| 420 | + </p> | ||
| 421 | + <h4>Кровля из металлочерепицы</h4> | ||
| 422 | + <p class="margin_bottom_20"> | ||
| 423 | + <span class="bold">1. Малый вес.</span> Эта характеристика дает ощутимую финансовую выгоду. Вам не придется усиливать стропильные конструкции, значит, удастся сэкономить на пиломатериалах. Легкость металлочерепицы для кровли упрощает транспортировку и монтаж, позволяет отказаться от дорогостоящих услуг подъемной и грузовой спецтехники. | ||
| 424 | + </p> | ||
| 425 | + <p class="margin_bottom_20"> | ||
| 426 | + <span class="bold">2. Прочность.</span> В отличие от рулонных и гибких материалов, металлочерепица устойчива к механическим повреждениям. Ее крайне сложно поцарапать и практически невозможно сломать. Высокие технические характеристики говорят и о хорошей несущей способности материала. | ||
| 427 | + </p> | ||
| 428 | + <p class="margin_bottom_20"> | ||
| 429 | + <span class="bold">3. Эстетичность.</span> Металлочерепица придает крыше законченный, аккуратный вид. Дом выглядит просто роскошно. Подбирая оригинальные цветовые сочетания, дизайнерам удается с помощью | ||
| 430 | + </p> | ||
| 431 | + | ||
| 432 | + <div class="empty_padding_400"></div> | ||
| 433 | + </div> | ||
| 434 | + </div> | ||
| 435 | + </div> | ||
| 436 | + </div> | ||
| 437 | + </div> | ||
| 438 | +</div> | ||
| 44 | 439 | ||
| 45 | -</div> | ||
| 46 | \ No newline at end of file | 440 | \ No newline at end of file |
frontend/views/вертска/js/my_scripts.js
| @@ -2,16 +2,6 @@ $(document).ready(function(){ | @@ -2,16 +2,6 @@ $(document).ready(function(){ | ||
| 2 | // ion tabs | 2 | // ion tabs |
| 3 | $.ionTabs("#tabs_1"); | 3 | $.ionTabs("#tabs_1"); |
| 4 | 4 | ||
| 5 | - // price rangeslider (filter price slider) | ||
| 6 | - $("#example_id").ionRangeSlider({ | ||
| 7 | - type: "double", | ||
| 8 | - min: 0, | ||
| 9 | - max: 500, | ||
| 10 | - from: 50, | ||
| 11 | - to: 450, | ||
| 12 | - grid: false | ||
| 13 | - }); | ||
| 14 | - | ||
| 15 | // ion checkradio init | 5 | // ion checkradio init |
| 16 | $("input[type='radio'], input[type='checkbox']").ionCheckRadio(); | 6 | $("input[type='radio'], input[type='checkbox']").ionCheckRadio(); |
| 17 | 7 |
frontend/web/css/style.css
| @@ -501,6 +501,11 @@ button:focus {outline: none;} | @@ -501,6 +501,11 @@ button:focus {outline: none;} | ||
| 501 | padding-bottom:60px; | 501 | padding-bottom:60px; |
| 502 | color:#333333; | 502 | color:#333333; |
| 503 | } | 503 | } |
| 504 | +.novelty_cont:after { | ||
| 505 | + display: block; | ||
| 506 | + content: ''; | ||
| 507 | + clear: both; | ||
| 508 | +} | ||
| 504 | .novelty_cont .item{ | 509 | .novelty_cont .item{ |
| 505 | border:1px solid #cdd1d9; | 510 | border:1px solid #cdd1d9; |
| 506 | border-bottom:none; | 511 | border-bottom:none; |