Eloquent where clause returning wrong entries - php

In my Laravel/Lumen Project (Version 8) I try to retrieve data from my Oracle Database, but I get unexpected data.
My database contains following 4 entries:
ID
FOREIGN_ID
NAME
1
100
Entry1
2
100
Entry2
3
100
Entry3
4
200
Entry4
My model:
class Entry extends Model
{
protected $connection = 'MyConnection';
protected $table = 'MY_TABLE';
protected $fillable = ['foreign_id', 'name'];
protected $hidden = ['foreign_id'];
protected $casts = [
'foreign_id' => 'integer'
];
}
When I execute the following line of code, only Entry1 with ID 1 is returned, while I would expect an empty collection:
Entry::where([['id', '!=', 1], 'foreign_id' => 100, 'name' => 'Entry1'])->get();
To analyze the problem, I also tried to write lined up where clauses:
//returns all but Entry1; correct
Entry::where(['id', '!=', 1])->get();
//returns Entry2 and Entry3; correct
Entry::where(['id', '!=', 1])->where(['foreign_id' => 100])->get();
//returns only Entry1; wrong, should be an empty collection
Entry::where(['id', '!=', 1])->where(['foreign_id' => 100])->where(['name' => 'Entry1'])->get();
The generated sql query looks like this:
"select * from "MY_TABLE" where ("ID" != ? and "FOREIGN_ID" = ? and "NAME" = ?)"
The Lumen Version is: 8.3.4
EDIT:
I have tried this on another Laptop now. There I get an empty collection.
Have you any idea what configuration/setting might do the trick, that my query is interpreted in two different ways?

Try below Code
Entry::where([
['id', '!=', 1],
['foreign_id', 100],
['name', 'Entry1']
])->get();

Related

How I get data by group User ID for foreach controller function in Laravel

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 eloquent model not able to store decimal values

I'm using Laravel 5.7 and PHP 7.3 where
I have to store decimal fields in database
table column decription look like this
'commission_percentage', 'decimal(12,4)'
'commission_amount', 'decimal(12,4)'
And I'm trying to store decimal value for this column in mysql using eloquent model.
And here is the example code for that.
$per = 10.23;
$commission = 2.1234;
$createArr = [
'commission_percentage' => $per,
'commission_amount' => $commission
];
MyModel::create($createArr);
my eloquent model look like
class MyModel extends Model
{
protected $table = 'my_table';
protected $guarded = ['id'];
protected $casts = [
'commission_percentage' => 'decimal:4',
'commission_amount' => 'decimal:4'
];
}
And I have also tried
protected $casts = [
'commission_percentage' => 'float',
'commission_amount' => 'float'
];
But no luck. I still get 10.0000 and 2.0000 inside the DB.
Even I have tried inserting value's using raw query
DB::insert('insert into my_table (commission_percentage,commission_amount ) values(?, ?)', [$per, $commission]);
But hard luck on that too as I still get 10.0000 and 2.0000 inside the DB.
The work around that I have found for this is to typecast the variable into "string"
$per = 10.23;
$commission = 2.1234;
$createArr = [
'commission_percentage' => (string) $per,
'commission_amount' => (string) $commission
];
MyModel::create($createArr);

How to use sync on a 3 model relationship? - Laravel

I have 3 models:
Match Team Player
And i want to create a table with the following structure:
id | match_id | team_id | player_id
So that i can associate the 3 models i refered.
I created a 4th model MatchPlayers for the table i referred and I can use the 'search' functions without a problem. Like this:
$match->matchPlayers()->first()->team()->get()
And it returns the excpected result, but I cant do a
$match->matchPlayers()->sync([])
So, how should i solve this? Is my relationship wrong or the sync method isnt allowed on a 3 model relationship and I shoud use other method?
Thanks in advance
Edit:
Match.php
public function teamPlayers(){
return $this->hasMany('\Modules\Matchs\Entities\MatchPlayer');
}
Team.php
public function matchTeamPlayers(){
return $this->hasMany('\Modules\Matchs\Entities\MatchPlayer');
}
Player.php
public function matchTeamPlayers(){
return $this->hasMany('\Modules\Matchs\Entities\MatchPlayer');
}
MatchPlayer.php
public function player(){
return $this->belongsTo('\Modules\Players\Entities\Player');
}
public function match(){
return $this->belongsTo('\Modules\Matchs\Entities\Match');
}
public function team(){
return $this->belongsTo('\Modules\Teams\Entities\Team');
}
If you've followed the Laravel documentation on Pivot tables and Many-Many relationships found here, and it's still not working, you might have more luck with "Attach". For example;
$matchPlayer = MatchPlayer::create([...]);
$match->matchPlayers()->attach($matchPlayer)
A good example of sync vs attach can be found here
Using a fourth model for this kind of relationship makes sense, as it gives you a navigation property for the third relation on your pivot table. This way you can form more complex queries this way.
For your particular problem, syncing based on match_id and team_id, I would simply do something like this:
$matchId = 123;
$teamId = 234;
$rows = [
['match_id' => $matchId, 'team_id' => $teamId, 'player_id' => 345],
['match_id' => $matchId, 'team_id' => $teamId, 'player_id' => 346],
['match_id' => $matchId, 'team_id' => $teamId, 'player_id' => 347],
];
// remove all previously stored connections
MatchPlayer::where('match_id', $matchId)
->where('team_id', $teamId)
->delete();
// insert the news ones
// (you could also use MatchPlayer::create() per item or
// $matchPlayer->save(), it doesn't matter)
MatchPlayer::insert($rows);
If this operation occurs very frequently, you will potentially burn through a lot of id values of the pivot table. In this case you could also perform a more efficient sync, which is slightly more complex:
$matchId = 123;
$teamId = 234;
$rows = [
['match_id' => $matchId, 'team_id' => $teamId, 'player_id' => 345],
['match_id' => $matchId, 'team_id' => $teamId, 'player_id' => 346],
['match_id' => $matchId, 'team_id' => $teamId, 'player_id' => 347],
];
// delete all players that are not among the new data anymore
MatchPlayer::where('match_id', $matchId)
->where('team_id', $teamId)
->whereNotIn('player_id', array_pluck($rows, 'player_id'))
->delete();
// remove rows from new data that already exist
$exist = MatchPlayer::where('match_id', $matchId)
->where('team_id', $teamId)
->pluck('player_id')
->toArray();
$rows = array_filter($rows, function ($value, $key) use ($exist) {
return ! in_array($value['player_id'], $exist);
});
// then we store the remaining data
MatchPlayer::insert($rows);

