Reputation: 1849
So I've searched the internet for similar cases, and I just got lost from all contradicting answers, and unrelated scenarios. So I thought to put my case hoping to get some specific answers.
I am new to Laravel, and creating small application. In the application I have to search for offeres and show the result in a blade view. Since the query is complex, and output of the search does not belong to a specific Model, I just wish to keep it as a raw query.
I have placed the query in the controller, but I just don't feel it's the right place. Especially if I need to reuse the query in many places.
Here's the method from the OfferController:
public function search(Request $request)
{
$area = $request->area;
$size = $request->size;
$sql = "SELECT distinct product_name,product_offer.quantity, product_offer.price
FROM product
inner join brand on product.brand_id = brand.brand_id
inner join brand_area on brand_area.brand_id = brand.brand_id
inner join area on area.area_id = brand_area.area_id
inner join product_offer on product_offer.product_id = product.product_id
where area.area_id = :area
and product.size_id = :size ";
$params = array(
'area'=>$area,
'size'=>$size
);
$offers = DB::select( DB::raw($sql), $params);
return view('searchresult')->with($offers);
}
So in short: should I move the query to the model, create DAL class, or keep it here? Baring in mind the project is small scale.
Upvotes: 2
Views: 2280
Reputation: 350
I'm writing my previous comment as an answer since I think its really what you are looking for:
I suggest you use a Trait to do this. The reason why is that it will keep your code clean and you'll be able to reuse this code later for other uses. A Trait is made for reusable code.
You will create a Trait:
<?php
namespace App\Traits; // Optional, but you could create a namespace for all your Traits if you need others
trait MyCustomTrait
{
public function perform(array $params) {
$sql = "SELECT distinct product_name,product_offer.quantity, product_offer.price
FROM product
inner join brand on product.brand_id = brand.brand_id
inner join brand_area on brand_area.brand_id = brand.brand_id
inner join area on area.area_id = brand_area.area_id
inner join product_offer on product_offer.product_id = product.product_id
where area.area_id = :area
and product.size_id = :size ";
return DB::select( DB::raw($sql), $params);
}
}
To use it, only write: use MyCustomTrait
in the scope of your controller and call your function like this: $this->perform([...])
.
Here's some links to learn more about traits:
Hope it helps you!
Upvotes: 1
Reputation: 12939
in my opinion, if you are going to reuse it, create a service that will perform that query and gives you back a result, something like SearchService
that looks like this:
<?php
class SearchService
{
public static function perform(array $params){
$sql = "SELECT distinct product_name,product_offer.quantity, product_offer.price
FROM product
inner join brand on product.brand_id = brand.brand_id
inner join brand_area on brand_area.brand_id = brand.brand_id
inner join area on area.area_id = brand_area.area_id
inner join product_offer on product_offer.product_id = product.product_id
where area.area_id = :area
and product.size_id = :size ";
return DB::select( DB::raw($sql), $params);
}
}
?>
And by doing so, you can just call
SearchService::perform([...]);
to get the results.
Obviously this is version1.0, you can improve it in a lot of ways, for example making it not static in order to make it testable, and also to allow getter and setter to exists, and a lot of other things, that might be usefull
Upvotes: 1
Reputation: 837
You have a fair point saying it does not look right to place query in the controller. I would offer you to have a look at the concept of Laravel repository pattern:
https://dev.to/asperbrothers/laravel-repository-pattern-how-to-use-why-it-matters-1g9d
Also, I think you could use Laravel DB
for this kind of query without the need to write it as a raw query. I do not think there is a huge need to have a raw query here. Laravel DB
table()
, select()
, where()
and other methods should be enough.
Actually, you could potentially write this using models and their relationships, but if the query is quite slow, it is better to use query builder for better efficiency.
EDIT:
also for some specific queries which do not belong to anything I remember seeing custom trait used, could also be a solution.
Upvotes: 1