I'm having problem in fetching the data using groupBy, I don't where I'm wrong, I have done it many times before, but today I'm wrong some where and I don't know where. Following is the Table from which I want to select the Data:
Table Name: user_questions
id | user_id | message | read_status_user | read_status_support | answered
Now suppose if one user sends more than one messages, then user_id will be repeated, So to want all the message from one particular user I'm firing the query like following:
UserQuestion::groupBy('user_id')->get();
This should give me the result like
user_id = 1 > message1
user_id = 1 > message2
....
user_id = 1 > message...(if any)
user_id = 2 > message1
user_id = 2 > message2
.....
So on...
But this is always giving me only one message from the particular user. I don't know why. Is there any mistake? I have tried another queries too, but all are giving me the same result.
Please help me with this. Everybody's help will be highly appreciated. Thanks to all of you in advance.
The issue here is that you are calling the groupBy function of the query builder object, which is what generates the query for your database. When you call the ->get() method, the query is executed and a Collection object containing the results is returned. What you are looking to use is the groupBy method of Laravel's Collection class, which means you need to put the ->groupBy('user_id') after the ->get().
Assuming you have the following data:
user_question
user_id question_id
1 1
1 2
1 3
2 4
3 5
3 6
Your current code
UserQuestion::groupBy('user_id')->get();
executes this query
select * from user_question group by user_id;
returning one row per user, since that's what group by does in MySQL.
user_id question_id
1 1
2 4
3 5
If instead, you do the following
$collection = UserQuestion::get();
the query is simply
select * from user_question
and when you call $collection->groupBy('user_id') on this collection, you get data structured like
[
1 => [
[ 'user_id' => 1, 'question_id' => 1 ],
[ 'user_id' => 1, 'question_id' => 2 ],
[ 'user_id' => 1, 'question_id' => 3 ]
],
2 => [
[ 'user_id' => 2, 'question_id' => 4 ],
],
3 => [
[ 'user_id' => 3, 'question_id' => 5 ],
[ 'user_id' => 3, 'question_id' => 6 ]
]
]
Try like this
$users = DB::table('table_name')
->groupBy('user_id')
->get();
after that push that to foreach loop
foreach ($users as $user)
{
var_dump($user->name);
}
ordering-grouping-limit-and-offset in Laravel
You've probably found the solution to your problem by now but otherwise, I would suggest to use the relationships. In the User model, I would do:
public function questions()
{
return $this->hasMany('App\UserQuestion');
}
Then I would get all the users and loop through them to get their messages.
$users = User::all();
$users->each(function ($user) {
$questions = User::find($user->id)->questions;
});
Related
How can I get data by grouping user_id for a foreach loop in a controller's function in Laravel. For example, user_id = 2, 5 rows available, user_id = 1, 10 rows available. Then show 2 arrays.
$lists = lists::wherestatus(1)->groupby('user_id')->get();
foreach($lists as $list){
$list = functionHere;
}
What function can I create for this on the controller for grouping?
I need more information, but based on what you shared, you should be able to do this (removing the foreach):
$lists = Lists::whereStatus(1)->get()->groupBy('user_id');
The difference is that if you use groupBy before get, you are grouping your query by user_id, so instead of getting 5 rows for user_id = 2 and 10 for user_id = 1, you are going to get 2 rows and just the latest data, so you need to use Collection's groupBy.
What you want to do is group all the information by user_id but have each row, a schema like this:
[
'1' => [ // user_id
['user_id' => '1', 'column1' => 'random value'],
['user_id' => '1', 'column1' => 'other value'],
// 8 remaining rows
],
'2' => [ // user_id
['user_id' => '2', 'column1' => 'other nice value'],
// 4 remaining rows
],
]
you should first in List model set:
public function scopeStatus(){
return $this->where('status','1');
}
and in your controller:
$products = List::status()->groupby('user_id')->get();
Laravel 5.3, I have this 2 models:
User:
public function newFunctions()
{
return $this
->belongsToMany('App\NewFunctions', 'user_newfunctions')
->withPivot(['function_count', 'days_count']);
}
NewFunctions:
public function users()
{
return $this
->belongsToMany('App\User', 'user_newfunctions', 'new_function_id', 'user_id')
->withPivot(['function_count', 'days_count']);
}
I now how can I save new data to User, with this:
$user = User::findOrFail($id);
$user->name = $request->input('name');
$user->save();
But now I have to update some values of a pivot table. the pivot table is this:
user_id | new_functions_id | function_count | days_count
---------------------------------------------------------
814 | 1 | 5 |2019-07-19 12:26:19
814 | 3 | 7 |2019-07-19 12:26:19
I have more than 1 row per user_id. I was trying to use:
$user
->newFunctions()
->sync([
'days_count' => $test_date,
'function_count' => $test_int_number
]);
But I'm getting error like:
Ilegal offset type
because is trying to update with this:
array(
'records' => array(
'days_count' => object(Carbon), 'function_count' => '66'),
'results' => array(),
'id' => object(Carbon),
'attributes' => array()
)
)
in BelongsToMany.php
So:
How could I update the values for each user_id on the pivot table?
And how should use syncto update just 'function_count' and 'days_count'? they come from request.
->sync() isn't used like that; it's used to attach() and detach() related new_function_ids until only the ids in sync() are present. You're probably looking for updateExistingPivot()
An example of ->sync() would be using the array:
$user->newFunctions()->sync([
"new_function_id" => 1,
"function_count" => 6,
"days_count" => "2019-07-08 12:00:00",
]);
This would remove the record where new_function_id is 3, and updating the values where new_function_id is 1.
To update function_count and days_count for either new_function_id of 1 or 3, use ->updateExistingPivot() (pass the id you want to update as the first parameter):
$user
->newFunctions()
->updateExistingPivot("1", [
"function_count" => 6,
"days_count" = "2019-07-08 12:00:00"
]);
// or $user->newFunctions()->updateExistingPivot("3", ...);
This will update the pivot table where new_function_id is 1, while leaving the row where new_function_id is 3.
Edit: If you're looking to update all existing records in the pivot table, you'll need to do this in a loop, call a sync with all current records in a single array, or run a manual query.
I have a two tables:
qr_details table:
id product_id qrcode_id created_at updated_at
1 1 12 2017-10-09 15:36:15 2017-10-09 15:36:15
2 3 13 2017-10-09 15:36:15 2017-10-09 15:36:15
winners table:
id product_id qrcode_id winner_name win_number created_at updated_at
1 1 12 hello 5 2017-10-09 15:36:15 2017-10-09 15:36:15
2 3 13 world 6 2017-10-09 15:36:15 2017-10-09 15:36:15
Now i want to get qr_details table product_id & qrcode_id into winners table. How can i do that with query in Laravel? I have made a SQL Fiddle here. Thanks in advance.
I don't really understand your question but you can try this:
$datas = DB::table('qr_details ')->get();
foreach($datas as $data){
DB::table('winners')->insert(['qrcode_id' => $data->qrcode_id, 'product_id'=>$data->product_id, ...bunch other inserts])
}
I believe you can do something like this:
$query = \DB::connection()->getPdo()->query("select * from qr_details");
$data = $query->fetchAll(\PDO::FETCH_ASSOC);
\DB::table('winners')->insert($data);
it will take a little time and just two queries
If you were to add new records to the winners table then you could use Eloquent models and insert method to add multiple record in a single query.
$qcodes = Qrcode::all()->map(function(Qrcode $qrcode) {
return [
'id' => $qrcode->id,
'product_id' => $qrcode->product_id,
'qrcode_id' => $qrcode->qrcode_id,
'winner_name' => 'some name',
'win_number' => 5
];
});
Winner::insert($qcodes);
However, guessing from what you said, that's probably not what you're after - as you want only product_id and qrcode_id to be added - in other words to update existing records.
If that's the case, and if your id column matches in both of the tables then you could do something similar to:
$qcodes = Qrcode::all();
$qcodes->each(function(Qrcode $qrcode) {
Winner::where('id', $qrcode->id)->update([
'product_id' => $qrcode->product_id,
'qrcode_id' => $qrcode->qrcode_id
]);
});
This is again assuming you are using Eloquent models - otherwise you'd have to do it using Query Builder:
$qcodes= DB::table('qr_details')->get();
$qcodes->each(function(Qrcode $qrcode) {
DB::table('winners')
->where('id', $qrcode->id)
->update([
'product_id' => $qrcode->product_id,
'qrcode_id' => $qrcode->qrcode_id
]);
});
Make sure you update table / model names accordingly.
Now, one issue with your sql structure is that your winners table product_id and qrcode_id is NOT NULL so it has to have some data there when record is first created. If you were to update these records, I would suggest to change these two columns to NULL so that initially they don't require any data.
I am working with Yii framework 2.0, I have one database table that looks like the following.
id active key
1 0 xx
2 1 xx
3 0 zzz
4 0 wwww
5 1 wwww
6 1 qqqqq
I would like to get the record where 'active' is 1 and 'key' is the same as 'key' of the record where 'active' is 0. The result that I want is
id active key
2 1 xx
5 1 wwww
It might not be easy to understand the question, so I put following code sample to support the question. This codes gives me the result I want.
$allModel = Model::find()->where(['active' => 0])->all();
$arrModelActive1 = [];
foreach($allModel as $model) {
$modelActive1 = Model::find()->where['active' => 1, 'key' => $model->key]->all();
$arrModelActive1[] = $modelActive1;
}
return $arrModelActive1;
I could approach this problem with the above code sample, but the problem is that I execute the query inside of the foreach loop which might decrease the performance. So I am looking for a join or an eager loading solution which Yii 2.0 might provide which could operate with the same table or so-called self-join operation.
Example:
You have relation as public function getTest()
{
return $this->hasMany(self::className(), ['key' => 'key'])
->where('active = :active', [':active' => 1]);
}
and after that you must select items with active field == 0
$model = Model::find(['active' => 0])->all(); var_dump($model->test);
Continuing this question,
in my web app, I want to allow users to add friends, like facebook, in my previous question, I finally decided to have the database structure as #yiding said:
I would de-normalize the relation such that it's symmetric. That is,
if 1 and 2 are friends, i'd have two rows (1,2) and (2,1).
The disadvantage is that it's twice the size, and you have to do 2
writes when forming and breaking friendships. The advantage is all
your read queries are simpler. This is probably a good trade-off
because most of the time you are reading instead of writing.
This has the added advantage that if you eventually outgrow one
database and decide to do user-sharding, you don't have to traverse
every other db shard to find out who a person's friends are.
So, now if user 1 adds user 2, and user 5 adds 2, something like this will go into the db:
ROW_ID USER_ID FRIEND_ID STATUS
1 1 2 0
2 2 1 0
3 5 2 0
4 2 5 0
As you see, we insert the row of the "REQUEST SENDER" first, so now imagine that user 5 is logged in, and we want to show him the friendship requests, here is my query:
$check_requests = mysql_query("SELECT * FROM friends_tbl WHERE FRIEND_ID = '5'");
the above query, will fetch ROW_ID = 4, this means with the above query shows us that user 2 has added 5, but he has NOT, actually the user 5 added user 2, so here we should not show any friendship requests for user 5, instead we need to show it for user 2.
How I'm supposed to check this correctly?
This is an edited answer.
Your SQL query should look like this:
SELECT USER_ID, FRIEND_ID FROM friends_tbl WHERE FRIEND_ID = '5' OR USER_ID = '5'
Then you have to parse your result in this way. Assuming you have got a php array like this:
$result = array(
0 => array(
'USER_ID' => 5,
'FRIEND_ID' => 2
),
1 => array(
'USER_ID' => 2,
'FRIEND_ID' => 5
)
2 => array(
'USER_ID' => 5,
'FRIEND_ID' => 8
),
3 => array(
'USER_ID' => 8,
'FRIEND_ID' => 5
)
)
You just have to get the even rows:
$result_final = array();
for($i = 0; $i < count($result); $i++) {
if($i % 2 == 0) $result_final[] = $result[$i];
}
Then you will have an array like this:
$result = array(
0 => array(
'USER_ID' => 5,
'FRIEND_ID' => 2
),
1 => array(
'USER_ID' => 5,
'FRIEND_ID' => 8
)
)
Alternative method: Make your SQL look like this:
SELECT FRIEND_ID FROM friends_tbl WHERE USER_ID = '5'
That's all.
Friendship query notifies should be placed in something like message inbox. Relation you described is meant to hold, well, friendship relations, not the fact of the event happening itself. You should consider create relation to hold notifies and fill it properly alongside with two inserts on friends_tbl
You'll need to hold a temporary table (or fixed - for data mining) which has all the requests made from one user to another, for example:
table: friendRequest
inviterId inviteeId status tstamp
2 5 0 NOW()
5 8 0 NOW()
assuming that 0 is unapproved.
Than you'll query for all pending requests
SELECT * FROM friendRequest WHERE invitee_id = :currentLoggedUserId AND status = 0
Once a user approved a user, you'll create a transaction, describing this newly formed relation and updating the friendRequests table
You could also query this way assymetric relations, where a user has many followers, by looking for un-mutual friendships.