Laravel ORM for Join Multiple Table

I have 9 tables that will love to join together all have the foreign key employee_id from employee table. How can I get ORM distribution for it. Below is the DB function that join all the function.
$modelEmployee = \DB::table('employees')
->select('*')
->join('employee_finances', 'employees.id', '=', 'employee_finances.employee_id')
->join('employee_addresses', 'employees.id', '=', 'employee_addresses.employee_id')
->join('employee_jobs', 'employees.id', '=', 'employee_jobs.employee_id')
->join('employee_admins', 'employees.id', '=', 'employee_admins.employee_id')
->join('employee_personals', 'employees.id', '=', 'employee_personals.employee_id')
->join('employee_memberships', 'employees.id', '=', 'employee_memberships.employee_id')
->where('employees.id', $id)
->get();
Step 1
First, create model for you employee table and add various relations to other table models
Eloquent Model for employees table
namespace App\Models;
class Employee extends \Illuminate\Database\Eloquent\Model {
public function employee_finances()
{
return $this->hasMany(\App\Models\EmployeeFinance);
}
public function employee_addresses()
{
return $this->hasMany(\App\Models\EmployeeAddress);
}
public function employee_jobs()
{
return $this->hasMany(\App\Models\EmployeeJob);
}
public function employee_admins()
{
return $this->hasMany(\App\Models\EmployeeAdmin);
}
public function employee_personals()
{
return $this->hasMany(\App\Models\EmployeePersonal);
}
public function employee_memberships()
{
return $this->hasMany(\App\Models\EmployeeMembership);
}
}
Step 2
Now create models for other join tables. Below is an example of employee_finances table. (similarly, create other models)
namespace App\Models;
class EmployeeFinance extends \Illuminate\Database\Eloquent\Model {
...
}
Step 3
Then for your query, you can use relations using with and whereHas functions of query builder. This equivalent to the result of the query mentioned in the question but the structure of the outcome will be different;
\App\Models\Employee::with('employee_finances','employee_addresses','employee_jobs','employee_admins','employee_personals','employee_memberships')
->whereId($employeeid)
->whereHas('employee_finances')
->whereHas('employee_addresses')
->whereHas('employee_jobs')
->whereHas('employee_admins')
->whereHas('employee_personals')
->whereHas('employee_memberships')
->get();
Result
Original Result object
The original resultant will be an object of common builder object where you cannot fire further relation actions which can be defined in Model level.
The original result will also be a flat array of the result and may have less. One example here would be the id column value would be replaced by the primary employee's table column id.
[
0 => [
'id' => 1,
'employee_name' => 'Employee',
'employee_finance_content' => 'finance_content',
'employee_personal_content' => 'personal_content',
'employee_jobs_content' => 'employee_jobs',
'employee_addresses_content' => 'employee_addresses',
'employee_admins_content' => 'employee_admins',
]
....
]
New result using Models
The result would be an instance of Employee model. The final result would be as an associative array where each relation would be an index of the array but the result will be an instance of the related Model, for example, the employee_finances would be an index or represent a column and the value contained within it will be an instance of EmployeeFinance on which you can further do ORM level activities.
[
0 => [
'id' => 1,
'employee_name' => 'Employee'
'employee_finances' => [
'id' => 2,
'employee_id' => 1,
'employee_finance_content' => 'finance_content'
],
'employee_addresses' => [
'id' => 10,
'employee_id' => 1,
'employee_address_content' => 'employee_address'
]
],
.....
]
you can use from this :
$row = $this->model->
where("id",$id)
->with("employee_finances")
->with("employee_addresses")
->with("employee_jobs")
->with("employee_admins")
->with("employee_personals")
->with("employee_memberships")
->with("employee_finances")
->get();
return $row->isEmpty() ? [] : $row->toArray();
plz define relations in your models with these names and use form that, here.

GroupBy Query Laravel 5.1

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;
});

Categories