Laravel Database query. User information - mysql

#foreach($users as $user)
<div>
{{ $user->username }}
</div>
#endforeach
public function group($id){
if (!$this->secure($id) && $this->secure($id)) return redirect('/404');
$user = Auth::user();
$hobbies = Hobby::all();
$group = $this->group;
$users = DB::table('users')
->join('user_hobbies', 'users.id', '=', 'user_hobbies.user_id')
->where('user_hobbies.hobby_id' == $group_id)
->select('users.*')->orderBy('first_name', 'ASC');
$users = $users->get();
$wall = [
'new_post_group_id' => $group->id
];
return view('groups.group', compact('user', 'users', 'group','wall', 'hobbies'));
}
Hey guys, complete beginner here.. Im trying to access and return the users information of the members of a group. I am not so sure where I am going wrong and I'm trying to understand the log instructions but I can't quite understand where I'm going wrong. Ive seen "Sql error column doesn't exist in where clause".. tried to change the code and finding undeclared variables too.
The system is that a user creates a hobby and that hobby becomes the group. ie 'my hobby is skiing and then a group of skiing is created'. So I have a user_hobbies model of course and everything is work, but I can't quite work out how to access the information of the user from the DB and display it in the blade.
Any help appreciated.

You have typo on query builder.
$users = DB::table('users')
->join('user_hobbies', 'users.id', '=', 'user_hobbies.user_id')
->where('user_hobbies.hobby_id' == $group_id) // This line
->select('users.*')->orderBy('first_name', 'ASC');
It should be
$users = DB::table('users')
->join('user_hobbies', 'users.id', '=', 'user_hobbies.user_id')
->where('user_hobbies.hobby_id', $group_id)
->select('users.*')->orderBy('first_name', 'ASC');
And make sure you use === instead of == for explicit comparation in PHP. It will cause a Type Juggling. I assume your blade file is correct since i dont know what's inside the $user object

Related

Add result of subquery to Eloquent query in Laravel 9

In Laravel 9 I am trying to add the result of a subquery to a query(for lack of better wording) and I am stuck. More concretely, I am trying to load all products and at the same time add information about whether the current user has bought that product.
Why do I want to do this?
I am currently loading all products, then loading all bought products, then comparing the 2 to determine if the user has bought a product, but that means extra queries which I would like to avoid. Pretend for the sake of this question that pagination doesn't exist(because when paginating the impact of those multiple queries is far diminished).
There is a many to many relationship between the 2 tables users and products, so these relationships are defined on the models:
public function products()
{
return $this->belongsToMany(Product::class);
}
and
public function users()
{
return $this->belongsToMany(User::class);
}
What I have tried so far:
I created a model for the join table and tried to use selectRaw to add the extra 'column' I want. This throws a SQL syntax error and I couldn't fix it.
$products = Product::query()
->select('id', 'name')
->selectRaw("ProductUser::where('user_id',$user->id)->where('product_id','products.id')->exists() as is_bought_by_auth_user")
->get();
I tried to use addSelect but that also didn't work.
$products = Product::query()
->select('id', 'name')
->addSelect(['is_bought_by_auth_user' => ProductUser::select('product_id')->where('user_id',$user?->id)->where('product_id','product.id')->first()])
->get();
I don't even need a select, I actually just need ProductUser::where('user_id',$user?->id)->where('product_id','product.id')->exists() but I don't know a method like addSelect for that.
The ProductUser table is defined fine btw, tried ProductUser::where('user_id',$user?->id)->where('product_id','product.id')->exists() with hardcoded product id and that worked as expected.
I tried to create a method on the product model hasBeenBoughtByAuthUser in which I wanted to check if Auth::user() bought the product but Auth wasn't recognized for some reason(and I thought it's not really nice to use Auth in the model anyway so didn't dig super deep with this approach).
$products = Product::query()
->select('id', 'name')
->addSelect(\DB::raw("(EXISTS (SELECT * FROM product_user WHERE product_users.product_id = product.id AND product_users.user_id = " . $user->id . ")) as is_bought_by_auth_user"))
->simplePaginate(40);
For all attempts $user=$request->user().
I don't know if I am missing something easy here but any hints in the right direction would be appreciated(would prefer not to use https://laravel.com/docs/9.x/eloquent-resources but if there is no other option I will try that as well).
Thanks for reading!
This should do,
$id = auth()->user()->id;
$products = Product::select(
'id',
'name',
DB::raw(
'(CASE WHEN EXISTS (
SELECT 1
FROM product_users
WHERE product_users.product_id = products.id
AND product_users.user_id = '.$id.'
) THEN "yes" ELSE "no" END) AS purchased'
)
);
return $products->paginate(10);
the collection will have purchased data which either have yes or no value
EDIT
If you want eloquent way you can try using withExists or withCount
i.e.
withExists the purchased field will have boolean value
$products = Product::select('id', 'name')->withExists(['users as purchased' => function($query) {
$query->where('user_id', auth()->user()->id);
}]);
withCount the purchased field will have count of found relationship rows
$products = Product::select('id', 'name')->withCount(['users as purchased' => function($query) {
$query->where('user_id', auth()->user()->id);
}]);

