Can someone explain what these laravel function do - laravel

I was going through my friend's laravel code, and saw some functions like withPost and others, here is the code
public function show($id)
{
$categorylist = Category::all();
$tagfoot = Tag::all();
$post = Post::find($id);
$popularposts= Post::selectRaw("posts.*, count('comments.id') as comments_count")->leftJoin('comments','comments.post_id', '=', 'posts.id')->groupBy('posts.id')->orderBy('comments_count', 'desc')->take(6)->get();
$prev = Post::where('id', '<', $post->id)->orderBy('id', 'desc')->first();;
$next = Post::where('id', '>', $post->id)->orderBy('id', 'desc')->first();
return view('posts.show')->withPost($post)->withTagfoot($tagfoot)->withCategorylist($categorylist)->withPrev($prev)->withNext($next)->withPopularposts($popularposts);
}
What do the withPost, withTagfoot, withCategorylist, withPrev, withNext, withPopularposts functions actually do?

Your mentioned code sends values to the view 'posts.show'.
Another way of sending value could be like the following. Here you can use the compact function of PHP to list the variables.
return view('posts.show', compact('post', 'tagfoot', 'categorylist', 'prev', 'next', 'popularposts'));

Using with keyword before a variable name to make a function is one of the ways you can pass that variable to views in Laravel. There are other ways and all are identical:
return view('posts.show')->withPost($post);
is just same as this:
return view('posts.show', compact('post'));

Related

Query builder didn't find data when using %

I'm trying to use query builder in controller using laravel, and i don't understand but the query didn't find the data.
Here's the code:
public function index()
{
$data = downloads::all();
if(request('searchName')){
$data = $data->where('fileName','like','%'.request('searchName').'%'); //Here's the problem
return view('download', compact('data'));
}
else{
return view('download', compact('data'));
}
}
i already tried dd(request('searchName')) and it display the input that i give, so there's no problem here
when I'm using $data->where('fileName','like','%'.request('searchName').'%') there's no data shown
i don't think that i misspell the fileName because when I'm using $data->where('fileName','like',request('searchName')) and it worked and display the file, but the fileName must be exactly the same as the inputed searchName, and of course what i wanted is not this
even when I'm using dd('%'.request('searchName').'%'); it will display "%*searchName*%" that's why i so confused when it didn't work when I'm using $data->where('fileName','like','%'.request('searchName').'%');
I even using SELECT * FROM *tables* WHERE fileName LIKE '%p%'; in SQL Workbench and it worked perfectly fine
Any suggestion of what should i do? Thank you
This looks odd. Why are you filtering the collection instead of adding the where conditional in your query?
Imagine you have thousands of download records but the where condition just match with a few ones, you will be fetching everything just for showing some of them.
IMO, a better approach should be
public function index(Request $request)
{
$data = downloads::
when($request->has('searchName'), function($query) use ($request){
$query->where('fileName','like','%'.$request->searchName.'%');
})
->get();
return view('download', compact('data'));
}
all() is static method not query builder.If you see internal of all() code then its calling get method
/**
* Get all of the models from the database.
*
* #param array|mixed $columns
* #return \Illuminate\Database\Eloquent\Collection|static[]
*/
public static function all($columns = ['*'])
{
return static::query()->get(
is_array($columns) ? $columns : func_get_args()
);
}
There are few ways to solve this .
public function index()
{
$downloads = downloads::query();
if(!empty(request('searchName'))){
$downloads->where('fileName','like','%'.request('searchName').'%');
}
$data=$downloads->get();
return view('download', compact('data'));
}
or
public function index()
{
$data = downloads::when(!empty(request('searchName')),function($query){
$query->where('fileName','like','%'.request('searchName').'%');
})->get();
return view('download', compact('data'));
}
You are trying to apply your querystring with like in a collection. In a collection, you can use the filter($callback_function) method to select elements in the collection. Pass a callback function that returns true for each element to be returned.
In your case, you can use the stristr() function to emulate a LIKE operator, something like this:
collect($data)->filter(function ($item) use ($searchName) {
return false !== stristr($item->fileName, $searchName);
});

