Laravel: query is only fetching one related id - php

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.

Related

Cakephp 4: FIND_IN_SET not returning result

I have an array, $submenus, in my app that I implode to a delimited string:
$subs = implode(',', $submenus);
The string will look something like this: 'ml_,nc_,msr_'. These values are stored in a field called group_prefix in my submenus table. Each submenu row has a unique group_prefix.
The following code builds menus and submenus from a database:
$menus = $this->Menus->find('all', [
'order' => ['Menus.display_order ASC'],
'conditions' => $conditions,
'contain' => [
'Submenus' => [
'conditions' => [
'Submenus.status' => 1,
'FIND_IN_SET("' . $subs . '", Submenus.group_prefix)'
],
]
]
]);
$this->set('menus', $menus);
It works fine until I add the FIND_IN_SET condition on Submenus. When I do, I get no submenus returned, just the main menus. Debug confirms that the string is formatted propery. Doesn't error out, I just get no resultset.
When I run the submenus query in MySQL, it works.
set #prefixes = 'ml_,nc_,msr_';
SELECT `id`, `name` FROM `submenus` WHERE `status` = 1 AND FIND_IN_SET(`submenus`.`group_prefix`, #prefixes);
+----+---------------------------+
| id | name |
+----+---------------------------+
| 4 | Mission Lessons Module |
| 5 | MSR Module |
| 8 | Work Authorization Module |
+----+---------------------------+
What am I missing?
Answer was to reverse the order of arguments in FIND_IN_SET.

(Laravel/PHP) SQL Query that selects all orders from table that matches product_id and variation_id in array

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.

Laravel - Set collection data from another collection

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' => ....
]
]

How can I join two tables on multiple columns in CakePHP 3?

I'm using CakePHP v3
I have a table that looks like this:
Document:
id | section | paragraph
-------------------------
1 2 4
Text:
id | section | paragraph | theText
---------------------------------------
12 2 4 Blah blah
So in SQL I could do something like this;
SELECT * FROM document
INNER JOIN text
ON document.section=text.section
AND document.paragraph=text.paragraph
How can I do something like this in CakePHP using the ORM? The Primary key in both tables is set up to be the id column.
I've looked into foreignKey and binidingKey in Cake's docs, but I can't see how to use multiple columns in those.
http://book.cakephp.org/3.0/en/orm/associations.html.
FWIW, here is a sample of code that shows how I want to access them.
$cond = [
'contain' => ['text']
];
$docs = $this->Documents->find('all',$cond);
Yes, it is possible. Just use arrays to express the columns that should be matched:
$this->belongsTo('Things', [
'bindingKey' => ['key1', 'ke2'],
'foreignKey' => ['fk1', 'fk2']
]);
That will match key1 = fk1 and key2 = fk2

Fetching row data as column names and set as boolean if exists or not

I have access to a database similar to this:
users:
id | name
====|========
1 | Tom
2 | Dick
3 | Harry
4 | Sally
exlusions:
user_id | exclusion
========|==============
1 | French only
3 | No magazine
4 | English only
1 | No magazine
Is it possible to query the database to get a result like this?
$users = [
[
'id' => 1,
'name' => 'Tom',
'english_only' => false, // unset or null would be okay
'french_only' => true,
'no_magazine' => true,
],
// . . .
];
I've been playing around with things like GROUP_CONCAT, PIVOT, and other examples and can't figure out how or if any of it applies.
SQL Fiddle -- thought I could modify this to match my scenario. I didn't get all that far, and as you can see I have no idea what I am doing...
You can use IF in your select to make your 3 columns out of the 1 based on their values.
SELECT id, name,
IF(exclusion='English only',true,false) as english_only
IF(exclusion='French only',true,false) as french_only
IF(exclusion='No magazine',true,false) as no_magazine
FROM users, exclusions
WHERE users.id=exclusions.user_id
I started with #RightClick's answer, but had to tweak it a bit for my SQL server.
SELECT User.id, User.name,
CASE WHEN Ex.exclusion = 'English Only' THEN 1 ELSE 0 END as english_only,
CASE WHEN Ex.exclusion = 'French Only' THEN 1 ELSE 0 END as french_only,
CASE WHEN Ex.exclusion = 'No magazine' THEN 1 ELSE 0 END as no_magazine
FROM users as User
LEFT JOIN exclusions Ex on User.id = Ex.user_id;
So much simpler than what I thought it was going to be after googling and searching SO all day...

Categories