Search query lost on pagination in laravel - php

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()

Related

PHP MVC LARAVEL

how can I show a array in the view?
Controller:
$users = DB::table('users')
->join('links', 'links.UserId', '=', 'users.UserId')
->select('users.*', 'links.*')
->get();
return view('site.user', ['UserId' => $users]);
I want to do foreach in LINKS, but not in users...
VIEW (users) (WITHOUT foreach):
<h1><?=$user->UserName . ' ' . $user->UserLastName?></h1>
LINKS (foreach):
<li class="white-balloon">
<?=$user->LinkName?>
</li>
First
return view('site.user', ['UserId' => $users]);
should be
return view('site.user', ['users' => $users]);
unless you want to use the variable UserId.
To loop over a variable in blade, use:
#foreach ($users as $user)
<p>This is a link {{ $user->LinkName }}</p>
#endforeach
or in PHP
<?PHP foreach( $users AS $user)
{
echo $user->LinkName;
} ?>
Note: if you have multiple links per user, you should redefine your SQL query. This method gives allot of overhead.
Here a good tutorial about Laravel relationships

Laravel 5.4: Avoid html in the Controllers and DB queries in the blade

I have a problem I can not solve. I have a foreach that prints me an HTML every time it finds value in the database, and it all works.
However, I would like to avoid putting html in the controller.php file.
At the moment I did:
$html_console='';
if($article->id_game > '0'){
$prel_console = \DB::table('info_game')
->where('id_game', '=', $article->id_game)
->get();
foreach($prel_console as $name_console)
{
$name_console_game = \DB::table('console')
->where('id', '=', $name_console->id_console)
->first();
$html_console.='<span class="label">'. $name_console_game->abb_cat.'</span>' ;
}
}
While in the blade:
{!! $html_console !!}
I tried to do this in the blade:
#foreach ($prel_console as $name_console)
<span class="label margin-top-5 font-size-10">{{ $name_console_game->abb_cat }}</span>
#endforeach
If I put the foreach in the blade, how do I deal with the query "name_console_game"
If you have a one to many relation between info_game table which should have a InfoGame model and console table with Console model then your could do something like this:
controller:
public function someMethod()
{
// assuming that you already have an $article object
$infoGame = InfoGame::where('id_game', $article->id_game)->get();
return view('some.view', compact('infoGame'));
}
view location views/some/view/blade.php
#foreach($infoGame->console as $name_console_game)
<span>{{ $name_console_game->abb_cat }}</span>
#endforeach

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).

Laravel 4 : trying to get variable from same page

I'm new to Laravel and I'm getting an error which I think has more to do with logic than anything else but I can't quite seem to grasp how to overcome it.
So, I have a page with a simple form to search for a particular string in my database. But I want to have the result show up on the same page.
Here's what I have so far:
This is my Route.php:
Route::get('/', 'HomeController#index');
Route::post('find', 'HomeController#find');
This is my HomeController:
public function index()
{
return View::make('index');
}
public function search()
{
return View::make('index');
}
public function find()
{
$match = Input::get('find');
if($match) {
$results = Book::where('title', 'like', '%'.$match.'%')
->orWhere('author', 'like', '%'.$match.'%')
->get();
return View::make('index', array('results', $results));
} else {
return Redirect::to('/')->with('flash_error', 'No string added!');
}
}
And my View (index.blade.php):
{{ Form::open(array('url' => 'find', 'method' => 'POST')) }}
{{ Form::text('find', '', array('class' => 'search-query', 'placeholder' => 'Search')) }}
{{ Form::submit('Submit', array('class' => 'btn btn-info')) }}
{{ Form::close() }}
#if (Session::has('flash_error'))
{{ Session::get('flash_error') }}
#endif
#foreach ($results as $result)
{{$result->title}}
#endforeach
(eventually the foreach will be replaced by some ajax loading to display each result)
And the error says "undefined variable: results" and shows the foreach.
I get why that error shows up since on the first pass to this page the results haven't been loaded yet but how can I overcome this? I really want the data to be shown on the same page without having to go to another page to display them.
Like I said, I think this is mostly logic related (although I'm very new to Laravel so it might be that too)
Any help would be greatly appreciated !
you need to pass an associative array as your second param of the make method
return View::make('index', array('results' => $results);
The problem here is that in your use of index.blade.php in multiple controllers, you forgot which controllers provide which variables (and as a result, which variables may be omitted).
When you request / (HomeController#index), index.blade.php is rendered, but since no $results are passed to the view, you see the Undefined Variable warning. This is not a problem in HomeController#find, because you define $results. To combat this, you'll need to do something along the lines of an isset() check on $results before you foreach over it. Like so:
#if(isset($results))
#foreach ($results as $result)
{{$result->title}}
#endforeach
#endif
Your logic may vary based on your page's layout (you might want to add an else and display some alternate placeholder content).
Also, if abstracting the call to View::make() with $results into index_gen() isn't keeping your code DRY, then I'd suggest replacing it in find() with the call to View::make().

Laravel: paginating a fluent query

I'm trying to paginate a page in my view like this:
#foreach($tasks as $task)
{{ $task->user_id }}
{{ $task->client_id }}
{{ $task->description }}
{{ $task->duration }}
{{ link_to_route('clients.show', 'View client', array($task->client_id), array('class' => 'btn btn-primary')) }}
#endforeach
{{ $tasks->links() }}
Using the following query in my controller:
$tasks = DB::table('tasks')
->join('users', 'tasks.user_id', '=', 'users.id')
->join('clients', 'tasks.client_id', '=', 'clients.id')
->select(array('tasks.description', 'tasks.duration', 'tasks.client_id', 'tasks.user_id', 'users.email', 'clients.name'))
->where('tasks.group_id', '=', $usergroup)
->orderBy('tasks.created_at', 'DESC')
->paginate(20);
return View::make('tasks.index', compact('tasks'));
It shows the tasks fine but there's no pagination link showing up so I can't head over to the next batch of 20 results.
Any ideas on how I can make this work?
I've tried #foreach($tasks->result as $task) in my view as suggested in http://forums.laravel.io/viewtopic.php?id=4092 but it gives me an error "Undefined property: Illuminate\Pagination\Paginator::$result"
For those playing at home - I discovered the answer to this:
The compact function is converting the object to an array. Change your return view method to:
return View::make('tasks.index')->with('tasks', $tasks);
And you're in the clear!
Another point - if you're using Bootstrap 3 RC1 like me you'll find that pagination breaks because of the way BS3 styles pagination - if you have that issue head over here for the solution: https://github.com/laravel/laravel/issues/2215
:)

Categories