Query builder proper sintax for 4 joins + 3 where clauses (Laravel5.7)

I'm trying to get this MySQL query to work in laravel 5.7 query builder.
It works fine in phpmyadmin
SELECT c.Symbol
, s.SectorName
, cprs.strenght
, s.parentid
, ssbpi.Risklevel
, ssbpi.ColumnType
FROM Companies AS c
JOIN Sectors AS s ON s.SectorID = c.SectorID
JOIN Company_PriceRS AS cprs ON cprs.CompanyID = c.CompanyID
JOIN SubSectorsBPIsData AS ssbpi ON ssbpi.subcategoryid = s.parentid
WHERE cprs.PostDate = '2017-05-08'
AND WHERE CompanyPriceRS.strenght = 'strong'
AND WHERE SubSectorsBPIsData.ColumnType = $ColumnType
ColumnType is a variable that comes from a dropdown and it's already being captured and working properly.
I have tried the normal way according to documentation:
$Completequerytry1 = DB::table('Companies')
->join('Sectors', 'Sectors.SectorID', '=', 'Companies.SectorID')
->join('CompanyPriceRS', 'CompanyPriceRS.CompanyID', '=', 'Companies.CompanyID')
->$join('SubSectorsBPIsData ', 'SubSectorsBPIsData.subcategoryid', '=', 'Sectors.parentid')
->where('CompanyPriceRS.strenght', '=', 'strong')
->where('SubSectorsBPIsData.ColumnType', '=', $ColumnType)
->where('CompanyPriceRS.Postdate', '=', '2017-05-08');
->select('Companies.Symbol', 'Sectors.SectorName', 'CompanyPriceRS.strenght', 'Sectors.parentid', 'SubSectorsBPIsData.subcategoryid','SubSectorsBPIsData.ColumnType')
->limit(10);
->select('Companies.Symbol', 'Sectors.SectorName', 'CompanyPriceRS.strenght', 'Sectors.parentid', 'SubSectorsBPIsData.subcategoryid','SubSectorsBPIsData.ColumnType')
->limit(10);
echo '<pre>';
print_r($Completequerytry1);
Error:
Symfony\Component\Debug\Exception\FatalThrowableError thrown with message "syntax error, unexpected '->' (T_OBJECT_OPERATOR)"
Using functions With several nested joins:
$Completequerytry1 = DB::table('Companies')
->join('Sectors', function ($join) use ($ColumnType) {
$join->on('Sectors.SectorID', '=', 'Companies.SectorID')
->join('CompanyPriceRS', function ($join2) {
$join2->on('CompanyPriceRS.CompanyID', '=', 'Companies.CompanyID')
->join('SubSectorsBPIsData', function ($join3) {
$join3->on('SubSectorsBPIsData.subcategoryid', '=', 'Sectors.parentid')
->where(function ($query1) {
$query1->where('CompanyPriceRS.strenght', '=', 'strong') //filter 1
->where('SubSectorsBPIsData.ColumnType', '=', $ColumnType) //filter2
->where('CompanyPriceRS.Postdate', '=', '2017-05-08'); // filter 3
});
});
});
})
->select('Companies.Symbol', 'Sectors.SectorName', 'CompanyPriceRS.strenght', 'Sectors.parentid', 'SubSectorsBPIsData.subcategoryid','SubSectorsBPIsData.ColumnType')
->limit(10);
echo '<pre>';
print_r($Completequerytry1);
Error:
ErrorException (E_NOTICE)
Undefined variable: ColumnType
3: Then tried functions with nested WHERE
$Completequerytry1 = DB::table('Companies')
->join('Sectors', 'Sectors.SectorID', '=', 'Companies.SectorID')
->join('CompanyPriceRS', 'CompanyPriceRS.CompanyID', '=', 'Companies.CompanyID')
->$join('SubSectorsBPIsData ', 'SubSectorsBPIsData.subcategoryid', '=', 'Sectors.parentid') //ERROR IS GIVEN ON THIS LINE
->where(function ($query1) {
$query1->where('CompanyPriceRS.strenght', '=', 'strong')
->where('SubSectorsBPIsData.ColumnType', '=', $ColumnType)
->where('CompanyPriceRS.Postdate', '=', '2017-05-08');
});
->select('Companies.Symbol', 'Sectors.SectorName', 'CompanyPriceRS.strenght', 'Sectors.parentid', 'SubSectorsBPIsData.subcategoryid','SubSectorsBPIsData.ColumnType')
->limit(10);
echo '<pre>';
print_r($Completequerytry1);
Error:
Undefined variable: join
Still don't know what i'm missing.
Should i create functions for the JOINs and the WHEREs ?
Running out of ideas. Thanks in advance for your insights :)
It turns out that the query was being sent to a variable directly from the controller, not to the view.
I was doing this only for testing but it was using too much memory with print_r(); function making impossible to get a result. Even when using dd(); i wasn't getting what i wanted (I think it's because some sintax errors i had).
So i passed the final variable to the view and it works fine since laravel could handle the data differently.
Also i used ->limit(10); to split the results and avoid memory overload.
Here is the final code working:
$Completequerytry1 = DB::table('Companies')
->join('Sectors', 'Sectors.SectorID', '=', 'Companies.SectorID')
->join('Company_PriceRS', 'Company_PriceRS.CompanyID', '=', 'Companies.CompanyID')
->join('SubSectorsBPIsData', 'SubSectorsBPIsData.subcategoryid', '=', 'Sectors.parentid')
->select('Sectors.SectorName', 'Companies.Symbol', 'Company_PriceRS.strenght', 'Sectors.parentid', 'SubSectorsBPIsData.Risklevel','SubSectorsBPIsData.ColumnType')
->where('Company_PriceRS.strenght', '=', 'strong')
->where('SubSectorsBPIsData.ColumnType', '=','X')
->where('Company_PriceRS.Postdate', '=', '2017-05-08')
->limit(10)
->get();
return view('besttrades2', array('Completequerytry1' => $Completequerytry1)); //sending my query variable to the view
Then in the view only used:
<?= $Completequerytry1; ?>
or show it in whatever way you want.
Sometimes it's better to have another project only for testing separately.