Relationship with paginate

I need to create a dynamic link to take the user to the last page of the laravel page. For example, if there is a pagination, I need to include lastPage () at the end of the url www.site.com/forum/slug?page=2
otherwise it goes to the normal page.
But I need to do this logic on another controller, which in turn is not working. See my relationships and how I'm doing:
public function grupoPerfil($slug) {
$grupo = Grupo::where('slug', $slug)->first();
$comments = Comment::whereHas('relato', function ($query) use ($grupo) {
return $query->where('grupo_id', $grupo->id);
})->paginate(10);
if($grupo){
$rels = $grupo->relatos()->with('user')->paginate(20);
return view('grupo', compact(['grupo', 'rels','comments']));
}
abort(404);
}
my blade:
#foreach($rels->sortByDesc('updated_at') as $r)
<card-relatos
url="{{localized_route('relatoUser', [$r->grupo->slug, $r->slug])}}"
getpaginate="{{ $comments->lastPage() }}"
</card-relatos>
#endforeach
But getpaginate always returns 2, as it is not related to relato_id. How do I solve this?
This is what I have done:
return Product::whereHas('category', function ($query) use ($slug) {
$query->where('slug', $slug);
})->paginate(15);

Use more complex where clauses in Scout

I am a happy user of Laravel Scout.
Now I'd like to extend my search:
$data
= new UserOverviewResourceCollection(User::search($searchphrase)
->currentStatus('active')->orderBy('lastname', 'asc')
->orderBy('firstname', 'asc')
->paginate(config('pagination.length')));
currentStatus comes from https://github.com/spatie/laravel-model-status .
Now I am getting a response, that currentStatus is not supported. I thought I could be a good idea to filter the result of User::search after it has been returned from scout?
Another idea: I'd like to add more complex where clauses:
->where([
[
'starts_on',
'<',
Carbon::now()->toDateTimeString(),
],
[
'ends_on',
'>',
Carbon::now()->toDateTimeString(),
],
])
Maybe you got a better idea?
I really need similar functionality as well but I'm afraid it's not possible at the moment (Laravel 8)
According to the docs; Laravel\Scout\Builder (which is what search() returns) only has a really basic implementation of the where method an can only handle exactly 2 arguments.
Here is the code from the scout package:
/**
* Add a constraint to the search query.
*
* #param string $field
* #param mixed $value
* #return $this
*/
public function where($field, $value)
{
$this->wheres[$field] = $value;
return $this;
}
See https://laravel.com/docs/8.x/scout#where-clauses
Putting the search() behind all regular eloquent builder methods won't work either since search will only be a static function of the model.
Hopefully this will be improved in the future.
You can extend Builder and add currentStatus method to store required status in builder. See example
https://github.com/matchish/laravel-scout-elasticsearch/issues/47#issuecomment-526287359
Then you need implement your own engine and build query using builder there.
Here is example for ElasticSearch engine
https://github.com/matchish/laravel-scout-elasticsearch/blob/06c90914668942b23ffaff7d58af5b9db1901fb1/src/Engines/ElasticSearchEngine.php#L135
Well rewriting it as this should work.
$data
= new UserOverviewResourceCollection(User::search($searchphrase)
->where('starts_on','<',now())
->orderBy('lastname', 'asc')
->orderBy('firstname', 'asc')
->paginate(config('pagination.length')));
Notice that now() is just a global helper function returning current moment Carbon instance. It's just shorter to write, no other reason for using it.
And if you want grouped where queries you do it like this:
$data
= new UserOverviewResourceCollection(User::search($searchphrase)
->where(function($q) {
$q->where('starts_on','<',now())->where('ends_on','>',now())
})
->orderBy('lastname', 'asc')
->orderBy('firstname', 'asc')
->paginate(config('pagination.length')));
And then you should be able to export this to the UserOverviewResourceCollection as a local scope, for example:
public function scopeActive($q) {
return $q->where('starts_on','<',now())->where('ends_on','>',now())
}
and then you can use something like this:
$data
= new UserOverviewResourceCollection(User::search($searchphrase)
->active()
->orderBy('lastname', 'asc')
->orderBy('firstname', 'asc')
I've written this from my head so there might be typos.
$data
= new UserOverviewResourceCollection(User::search($searchphrase)
->currentStatus('active')->orderBy('lastname', 'asc')
->where(function($q){
$query->where('starts_on', '<',Carbon::now()->toDateTimeString());
$query->where('ends_on', '>',Carbon::now()->toDateTimeString());
})
->orderBy('firstname', 'asc')
->paginate(config('pagination.length')));
Try this code. This will satisfy your complex where condition

Property [***] does not exist on this collection instance Laravel eloquent relationship

In my Post Model
public function user()
{
return $this->belongsTo('App\User');
}
And in the User Model
public function posts()
{
return $this->hasMany('App\Post');
}
Now I am trying to get the comments of a specific user
$user= User::where('name', 'like', '%Mat%')->first();
return $user->posts->comment;
But it shows
Property [comment] does not exist on this collection instance.
The user has many posts which therefore returns a collection, you will need to loop over this to get your comments out. I.e.
$user = User::where('name', 'like', '%Mat%')->first();
$user->posts->each(function($post) {
echo $post->comment;
});
See the documentation on Laravel Collections
I think you can try this :
$user= User::with('post')->where('name', 'like', '%Mat%')->get();
$postComment = array();
foreach($user->post as $post){
$postComment = $post->comment;
}
return $postComment;
Hope this help for you !!!
If you want to have all comments you can use the following code:
$comments = [];
$user = User::where('name', 'like', '%Mat%')->with(['post.comment' => function($query) use (&$comments) {
$comments = $query->get();
}])->first();
return $comments;
Property [comment] does not exist on this collection instance.
The above error occurs because the Posts function returns a collection. Now you will have to traverse through each element of the collection.
Since, you are returning $user->posts()->comment, I am assuming you need it in the form of an array and don't have to simply echo them out, one by one. So you can store them all in an array & then process it whatever whay you like.
$comments = array();
$user->posts()->each(function $post){
$comments = $post->comment;
}
return $comments;
For greater insight, into this collection function read:
https://laravel.com/docs/5.4/collections#method-each

laravel 5.2 if else to query database

stuck on a form that allows the user to enter a value into a choice of two fields. I can query the database using one field but want to add more range to database queries. With the following code below when i try to access the page to query it just shows me a white screen.
public function index()
{
$data = $request->all();
if(!empty($data['pstoreNum']))
{
$pstoreNum = $data['pstoreNum'];
$result = DB::table('perfumes')->where('StoreNumber','=',$pstoreNum)
->get();
return view('perfumes',compact('result'));
}
else if(!empty($data['pweekNum']))
{
$pweekNum = $data['pweekNum'];
$result = DB::table('perfumes')->where('WeekNumber','=',$pweekNum)
->get();
return view('perfumes',compact('result'));
}
}
My routes file simple calls the index function. Any help would be appreciated.
You can add query functions within your query like so
public function index(Request $request)
{
$data = $request->all();
$result = \DB::table('perfumes')->where(function($query) use ($data) {
if(!empty($data['pstoreNum'])) {
$query->where('StoreNumber', '=', $data['pstoreNum']);
}
if(!empty($data['pweekNum'])) {
$query->where('WeekNumber', '=', $data['pweekNum']);
}
})->get();
return view('perfumes',compact('result'));
}
You can then use the one query and add multiple wheres on various conditions.
https://laravel.com/docs/5.2/queries#advanced-where-clauses

Resources