Database Query Syntax - php

Solution: I used db facade, DB::select() to run raw sql query.
I have two tables users(id, username, city, country) and friends(id, user_id, friend_id, status). The 'users' table stores the user information and 'friends' table store the currently logged in user's id, friend_id is the id of the user who sent a friend request to the current user and status will be 'received'. I want to show information of the users to sent requests to the current user. Is my database query syntax correct? I can see correct output if I don't use the nested subquery. Thanks in advance!
My DB query:
$friendrequests = DB::table('users')->select(['username','city','country'])->where('id',DB::table('friends')->select('friend_id')->where([['status','received'],['user_id',$user->id]]));
My html:
#extends('layouts.master')
#section('title')
Friend Requests
#endsection
#section('content')
#include('includes.message-block')
<section class="row requests">
<div class="col-md-6 col-md-offset-3">
<header><h3>Friend Requests</h3></header>
<div class="requestlist">
<header><h2>You have request from:</h2></header>
#foreach($users as $user)
<p>Name: {{ $user->username }}<br />City: {{ $user->city }}<br />Country:{{ $user->country }}</p>
<div class="interaction">
//stuff here
</div>
#endforeach
Back
</div>
</div>
</section>
#endsection
The route:
Route::get('/friendrequests',[
'uses' => 'FriendController#getFriendRequests',
'as' => 'friendrequests',
'middleware' => 'auth'
]);
The controller (works if I don't use the nested subquery):
public function getFriendRequests()
{
$user = Auth::user();
$friendrequests = DB::table('users')
->select(['username','city','country'])
->where('id',
DB::table('friends')->select('friend_id')->where([['status','received'],['user_id',$user->id]])->get())->get();
return view('friendrequests',['users' => $friendrequests]);
}

You can solve this problem with the approach of "hasManyThrough". In your User's model you should do something like this:
class User extends Model{
//... your code here
public function possibleFriends(){
$this->hasManyThrough(User::class, Friend::class, 'friend_id', 'id')->wherePivot('status', 'received');
}
}
More details in the official docs.

Please try this may be helpful
$friendrequests = DB::table('users')
->select(['username','city','country'])
->whereIn('id', function($query) use($user) {
$query->select('friend_id')
->from('friends')
->where('status', 'received')
->where('user_id', $user->id);
})->get();

Related

Property [X] does not exist on the Eloquent builder instance in laravel 9

I have a basic laravel 9 crud app.
There I have two tables in my db. companies and employees.
I'm trying to display single-user details on my employees.show blade
All my data is displayed correctly but when I try to print user's company, I'm kept getting the following error.
Property [company] does not exist on the Eloquent builder instance.
Following is my employee model
protected $fillable = [
'first_name', 'last_name', 'email', 'phone', 'company_id'
];
public function company()
{
return $this->belongsTo(Company::class);
}
and the following is the show function in my controller
public function show(Employee $employee)
{
$data = Employee::with('company')->where('id', '=', $employee->id);
return view('employees.show', compact('employee','data'));
}
and this is my show.blade
<div class="row mb-4">
<label class="col-sm-2 col-label-form"><b>Company</b></label>
<div class="col-sm-10">
{{ $data->company->name }}
</div>
</div>
How can I display the company properly...
I have company_id as a foreign key in my employees' table...
I have following when I dd $data
You're returning a QueryBuilder from the Employee query in your show() function. You want to add ->get() to return a collection or Employee records:
public function show(Employee $employee)
{
$data = Employee::with('company')->where('id', '=', $employee->id)->get();
return view('employees.show', compact('employee','data'));
}
I think the problem in Query for get data. In employees.show you only show one data then and in controller you got collection of data as array. So your single data element can't access because it is array and for execution you need to add foreach loop for that.
Here you need to change query method from get() to first() and it will resolve your issue.
Your show function code looks like this
public function show(Employee $employee)
{
$data = Employee::with('company')->where('id', '=', $employee->id)->first();
return view('employees.show', compact('employee','data'));
}
Your employees.show blade looks like this
<div class="row mb-4">
<label class="col-sm-2 col-label-form"><b>Company</b></label>
<div class="col-sm-10">
{{ $data->company->name }}
</div>
</div>

select id from post table where title=$title

i have post table and i have comment table i have made them with laravel
i made a IndexController and it has a method that returns all of my posts by their title;
i also return and compact comment of each post and show them under each post content but i have to pass the post id to comment table by myself
for example i have a post with id=7 and i have to pass the 7 to post_id column of comment table
i have to write a query something like this
select id from posts where title=$title
with this query i want to select post id by post title and pass it to post_id in my comment table
this my index controller
public function single($title)
{
$posts = Post::where('title', $title)->get();
$comments = Comment::where([
['post_id', 7],
['verify',1]
])->orderBy('id', 'desc')->get();
return view('main.single', compact('posts', 'comments'));
}
this is comment controller
public function store(Request $request)
{
Comment::create([
'post_id' => $request['post_id'],
'user_id' => Auth::user()->id,
'message' => $request['message'],
]);
}
and also this my single blade file code
#foreach($comments as $comment)
<div class="container">
<div class="bg-secondary bg-opacity-10 p-3 mb-4">
<div>
<p class="fw-bold">{{$comment->user->first_name.' '.$comment->user->last_name}}
<br>
<span class="text-muted text-small-14 fw-light">{{$comment->created_at}}</span>
</p>
</div>
<div class="mt-0">
</div>
<div>
{{$comment->message}}
</div>
</div>
</div>
#endforeach
and also i use laravel 8
You can do the following if you don't want to pass by yourself, assuming your relationships are correct. If not, feel free to include them in your current question, and I can help with those too.
public function single($title)
{
$post = Post::with(['comments' => function ($query) {
$query->where('verify', 1)->orderBy('id', 'desc');
}])->where('title', $title)->first();
return view('main.single', compact('post'));
}
This will allow you to pass just a post to your blade view.
Now instead of
#foreach($comments as $comment)
You can
#foreach($post->comments as $comment)

Routing with parameters in laravel 5

I've got a results page for my website that outputs a list of users.
#extends('templates.default')
#section('content')
<h3>Results for "{{ Request::input('query') }}"</h3>
#if (!$users->count())
<p>No results found, sorry.</p>
#else
<div class="resultRow">
<div class="">
#foreach ($users as $user)
#include('user/partials/userblock')
#endforeach
{!! $users->appends(Request::except('page'))->render() !!}
</div>
</div>
#endif
#stop
with a fairly standard search controller:
class SearchController extends Controller {
public function getResults(Request $request) {
$query = $request->input('query');
$users = User::where(DB::raw("CONCAT(first_name, ' ', last_name)"), 'LIKE', "%{$query}%")->where('role', '=', 2)
->orWhere('username', 'LIKE', "%{$query}%")->where('role', '=', 2)
->orWhere('profile_text', 'LIKE', "%{$query}%")->where('role', '=', 2)
->orWhere('keywords', 'LIKE', "%{$query}%")->where('role', '=', 2)
->orWhere('tagline', 'LIKE', "%{$query}%")->where('role', '=', 2)
->simplePaginate(1);
return view('search.results')->with('users', $users);
}
}
Now, this works fine and well. If I search for "Jack", I get all the Jacks.
What I want to know now is, would it be possible to have a route with a predefined parameter or query string?
For example, say, on my front page I had a link to all the plumbers in my users.
<a id="plumbers" href="{{ route('search.results')->withQueryOfPlumbers }}">Plumbers</a></li>
Would this be possible? Or should I be outputting my data another way?
If you are just using GET parameters, the route() helper allows you to pass parameters as a second parameter such as: route('search.results', ['user-type, => 'plumbers'])
This will output: http://www.example.com/search/results?user-type=plumbers
You can add a column to your User called profession, then you'd do something like this:
$plumbers = User::where(['profession'=>'plumber', /*other WHERE options*/])->get();
This will return all of the users that are plumbers.
If you're hard coding the id and text of the a link, then you could just do
<a id="plumbers" href="{{ route('search.results') }}/plumbers">Plumbers</a>
And then match the keyword of plumbers in your routing table, see Laravel docs on routing parameters for more info.
Your route would look something like this:
Route::get('/search/{trade?}', ['uses' =>'SearchController#getResults', 'as' => 'search.results']);
You should be able to then inject the $trade variable into your controller. A small aside, I would avoid using raw queries in controllers as much as possible from a design and maintenance perspective and make a "search" helper function in your Eloquent model for users (See Eloquent query scopes).

Search query lost on pagination in laravel

I'm quite new to laravel and backend stuff altogether so this might be a newb question!
My website has a search engine which is used to look up users.
Right now I'm using a pretty simple search controller, below is the code.
class SearchController extends Controller {
public function getResults(Request $request) {
$query = $request->input('query');
if (!$query) {
return redirect()->route('home');
}
$users = User::where(DB::raw("CONCAT(first_name, ' ', last_name)"), 'LIKE', "%{$query}%")->where('role', '=', 2)
->orWhere('username', 'LIKE', "%{$query}%")->where('role', '=', 2)
->orWhere('profile_text', 'LIKE', "%{$query}%")->where('role', '=', 2)
->orWhere('keywords', 'LIKE', "%{$query}%")->where('role', '=', 2)
->simplePaginate(1);
return view('search.results')->with('users', $users);
}
}
And the results page:
#extends('templates.default')
#section('content')
<h3>Results for "{{ Request::input('query') }}"</h3>
#if (!$users->count())
<p>No results found, sorry.</p>
#else
<div class="resultRow">
<div class="">
#foreach ($users as $user)
{{ $user->username }}
#endforeach
{!! $users->render() !!}
</div>
</div>
#endif
#stop
So if I were to search "John", I'd get the result of all the Johns, with the URL being http://localhost/search?query=John .
However, if I were to click on the next page of results (http://localhost/search?page=2), the query is lost, so my search controller just sends me back to my home page.
How do I keep the query through pagination?
EDIT: I'm pretty sure my problem is that it's going through the search controller once again after it click on page 2, but I have no idea how I would fix that.
Switched
{!! $users->render() !!}
with
{!! $users->appends(Request::except('page'))->render() !!}
Works like a charm. Credit goes to : Laravel 5 route pagination url encoding issue (unrelated issue)
in your getResult function, pass a $query variable to the view
return view('search.results', ['users' => $users, 'query' => $query]);
Then in your view, appends the query or other variables you need
{{ $users->appends(['query' => $query])->links() }}
you can check more in laravel docs
You can use paginate the following way.
$users->withQueryString()->links()

How to manipulate an object in laravel

I have a laravel query as the one below:
$campaign = Campaign::with(array('tracks.flights' => function($q) use ($dates)
{
$q->whereRaw("flights.start_date BETWEEN '". $dates['start']."' AND '".$dates['end']."'")->orderBy('start_date')
->with('asset')
->with('comments');
}
))
->with('tracks.group')
->with('tracks.media')
->orderBy('created_at', 'desc')
->find($id);
I am very new to laravel and right now the response from this query returns all the data required including the comments with the comments attributes from the DB.
What i want to achieve is manipulate the comments object so it includes the user name from the users table as the comments table has the user_id only as an attribute.
How can I achieve this? I am very new to laravel.
Your Comment model must have a relationship with the User model, such as:
public function user()
{
return $this->belongsTo('App\User');
}
Now when you are iterating comments you are able to do $comment->user->name or in your case it will be something like this:
#if(!$campaign->tracks->flights->isEmpty())
#foreach($campaign->tracks->flights as $flight)
#if(!$flight->comments->isEmpty())
#foreach($flight->comments as $comment)
{!! $comment->user->name !!}
#endforeach
#endif
#endforeach
#endif
Once you can do this, next step is to understand eager load with eloquent.

Categories