Laravel multi condition query - php

I want to search for users previous relations but not sure how to make this logic happen.
Logic
My table has 2 columns from_id to_id (both will get users ids)
I am sending 2 ids to back-end (one as input, another one in request header)
I want to say: whereinput id is from_id and header id is to_idORwhere input id is to_id and header id is from_id` return the result otherwise is null obviously.
Note:
The part that I'm stuck in is and in conditions input id is from_id and header id is to_id OR where input id is to_id and header id is from_id
Code
currently I have half way code which is this:
public function check(Request $request) {
// user id from header request (request sender) e.g `1`
$user = $request->user();
// second user id (not sure where to use it yet) e.g `4`
$request->input('receiverId');
$chat = PrivateChat::where('from_id', $user->id)->orWhere('to_id', $user->id)->first();
}
To make it simple
Basically I want return old chat between the 2 ids regardless of who was sender (from_id) and who was receiver (to_id).
Any idea how to make my logic happen?
Update
this is my full code and it always return false while i do have previous chat between users with id 1 and 4.
public function check(Request $request) {
$user = $request->user();
$chat = PrivateChat::where([['from_id', $user->id],['to_id',$request->input('receiverId')]])
->orWhere([['from_id', $request->input('receiverId')],['to_id',$user->id]])->first();
$receiver = User::where('id', $request->input('receiverId'))->first();
if($chat) {
return response()->json([
'data' => new PrivateChatResource($chat),
'exist' => true,
'receiver' => new UserResource($receiver),
'message' => 'Chat data retrieved successfully.'
]);
} else {
return response()->json([
'exist' => false,
'receiver' => new UserResource($receiver),
'message' => 'Chat data retrieved successfully.'
]);
}
}

As i see it you want to do the boolean logic, if wrong please correct me.
(from_id = header_id AND to_id = header_id) OR (from_id = input_id AND to_id = input_id)
This can be obtained with the following Eloquent query. Using where($cloure) syntax, for doing the boolean logic listed above. Calling where with a closure, adds parenthesis to your logic, everything within the clojure will be wrapped in ().
$user = $request->user();
$userInput = $request->input('receiverId');
PrivateChat::where(function ($query) use ($user) {
$query->where('from_id', $user->id)->orWhere('to_id', $user->id);
})->orWhere(function ($query) use ($userInput) {
$query->where('from_id', $userInput)->orWhere('to_id', $userInput);
})->first();

If i understand correctly your where logic looks like this:
('from_id' = $user->id & 'to_id' = $request->input('receiverId'))
|| ('from_id' = $request->input('receiverId') & 'to_id' = $user->id)
You can define multiple conditions in a single where:
PrivateChat::where([['from_id', $user->id],['to_id',$request->input('receiverId')]])
->orWhere([['from_id', $request->input('receiverId')],['to_id',$user->id]])->first();
->first() will return the first record that meets one of the conditions, but if you want all results you can use ->get().

Related

Laravel - Use conditions when selecting data using controllers

I have the following controller where I try to select all the customers of a user (The ones with 'user_id' equal to the 'id' of the authenticated user). I know how to do it in the following way, but as you can see it is not very efficient since it selects more records than necessary.
public function index() // Http/Controllers/CustomerController.php:17
{
$user_id = Auth::id(); // Get user ID
$customers = Customer::all()->where('user_id', $user_id); // Select all users and then filter by ID
return $this->showAll($customers, 200); // Return JSON response with response code
}
Change your $customers = Customer::all()->where('user_id', $user_id); to:
$customers = Customer::where('user_id', $user_id)->get();
https://laravel.com/docs/7.x/eloquent#retrieving-models

Query in Yi2 and checking a relationship in another table

I am trying to get data in a Yii2 table call Post. This table has an attribute call owner and I want to check whether the value of owner is equal to a particular Value I pass call it userId or the value of owner is equal to the following attribute of the Followship table where the value of the follower attribute of the Followship Table is equal to the the value I pass call it userId.
In implementing the above logically and bit by bit, I have written the following code;
$allpost = Post::find()->all();
$relevantpost = [];
foreach ($allpost as $post) {
if($post->owner == $userId){
$relevantpost[] = $post;
}
else{
$follower = Followship::findOne(['follower'=>$userId, 'following'=>$post->owner]);
if($follower){
$relevantpost[] = $post;
}
}
}
return $relevantpost;
This code works well but I want to write an active query for this such as ;
$allpost = Post::find()
->where(['owner'=>$userId])
->orWhere(['is NOT', $follower = Followship::findOne(['follower'=>$userId]) and 'owner' => $follower->following, NULL])
->all();
or in the worse case,
$allpost = \Yii::$app->db
->createCommand(
"SELECT postId, location, details, created_at FROM Post
WHERE owner = " . $userId. "OR
owner = '0' OR
owner = following IN (
SELECT following FROM Followship WHERE follower = ". $userId . " AND
)
ORDER BY dateCreated DESC"
)
->queryAll();
I keep getting errors with the above queries. I am missing out a fundamental of the Yii2 query builders.
Please any help on this will be greatly appreciated.
First you could make a relation (which connects Post and Followers by post owner) inside your Post class
class Post extends ActiveRecord {
public function getFollowersDataset() {
return $this->hasMany(Followers::className(), ['following' => 'owner']);
}
...
}
And then you can just use it in your queries
Post::find()
->joinWith('followersDataset')
->where(['or',
['owner' => $user_id],
['follower' => $user_id]])
->all()
The condition accept three parameters
[the_condition, the_attribute, the_value]
In case of AND and OR the thing change
[the_condition, first_condition, second_condition]
With the second tried you can make something like that
$allpost = Post::find()
->where(['owner'=>$userId])
->orWhere([
'AND',
['is NOT', $follower, Followship::findOne(['follower'=>$userId]),
['owner', $follower->following, NULL]
])
->all();
You can check in debug bar the querys that you're making, or another way, its to make a mistake in a field, for example if in your where condition you put ->where(['owners'=>$userId]), that trhow an error with the query that you made, so you can see what query you did

Laravel Create OR update related model

I have the following function to create a new related model;
//Create the results entry
$result = new Result([
'result' => $total,
'user_id' => $user->id,
]);
//attach it to the fixture - parse through looking for the user_id or opponent_id
//to match the current user in the loop.
$fixture = LeagueFixture::where('league_id', $league_id)
->where('gameweek', $gameweek)
->where(function($q) use ($user){
$q->where('user_id', $user->id)
->orWhere('opponent_id', $user->id);
})
->first();
$fixture->results()->save($result);
The ->save() at the end does most of the magic, attaching the correct fixture_id to the result table. The problem is that if the function is run again, it creates new entries for the same results.
There is a firstOrCreate() method, but i don't know how to use this when saving a related model.
Thanks
It's exactly like this: http://laravel.com/docs/5.0/eloquent#insert-update-delete.
//Create or find a existing one...
$result = Result::firstOrCreate([
'result' => $total,
'user_id' => $user->id,
]);
//grab fixture...
$fixture = LeagueFixture::where('league_id', $league_id)
->where('gameweek', $gameweek)
->where(function($q) use ($user){
$q->where('user_id', $user->id)
->orWhere('opponent_id', $user->id);
})
->first();
//associate (set fixture_id in $result equals to $fixture's key)
//any previous association will disappear.
$fixture->results()->associate($result);
//save to write changes in the database.
$result->save()
you can check here (https://github.com/laravel/framework/blob/5.0/src/Illuminate/Database/Eloquent/Model.php#L559). Laravel will search in your database and return if it found it or create a new.

Laravel - Friendship

I'm trying to do a friendship system in laravel 5 and I'm stuck.
I have a friends_user table which look like this:
id
user_id
friend_id
status
Here is the point, I go to an user page, and Ii wanna see how is my relation with this user, 4 solutions:
We are friends
We're not
He doesn't have accepted the request yet
I have to confirm or not.
I wanna create a method that checks if a user is friend with an other, simple.
I have a 'status' column which is a boolean (0 for pending and 1 for friends)
The perfect solution for me would be to be able in one method to check if:
The users are friend, so either ('user_id', Auth::user()->id)->and ('friend_id', $friend->id) or the inverse ('user_id', $friend->id)->and ('friend_id', Auth::user()->id), it has to check in the 2 senses
I sent request and have to wait for his answer
I received the request and have to accept it.
We're not friend and so, i can add him.
So if you can tell me where i'm wrong here, here's my logic (just for check if users are friend) : User.php
public function isFriend($slug)
{
// Get both user
$user = Auth::user();
$receiver = User::where('slug', $slug)->first();
// get list of friends (so who have status = 1)
$result = Friends::where('status', 1);
// Get users where user id is equal to connected
$result = $result->where('user_id', $user->id)->where('friend_id', $receiver->id);
$result = $result->orWhere('user_id', $receiver->id)->where('friend_id', $user->id);
$result = $result->get();
if(count($result) == 0)
return false;
return true;
}
After I do these checks in my view.
This works pretty much, but only if i (the current user) has sent the request but if it's the inverse it returns me the user even if status is at 0. I think that my $result erase the other ones isn't it? What's the solution so?
I hope it's clear, and if you can tell me how do this in a clean way, it would be great.
That's a common mistake. Beware of your "orWhere" clause.
public function isFriend($slug)
{
// Get both user
$user = Auth::user();
$receiver = User::where('slug', $slug)->first();
// get list of friends (so who have status = 1)
$result = Friends::where('status',1)->where(function($query) use ($receiver,$user)
{
$query->where([
'user_id' => $user->id,
'friend_id' => $receiver_id
])->orWhere([
'user_id' => $receiver->id,
'friend_id' => $user->id
]);
})->get();
return ! $result->isEmpty();
}

Laravel Join Returning odd values

Just come across a bug on my Join query.
I am echoing out data in a foreach, and showing the username. On other pages it works fine and each username matches the username from the ID in the row. However, in the example below the username return is ALWAYS the name of the logged in user.
Hope the below makes some more sense. Thanks.
The query is:
$query = DB::table('blogs')
->join('followers', 'blogs.id', '=', 'followers.blogid')
->where('followers.userid', Auth::user()->id)
->where('frontpage', '1')
->latest('lastupdated');
This is called via:
Route::get('following', array('before' => 'auth', function()
{
$slug = Route::getCurrentRoute()->uri();
$builds = Blog::findBuilds($slug);
return View::make('pages/home', compact('builds'), array('pageTitle' => 'Builds You Are Following'));
}));
And then on the pages/home I am showing the data like so:
foreach ($builds as $build)
{
$usernameOfOwner = User::usernameFromID($build->userid);
}
And then... the function for getting the username from ID is:
public static function usernameFromID($id) {
$user = DB::table('users')->where('id', $id)->first();
return $user->username;
}
Everywhere else on my website when I run a query similiar to the top one but not a join so e.g.:
$query = static::where('frontpage', '1')->latest('lastupdated');
It works fine, so my only guess is that its down to the Join as thats the only different part of the code.
The problem is that you have multiple columns named userid. followers.userid and blogs.userid. Now in this case, unfortunately followers.userid gets returned when you use $build->userid
You can change that by only selecting the columns you want in your result.
$userid = Auth::user()->id;
$query = DB::table('blogs')
->join('followers', function($q) use ($userid){
$q->on('blogs.id', '=', 'followers.blogid');
$q->where('followers.userid', '=', $userid);
})
->select('blogs.userid', 'other-column')
->where('frontpage', '1')
->latest('lastupdated');
By the way: * works too, so you can do select('blogs.*') if you want

Categories