Пользователь может выбрать до 5ти ингредиентов для приготовления блюда, при
этом:
1. Если найдены блюда с полным совпадением ингредиентов вывести
только их.
2. Если найдены блюда с частичным совпадением ингредиентов вывести
в порядке уменьшения совпадения ингредиентов вплоть до 2х.
3. Если найдены блюда с совпадением менее чем 2 ингредиента или не
найдены вовсе вывести “Ничего не найдено”.
4. Если выбрано менее 2х ингредиентов не производить поиск, выдать
сообщение: “Выберите больше ингредиентов”.
class m170818_200201_ingredient_table extends Migration
{
public function safeUp()
{
$tableOptions = null;
if($this->db->driverName == 'mysql'){
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB';
}
$this->createTable('{{%ingredients}}',[
'id' => $this->primaryKey(),
'name' => $this->string()->notNull(),
'created_at' => $this->integer()->notNull(),
'updated_at' => $this->integer()->notNull(),
'status' => $this->smallInteger()->notNull()->defaultValue(0)
], $tableOptions);
$this->createIndex('idx-ingred-id', '{{%ingredients}}', 'id');
$this->createIndex('idx-ingred-name', '{{%ingredients}}', 'name');
$this->createIndex('idx-ingred-status', '{{%ingredients}}', 'status');
}
public function safeDown()
{
$this->dropTable('{{%ingredients}}');
}
}
class m170818_200136_recipes_table extends Migration
{
public function safeUp()
{
$tableOptions = null;
if($this->db->driverName == 'mysql'){
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB';
}
$this->createTable('{{%recipes}}',[
'id' => $this->primaryKey(),
'name' => $this->string(100),
'created_at' => $this->integer()->notNull(),
'updated_at' => $this->integer()->notNull(),
'status' => $this->smallInteger()->notNull()->defaultValue(0)
], $tableOptions);
$this->createIndex('idx-recipe-id', '{{%recipes}}', 'id');
$this->createIndex('idx-recipe-name', '{{%recipes}}', 'name');
$this->createIndex('idx-recipe-status', '{{%recipes}}', 'status');
}
public function safeDown()
{
$this->dropTable('{{%recipes}}');
}
}
class m170819_172758_recipes_ingredients_table extends Migration
{
public function safeUp()
{
$this->createTable('{{%recipes_ingredients}}', [
'recipe_id' => $this->integer()->notNull(),
'ingredient_id' => $this->integer()->notNull()
]);
$this->addPrimaryKey('pk-recipes-ingredients', '{{%recipes_ingredients}}', ['recipe_id', 'ingredient_id']);
$this->createIndex('idx-recipe', '{{%recipes_ingredients}}', 'recipe_id');
$this->createIndex('idx-inged', '{{%recipes_ingredients}}', 'ingredient_id');
$this->addForeignKey('fk-recipe_id', '{{%recipes_ingredients}}', 'recipe_id', '{{%recipes}}', 'id', 'CASCADE', 'RESTRICT');
$this->addForeignKey('fk-ingred_id', '{{%recipes_ingredients}}', 'ingredient_id', '{{%ingredients}}', 'id', 'CASCADE', 'RESTRICT');
}
public function safeDown()
{
$this->dropTable('{{%recipes_ingredients}}');
}
}
<?php
namespace app\modules\recipes\models\search;
use app\modules\recipes\models\Ingredients;
use app\modules\recipes\models\RecipesIngredients;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use app\modules\recipes\models\Recipe;
class RecipesIngredientsSearch extends RecipesIngredients
{
private $_id = [];
/**
* @inheritdoc
*/
public function rules()
{
return [
[['recipe_id', 'ingredient_id'], 'integer'],
];
}
/**
* @inheritdoc
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* @param array $params
*
* @return ActiveDataProvider
*/
public function search($params)
{
foreach($params['Ingredients'] as $key => $value){
if(!empty($value['name'])){
$this->_id[] = $value['name'];
}
}
$query = RecipesIngredients::find();
$query->joinWith(['ingredient', 'recipe'])->where(['ingredients.status' => Ingredients::STATUS_ACTIVE, 'recipes.status' => Recipe::STATUS_ACTIVE]);
$query->andWhere(['in', 'recipes_ingredients.ingredient_id', $this->_id]);
$query->orderBy(['recipes.name' => SORT_ASC]);
$query->addOrderBy(['recipes.id' => SORT_DESC]);
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
return $dataProvider;
}
}
public function getIngred()
{
return $this->hasMany(Ingredients::className(), ['id' => 'ingredient_id'])->viaTable('{{%recipes_ingredients}}', ['recipe_id' => 'id']);
}
public function getRecipe()
{
return $this->hasMany(Recipe::className(), ['id' => 'recipe_id'])->viaTable('{{%recipes_ingredients}}', ['ingredient_id' => 'id']);
}
public function getRecipe()
{
return $this->hasOne(Recipe::className(), ['id' => 'recipe_id']);
}
public function getIngredient()
{
return $this->hasOne(Ingredients::className(), ['id' => 'ingredient_id']);
}
SELECT r.id, COUNT(ri.recipe_id) AS count_ingredients
FROM recipes AS r
LEFT JOIN recipes_ingredients AS ri ON r.id = ri.recipe_id
GROUP BY r.id