Home » Php » php – Convert SQL query to Laravel equivalent

php – Convert SQL query to Laravel equivalent

Posted by: admin February 25, 2020 Leave a comment

Questions:

I’m a beginner in Laravel and php.
I have MySQL tables:

CREATE TABLE `dishes` (
  `id` bigint(20) UNSIGNED NOT NULL,
  `company_id` bigint(20) UNSIGNED NOT NULL,
  `name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `description` longtext COLLATE utf8mb4_unicode_ci,
  `enable` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '1',
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;


CREATE TABLE `dish_values` (
  `id` bigint(20) UNSIGNED NOT NULL,
  `dishes_id` bigint(20) UNSIGNED NOT NULL,
  `food_ingredient_id` bigint(20) UNSIGNED NOT NULL,
  `company_id` bigint(20) UNSIGNED NOT NULL,
  `quantity` decimal(9,2) NOT NULL DEFAULT '0.00'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;


CREATE TABLE `food_ingredients` (
  `id` bigint(20) UNSIGNED NOT NULL,
  `company_id` bigint(20) UNSIGNED NOT NULL,
  `name` varchar(120) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `garbage` decimal(9,2) NOT NULL DEFAULT '0.00',
  `energy_value` decimal(9,2) NOT NULL DEFAULT '0.00',
  `protein` decimal(9,2) NOT NULL DEFAULT '0.00',
  `fat` decimal(9,2) NOT NULL DEFAULT '0.00',
  `available_carbohydrates` decimal(9,2) NOT NULL DEFAULT '0.00',
  `roughage` decimal(9,2) NOT NULL DEFAULT '0.00',
  `description` longtext COLLATE utf8mb4_unicode_ci,
  `url_address` varchar(160) COLLATE utf8mb4_unicode_ci NOT NULL,
  `allergen` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
  `allergen1` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
  `allergen2` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
  `allergen3` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
  `available_in_demo` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
  `enable` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '1'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

and query mysql:

select d.id, d.company_id, d.name, d.description, d.enable, d.allergen
from dishes d  
where not exists (
    select 1
    from dish_values v 
    inner join food_ingredients i on i.id = v.food_ingredient_id
    where 
        v.dishes_id = d.id 
        and i.allergen1 = '1'
)  and d.company_id = 1 and d.enable = 1

These queries work fine, I want convert them to Laravel equivalent.

What i wrote:

Dish::whereHas('foodIngredient', function($q) use($query, $companyId)
            {
                $q->whereHas('dish_values', function($q) use($query, $companyId){
//                        $q->where([['allergen1', 1], ['dishes.company_id', 1]])
//                            ->orWhere([['allergen1', 1], ['dishes.company_id', $companyId]]);
                    });
            })->where([
                ['dishes.name', 'LIKE', '%' . $query . '%'],
                ['dishes.enable', '=', 1],
//                ['food_ingredients.allergen1', '=', 1],
            ])->paginate(8)

But it’s not working.
My Model:

class Dish extends Model
{
    protected $quarded = ['id'];
    protected $fillable = ['company_id', 'name', 'description',  'enable', 'allergen'];
    public $timestamps = false;

    public function components()
    {
        return $this->hasManyThrough('App\DishValues', 'App\Dish', 'id', 'dishes_id');
    }

    public function foodIngredient()
    {
        return $this->hasManyThrough('App\FoodIngredient', 'App\DishValues', 'dishes_id', 'id');
    }

    public function foodIngredient2()
    {
        return $this->hasManyThrough('App\FoodIngredient', 'App\DishValues', 'id', 'food_ingredient_id');
    }

}

but this is not working

How can I make it? I’m trying many options, but I don’t know how convert my query to Laravel equivalent

How to&Answers:

I believe whereDoesntHave is the right query in this scenario, not whereHas.

I rename your relationship to foodIngredients, instead of foodIngredient. Because this is a many to many relationship.

So you can rewrite your query to something like:

Dish::whereDoesntHave('foodIngredients', function ($query) {
    $query->where('allergen1', 1);
})
->where('company_id', 1)
->where('enable', 1)
->get();