i have two different tables like these:
Table:products
id->1
name->pencil
siz->big
Table:colours
id->2
colour_name->red
product_id->1
Here is my codes in controller;
$products= Product::where('active', 1);
if ($request->has('size')) {
$products->whereIn('size', $request->input('size'));
}
$products= $products->paginate(10);
return view('pencil.index', compact("products"));
The results are filtered by request's size values. But the problem colours in different table, how can i do the correct query for colour filters ? Thank you.
You can do it nicely using Eloquent. So in your Product model class add this method:
public function colours()
{
return $this->hasMany(Colour::class);
}
and in your Colour model:
public function product()
{
return $this->belongsTo(Product::class);
}
Then in your controller or wherever you have the business logic you can do it like so:
Product::where('id', $productId)->colours; // this gives you list of all the colours for that product.
Getting list of colours based on the colour name:
$colours = Colour::where(
'colour_name', request('colour')
)->get();
then simply when iterating over the $colours you can use:
foreach($colours as $colour)
{
// $colour->product; is what you are looking for.
}
--- EDIT
Product::with('colours', function($query) use ($colour) {
$query->where('colour_name', $colour);
});
Related
I'm trying to get only the category names, of all articles on the index() function on Laravel. So all articles and the related categories of each article. It's a many-to-many relationship.
What i did so far:
foreach($articles as $article) {
if (isset($article)) {
$article['categories'] = $article->category;
}
}
This gets me all articles with the related categories as a collection, it works, but not quite what I want. As I said, I want only the category names.
I tried $article->category->name; obviously did not work
also: $article->category->get('name');
furthermore what is interesting, If I rename $article['categories'] to $article['cat'] I get 2 collections the category with all related category objects and another exact same on just names cat.
I also tried:
...
$article['categories'] = $this->getcat($articles);
return response()->json($articles, 200);
}
public function getcat($query) {
if (isset($query) && is_countable($query)) {
foreach ($query as &$entity) {
if (!isset($entity)) { continue; }
if (isset($entity->categories)) {
$originObjects = $entity->categories;
$competition_all = [];
foreach($originObjects as $object) {
array_push($competition_all, $object->name);
}
return $competition_all;
}
}
}
The function returns what I need, but it does not return it as json, on the frontend.
From what i see.. your response is return response()->json($names, 200); , but your categories names array is saved into the $article['categories'] array. So.. if you return the response()->json($article, 200);, your categories names should be returned as json. The reason that $article->category->name; does not works is because this is array with objects because the type of your relation, but here you call only property.
The better way is to add to the query, the with function and pass the relation as first parameter, and then in second to add anonym function with the query and select only the names.
Eg.
$articles = Article::with('category', function($q) { ... })->get();
I have 2 models: car painted color, and cars
public function color()
{
return $this->hasOne(Colors::class)->latest();
}
I need to search the latest painted car color but with whereHas, it's searching all colors
$colors = ['black', 'white'];
$cars->whereHas('color', function($cars) use ($colors) {
return $cars->whereIn('paint_color', $colors);
});
How can I make whereIn to only query on the latest row?
First of all, since each car could have been painted many colors but you want to retrieve the latest painted color. This means you have a one to many relationship from car to color. Therefore the relationship color should be changed to
public function colors()
{
return $this->hasMany(Colors::class)
->latest();
}
Then to only retrieve the latest color you can call ->limit(1) since the colors are already ordered by the relationship.
$cars = $query->with(['colors', function($query) {
return $query->limit(1);
}])
->get();
Then you can filter whether the latest color is in your $colors array
$filteredCars = $cars->filter(function($car) {
return $car->colors->whereIn('paint_color', $colors);
});
Quick question, I have Model that related to different model (one to many).
I'm building method that should return js array with related table included to array.
But I need to sort a bit warrant_grants, I need to return $warrant_grants->where('status', active). So My ->where() doesn't work this way:
public function warrants($company_id){
$company = auth()->user()->companies()->findOrFail($company_id);
$warrants = $company->warrants;
foreach($warrants as $warrant) {
//this doesn't work
$warrant->warrantGrants->where('status', 'active');
}
$warrants = $warrants->toArray();
return array_splice($warrants, 0);
}
Relationship:
public function warrantGrants()
{
return $this->hasMany(WarrantGrant::class);
}
Need this little help, bc it returns me data with any status, I need only 'active'
Try this
$company = App\Company::whereHas('warrants.warrantGrants', function ($query) {
$query->where('status', '=', 'active');
})->get();
I have two tables, say Products and Biddings where one product can be bid by many users. Naturally I have two models:
class Product extends Model
{
public function biddings()
{
return $this->hasMany('App\Bidding');
}
}
class Bidding extends Model
{
public function product()
{
return $this->belongsTo('App\Product');
}
}
So, say I want to get all products along with the highest priced bidding I did something like this.
$productBidding = DB::table('biddings')
->select('*', DB::raw('max(price) as price'))
->join('products', 'products.id', '=', 'biddings.product_id')
->groupBy('product_id')
->get();
That works well BUT I kinda want to do it Eloquent way. So how do I convert Query Builder way to Eloquent? I am currently on this but do not know how to put the "max" condition in.
$productBidding = Products::with('biddings')
->get();
$productbinding=Bidding:with('product')
->get();
foreach($productbinding as $productbind)
{
echo $productbind->product->name; // example
}
I would extract the highest bid to a separate function on the Product model, like so:
public function highestBid() {
return $this->biddings()->max('price');
}
Then fetch the products and get the highest bid:
$products = Product::get();
foreach ($products AS $product) {
echo $product->highestBid();
}
I got stuck here been trying from 2-3 hours.
I have a many to many relation:
class Category extends Model
{
public function news()
{
return $this->belongsToMany('App\News');
}
}
class News extends Model
{
public function categories()
{
return $this->belongsToMany('App\Category');
}
}
I am trying to get latest 5 news of the related categories:
$front_categories = Category::with(array(
'news'=>function($query){
$query->where('publish','1')->orderBy('created_at', 'desc')->take(5);}))
->where('in_front', 1)->get();
The above query is not working for me it give a total of five results instead of 5 result for each categories.
Based on what I know about Laravel, you could try doing it this way instead.
class Category {
public function recentNews()
{
return $this->news()->orderBy('created_by', 'DESC')
->take(5);
}
}
// Get your categories
$front_categories = Category::where('in_front', 1)->get();
// load the recent news for each category, this will be lazy loaded
// inside any loop that it's used in.
foreach ($front_categories as $category) {
$category->recentNews;
}
This has the same effect as Lê Trần Tiến Trung's answer and results in multiple queries. It also depends on if you're reusing this functionality or not. If it is a one-off, it may be better to put this somewhere else. Other ways could also be more dynamic, such as creating a method that returns the collection of categories and you can ask it for a certain number:
class CategoriesRepository {
public static function getFrontCategories(array $opts = []) {
$categories = Category::where('in_front', 1)->get();
if (!empty($opts) && isset($opts['withNewsCount']))
{
foreach ($categories as $category)
{
$category->recentNews = static::getRecentNewsForCategory(
$category->id,
$opts['withNewsCount']
);
}
}
return $categories;
}
}
$front_categories = CategoriesRepository::getFrontCategories([
'withNewsCount' => 5
]);
I think, Because you do eager loading a collection which has more than one record.
To solve it, you need to loop
$front_categories = Category::where('in_front', 1)->get();
foreach ($front_categories as $fCategory) {
$fCategory->load(['news' => function($query) {
$query->where('publish','1')->orderBy('created_at', 'desc')->take(5);
}]);
}
This solution will do many queries to DB. If you want to do with only 1 query, checkout this Using LIMIT within GROUP BY to get N results per group?