calculating with values from two different mysql tables

I'm building a sort of human resources application where I have to reduce a variable of a mysql table with a variable of another mysql table.
The CMV I'm using is Laravel so I'm trying to use the DB class as much as possible.
This is the first table, users:
users_table
And the second table, aanvraags:
aanvraags_table
I would like reduce the variable vakantie from the first table with the variable duur from the second table. This would happen right after the vacation request is accepted. There is already a function in my controller to change the variable goedgekeurd from 0 to 1. The function looks like this:
public function updateNieuw($id){
//update aanvraag
$update_aanvraag = DB::table('aanvraags')
->where('id', $id)
->update([
'goedgekeurd' => 1 //approved by the boss
]);
Within that same function I would like to reduce the variable vakantie with the variable duur.
At the moment I already tried a few things like:
$update_vakantiedag = DB::table('aanvraags')
->select('duur')
->where('id', $id)
->get();
$vakantie = DB::table('users')
->join('aanvraags', 'users.id', '=', 'aanvraags.user_id')
->where('aanvraags.id', '=', $id)
->update([
'users.vakantie' => $update_vakantiedag
]);
All of this doesn't get me anywhere. Most of the time I get errors or the value from the variable vakantie from the first table.
It is quite important for the application that the reduction takes place. The variable vakantie displays the remaining vacation days per user after accepting a new request and is displayed in the app.
Any tips or solutions are welcome !
Thank you all in advance !
Use this:
$update_vakantiedag = DB::table('aanvraags')
->select('duur')
->where('id', $id)
->first();
$vakantie = DB::table('users')
->join('aanvraags', 'users.id', '=', 'aanvraags.user_id')
->where('aanvraags.id', '=', $id)
->decrement('users.vakantie', $update_vakantiedag->duur);
#JonasStaudenmeir Thanks a lot ! I changed the function and it works !
$update_vakantiedag = DB::table('aanvraags')
->select('duur')
->where('id', $id)
->first();
$verlof = DB::table('users')
->join('aanvraags', 'users.id', '=', 'aanvraags.user_id')
->where('aanvraags.id', '=', $id)
->first();`
$vakantie = DB::table('users')
->join('aanvraags', 'users.id', '=', 'aanvraags.user_id')
->where('aanvraags.id', '=', $id)
->update([
'users.vakantie' => $verlof->vakantie - $update_vakantiedag->duur
]);
Thank you so much !

Laravel Query Builder - where clause equals anything programmatically

I'm using Laravel 5.6 - Query Builder.
Is it possible to make a query builder where statement that a value equals everything programmatically?
Let's say that I have this code:
$foo = 1;
DB::table('users')
->select('*')
->where('status', '=', $foo)
->get();
If $foo = 1 then it's straightforward. The query will select everything with the status of 1.
Q: Is it possible to assign something to the $foo variable so the select query returns every record regardless of the status from the DB?
Of course, I can make it happen with 2 query statements like this:
$foo = 1;
if ($foo === null) {
DB::table('users')
->select('*')
->get();
} else {
DB::table('users')
->select('*')
->where('status', '=', $foo)
->get();
}
However, I'm looking for a shorter / more effective solution. Is it possible somehow - without using raw code inside the Where statement?
You may try something like this:
$query = DB::table('users')->select('*');
// $foo = 'get it...';
if ($foo) {
$query->where('status', $foo);
}
$result = $query->get();
Or even more laravel-ish:
$result = DB::table('users')->select('*')
->when($foo, function ($query) use ($foo) {
return $query->where('status', $foo);
})
->get();
Check more here.

How add to collection only models with no record joined - Eloquent

In my model Questions I have simple relation to Standpoint
public function standpoints_byrel()
{
// return $this->hasMany('App\Models\Standpoint');
return $this->hasMany('App\Models\Standpoint', 'question_id');
}
Now,
I have yet another model Userattitude (tableuser_attitudes`) which allow users to upvote and downvote Standpoints.
I am able to list Standpoints, which were voted by a given user:
$user_attitudes = Userattitude::join('entitystandpoints', function ($q) use($questionid,$user) {
$q->where('user_attitudes.item_type', '=', 'entitystandpoint');
$q->on('user_attitudes.item_id', '=', 'entitystandpoints.id');
$q->where('entitystandpoints.question_id', '=', $questionid);
$q->where('user_attitudes.creator_id','=', $user);
})
->select('user_attitudes.*')
->get();
TO DO
Now I try to list all standpoints, which were NOT voted by the given user.
I have no idea how to do it using Eloquent.
Any help appreciated.
edit
condition to meet:
if an user votes up or down, a new model Userattitude is created. Therefore Standpoint models not down- or upvoted have nothing to join. still, in the Userattitude there are two fields for upvoting : 'attitude' and 'importance'. often one of them is null
Try with a left join where the left parameter of the join is null.
Something like this (but please check the syntax out, I'm not an Eloquent expert):
$user_attitudes = Userattitude::leftJoin('entitystandpoints', function ($q) use($questionid,$user) {
$q->where('user_attitudes.item_type', '=', 'entitystandpoint');
$q->on('user_attitudes.item_id', '=', 'entitystandpoints.id');
$q->where('entitystandpoints.question_id', '=', $questionid);
$q->where('user_attitudes.creator_id','=', $user);
})
->whereNull('entitystandpoints.id')
->select('user_attitudes.*')
->get();
Let me know.