I have two tables: products and colors.
Products
id | product_name | color_id
----------------------------
1 | Product 1 | 1
2 | Product 2 | 2
Colors
id | name
---------
1 | blue
2 | silver
3 | green
And i have collection:
$product = Product::all();
And i want to have another collection from color table with colors which exists in product collection. So i want to see colors: blue (product 1) and silver (product 2) without green. Is it possible to get something like this? I think about relationship but i'm not sure how to do it. Thanks.
If you want take colors from colors table that are assigned to any product, then you can do like this:
$products = Product::all();
$assigned_color_ids = $products->pluck('id')->toArray();
$colors = Color::whereIn('id', $assigned_color_ids)->get();
For your given table, the query will be whereIn('id', [1, 2]) because color with id 3 is not used in products table
maybe can try this,
in your COlors model define a relation to products
/**
* Get the products for the color.
*/
public function products()
{
return $this->hasMany('App\Products','color_id');
}
and you can access to all products from color model,
$colorswithproducts = Colors::whereHas('products')->get();
dd($colorswithproducts);
1 => [
'name' => 'blue'
'products' =>
[
"id" : "1",
'name' => ....
]
]
Related
Im trying to build a SQL Query that will select all orders from a table that matches options that i defined.
Databse i use: Mysql
Language: PHP
Basicly i have a array that looks like this.
[
[
"user_id" => 1,
"product_id" => 5548,
"variation_id" => 14
],
[
"user_id" => 1,
"product_id" => 5548,
"variation_id" => 15
],
[
"user_id" => 1,
"product_id" => 4422,
"variation_id" => 4
]
]
This means that the user(id: 1) has one product with the "id" of 5548, and then he also has 2 variations of that product that are "id" 14 and 15. You can also see that the same user owns the product(id:4422) that has variation(id:4).
I then have a "order_lines" table that looks like this
order_lines
+----+-----+---------+-----------------------------+
| id | uid | user_id | product_id | variation_id |
+----+-----+---------+-----------------------------+
| 1 | 1 | 1 | 5548 | 14 |
+----+-----+---------+-----------------------------+
| 2 | 2 | 1 | 5548 | 15 |
+----+-----+---------+-----------------------------+
| 3 | 3 | 1 | 4422 | 4 |
+----+-----+---------+-----------------------------+
| . | . | . | .... | .. |
+----+-----+---------+-----------------------------+
I now need a SQL Query that selects all the rows where there is a match between the user_id, product_id and variation_id that are defined in the array.
The output should contain all rows that meet these conditions.
I hope someone can pin me in the right direction.
I'm building in Laravel if you got the query builder just at your hand. Else i very much appreciate an SQL Query.
if I am getting you right, below code will help you, using just Core PHP
foreach($array as $arr){
$user_id = $arr['user_id'];
$prodct_id = $arr['prodct_id'];
$variation_id = $arr['variation_id'];
$query = "SELECT * FROM order_lines WHERE user_id = $userId AND product_id = $productId AND variation_id = $variationId";
$queryResult = mysql_fetch_assoc($query);
$yourCollection[] = $queryResult;
}
print_r($yourCollection);
Try below code to use Laravel Query Builder, below code will help you to get results for multiple users based on product and variation.
$qb_order_lines = DB::table('order_lines');
$where_condition = [
['user_id' => '', 'product_id' => '', 'variation_id' => ''],
];
foreach ($where_condition as $condition) {
$qb_order_lines->orWhere(function($query) use ($condition) {
$query->where('user_id', $condition['user_id'])
->where('product_id', $condition['product_id'])
->where('variation_id', $condition['variation_id']);
});
}
$obj_result = $qb_order_lines->get();
If you want to get it for only one user, use below code
$obj_result = DB::table('order_lines')
->where('user_id', $condition['user_id'])
->where('product_id', $condition['product_id'])
->where('variation_id', $condition['variation_id'])
->get();
You can modify the above query builders based on your requirements like select fields or group by.
Let me know if you need any help.
For anyone interesting.
My problem was that i needed to count of many matches that were between my array and my database.
Instead of selecting and outputting. I eneded up using sql count() function in a query, that did the job.
I have created a MySQL database table where I want to show the menu structure based on their parent. The menu table contains the following data:
id | menuname | parentid
---+-------------------+---------
1 | dashboard | 0
2 | Content | 0
3 | Home Page Content | 2
4 | Banners | 2
5 | Settings | 0
6 | Block Content | 3
7 | Site Content | 3
So that the menu structure will look like:
dashboard
Content
Home Page Content
Block Content
Site Content
Banners
Settings
I have gone though the post over here Recursive menu tree from array
however, unable to understand the basics. However, the idea I understood that I need to write a recursive function to sort out this. Can someone give me some ideas how to generate the above?
Imagine you are selected from database with sql query
SELECT * FROM my_table ORDER BY parentid ASC, id ASC
and you have this array in PHP
$arr = [
[
"id"=>1,
"username"=>"dashboard",
"parentid"=>0
],
[
"id"=>2,
"username"=>"dashboard",
"parentid"=>0
],
[
"id"=>5,
"username"=>"dashboard",
"parentid"=>0
],
[
"id"=>3,
"username"=>"dashboard",
"parentid"=>2
],
[
"id"=>4,
"username"=>"dashboard",
"parentid"=>2
],
[
"id"=>6,
"username"=>"dashboard",
"parentid"=>3
],
[
"id"=>7,
"username"=>"dashboard",
"parentid"=>3
],
];
$categories = [];
foreach ($arr as $item){
if($item["parentid"]==0){
$categories[$item["id"]] = $item;
}else{
$categories[$item["parentid"]]["subs"][] = $item;
}
}
Im trying to get all id's that are related to a specific list but my query is only returning the first related id in the table and not the others.
Tables
List | id | person_id | name | description
| 1 | 10 | Test List | null
List_Ref | id | list_id | data_id
| 1 | 1 | 100
| 2 | 1 | 101
Query
$lists = DB::table('List')
->leftJoin('List_Ref', 'List_Ref.list.id', '=', 'List.id')
->select('List.id', 'List.name', 'List_Ref.data_id')
->where('person_id', Auth::user()->person_id)
->groupBy('List.id')
->orderBy('List.id')
->get();
Result (Laravel Die and Dump)
#items: array:1 [
0 => {
"id" : 1
"name" : "Test List"
"data_id" " 100
}
]
I would like to produce a result like the following
#items: array:1 [
0 => {
"id" : 1
"name" : "Test List"
"data_id" => {
"id" : 100
"id" : 101
}
}
]
If you want to get available grouped items don't use group by while building your query.
Do like this:
$lists = DB::table('List')
->leftJoin('List_Ref', 'List_Ref.list.id', '=', 'List.id')
->select('List.id', 'List.name', 'List_Ref.data_id')
->where('person_id', Auth::user()->person_id)
->get();
$lists->groupBy('List.id')->orderBy('List.id');
Use laravel collection's groupBy and orderBy method to get the grouped items. Hope it helps you!
I dont know laravel but you are doing a left join from "List" to "List_Ref".
So every entry in Talbe List will be matched with ONE entry of List_Ref.
Try Full join.
Don't use groupBy('List.id') It will group the data on the basis of id of List table & always return only single data.
I have a Coupon model in a Many to Many relation with a Product model (with pivot table and so on...). I created some local scope to get only available coupons, and to get only coupons of determined category:
public function scopeAvailable($query)
{
return $query->where('available', '>', 0);
}
public function scopeOfCategory($query, $category)
{
return $query->join('categories', 'categories.id', '=', 'coupons.category_id')
->where('categories.slug', $category);
}
I want to eager load all available coupons of some category with their respective products. So I'm doing:
$coupons = Coupon::with('products')->available()->ofCategory($category)->paginate(20);
If I call $coupons->first(), I can see the information about the coupon. But if I call $coupons->first()->products I get an empty array.
If I comment the ->ofCategory($category) part, it works as expected.
Here is my Models:
class Coupon extends Model
{
public function products()
{
return $this->belongsToMany('App\Product');
}
...
}
class Product extends Model
{
public function coupons()
{
return $this->belongsToMany('App\Coupon');
}
...
}
I'm using Laravel 5.2. What am I doing wrong?
Edit:
It looks like a problem with my Category. If I try to get coupons on "other" category, I got my coupon as expected. If I try to get coupons on "electronics" category, I got a coupon with no products. I'm pretty sure I have coupons with products both on "electronics" and "other" categories.
If I dump Category::where('slug', '=', 'electronics')->first():
...
protected 'attributes' =>
array (size=3)
'id' => int 1
'name' => string 'Electronics' (length=11)
'slug' => string 'electronics' (length=11)
...
If I dump Category::where('slug', '=', 'other')->first():
...
protected 'attributes' =>
array (size=3)
'id' => int 2
'name' => string 'Other' (length=5)
'slug' => string 'other' (length=5)
...
Edit 2:
I created another coupons with "other" category, so I have two coupons with this category. When I print the coupons, it shows the first coupon twice.
Table coupons:
| id | name | available | category_id |
|----|------------|-----------|-------------|
| 1 | Coupon #1 | 1 | 1 |
| 2 | Coupon #2 | 1 | 1 |
| 3 | Coupon #3 | 1 | 1 |
Table products:
| id | name |
|----|-------------|
| 1 | Product #1 |
| 2 | Product #2 |
| 3 | Product #3 |
Table coupon_product:
| id |product_id| coupon_id |
|----|----------|-----------|
| 1 | 1 | 1 |
| 2 | 2 | 1 |
Table categories:
| id | slug |
|----|-------------|
| 1 | category-1 |
| 2 | category-2 |
| 3 | category-3 |
Product.php:
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
public function coupons()
{
return $this->belongsToMany('App\Coupon');
}
}
Coupon.php:
class Coupon extends Model
{
public function products()
{
return $this->belongsToMany('App\Product');
}
public function scopeAvailable($query)
{
return $query->where('available', '>', 0);
}
public function scopeOfCategory($query, $category)
{
return $query->join('categories', 'categories.id', '=', 'coupons.category_id')
->where('categories.slug', $category);
}
}
And finally when I run:
$coupons = App\Coupon::with('products')->available()->ofCategory('funny')->first();
dd($coupons->products);
I get this:
Which is correct. Can you post more detailed info about your current state of the project?
I have two tables, a main one, and one that supports the main table, very very similar to what wordpress has, posts and posts_meta.
Main table:
id
title,
content
id | title | content
1 | one | content one
2 | two | content two
Meta table:
id
item_id
key
value
id | item_id | key | value
1 | 1 | template | single
2 | 1 | group | top
1 | 2 | template | page
2 | 2 | group | bottom
And my goal is, in the end, have an array with the data from the main table, merged with the meta table. example:
$data = array(
array(
'id' => 1,
'title' => 'one',
'content' => 'content one',
'template' => 'single',
'group' => 'top'
),
array(
'id' => 2,
'title' => 'two',
'content' => 'content two',
'template' => 'page',
'group' => 'bottom'
)
);
What is the best way to achieve this in a way that preforms good?
I am using PDO to connect to my database, and how Im doing right now is, I first query the data on the first table, and then for each result, i query the meta table, I use prepared statements for this, since it's suposed to be fast, but even so, it's harming the performance of my script.
Thank you
Instead of querying meta table for each result from first query
you should extract the ids from the first result:
$rows = q('SELECT * FROM posts');
$byIds = [];
foreach ($rows as &$row)
{
$byIds[$row['id']] =& $row;
}
and run second query:
$rows2 = q('SELECT * FROM posts_meta WHERE item_id IN (' . implode(',', array_keys($byIds)) . ')');
Then loop the results in PHP and merge with first query results.
foreach ($rows2 as $row2)
{
$byIds[$row2['item_id']][$row2['key']] = $row2['value'];
}
You have your merged results in $rows variable now:
var_dump($rows);
This way you will have only 2 db requests.
Please note that i have used $byIds as array of references so i dont have to search row with specific id in second loop. This way order of elements in $rows are preserved.