I built a laravel 5 application and now I am testing how it handles different inputs. Thus I encountered a weird problem. In the header I have a search field. It returns results, paginated by 10.
The problem
If a user inputs a letter, for an example "e" in English, everything works just fine. However, when a user enters a letter, for an example "e" in Bulgarian - the first page of the results is shown correctly and when a user hits page 2 the query in the search from "е" in Bulgarian changes to "%D0%B5" and no more results are shown. Here is an actual link to the website. http://podobri.eu
I guess this has something to do with the encoding but I can't see what I am doing wrong.
Here is the actual code
Route
Route::get('/search', [
'uses' => '\Podobri\Http\Controllers\SearchController#getResults',
'as'=>'search.results',
]);
SearchController
public function getResults(Request $request){
$query = $request->input('query');
$comments = Comment::where(function($query){
return $query;
})->orderBy('created_at', 'desc')->get();
if(!$query || $query==''){
return view('problems.index')->with('comments', $comments);
}
$problems = Problem::where(DB::raw("CONCAT(problem_title, ' ', problem_description)"), 'LIKE', "%$query%")
->orWhere('location', 'LIKE', "%$query%")
->orWhere('category', 'LIKE', "%$query%")
->orderBy('created_at', 'desc')->paginate(10);
Carbon::setLocale('bg');
return view('search.results')
->with('comments', $comments)
->with('problems', $problems)
->with('title', 'Резултати за "'."$query".'" | Подобри')
->with('description', 'Резултати за "'."$query".'" в системата на Подобри');
}
View
#foreach($problems as $problem)
<div>
#include('problems.partials.problemblock')
</div>
#endforeach
<!-- Paginating-->
{!! $problems->appends(Request::except('page'))->render() !!}
Search form
<form action="{{ route('search.results') }}" role="search" class="navbar-form navbar-left head-form-responsive">
<div class="form-group">
<input type="text" required id='searchQuery' title="Търсете за проблеми" value="{{ Request::input('query') }}" name="query" class="form-control"
placeholder="Търсете за проблеми"/>
</div>
<button type="submit" id='searchBtn' class="btn btn-default">Търсете</button>
</form>
It looks to me like your issue is happening because the paginator is appending a trailing slash with some odd redirect (not sure if you guys are using custom htaccess). Example, if you search for e, this is the URL:
http://podobri.eu/search?query=e
However, the URL for the second page is this:
http://podobri.eu/search/?query=e&page=2
Notice the slash in front of ?query. If you remove the slash, it works. So, how can you fix this?
This was actually fixed a few months ago. You can see this commit here: https://github.com/laravel/framework/commit/806fb79f6e06f794349aab5296904bc2ebe53963
So, if you are using L5.1 or 5.2, you can run composer update, and it'll fix itself. However, if you are using 5.0, it seems like it still has this bug so you can use the setPath method and try this instead:
{!! $problems->setPath('')->appends(Request::except('page'))->render() !!}
I had a similar problem and my solution was changed the method of the route.
Route::post('uri', 'Controller#function')
->name ('view.function');
for:
Route::any('uri', 'Controller#function')
->name ('view.function');
It's works for me.
Regards and good luck.
Related
Before question , This is my code
Show.blade.php
#foreach ($comments as $comment)
#if ($comment->post_id == $post->id)
.....
<form action="{{ route('createreply', ['rid' => $comment->id]) }}" method="POST">
#csrf
<input type="text" class="form-control" name="replyContent" id="replyContent" style="color:white" />
<button type=" submit" style=" color :lavender " class="btn btn-secondary">comment</button>
</form>
....
#endif
#endforeach
(( comment is original comment, and i made reply for answer of comment ))
web.php (route)
Route::post('/replycreate', [CommentController::class, 'createReply'])->name('createreply');
my controller (comment)
public function createReply(Request $request, $rid)
{
$reply = new Reply();
$reply->replyContent = $request->replyContent;
$reply->user_name = Auth::user()->name;
$reply->comment_id = $rid;
dd($reply);
$reply->save();
return redirect()->back();
}
I have problem with making re-reply,
and my code returns error and it says
Too few arguments to function App\Http\Controllers\CommentController::createReply(), 1 passed in C:\Users\ALSACE\post-app\vendor\laravel\framework\src\Illuminate\Routing\Controller.php on line 54 and exactly 2 expected
I tought i had used two argument , but this kind of error occurs.
so i tought using dd($reply),
dd() can't even complete.
you can guess $rid is empty .. but in the same Show.blade.php , I had used $comment with no problem so i think i can not be problem.
plz help with newbe Laravel student!!
Your createReply method expect 2 arguments, BUT you don't have variable in your route.
You must change the route to:
Route::post('/replycreate/{rid}', [CommentController::class, 'createReply'])->name('createreply');
You forgot to add the id to the route itself. If you're going to require it in the function parameters, then it needs to be added on the route URL.
Route::post('/replycreate/{rid}', [CommentController::class, 'createReply'])->name('createreply');
I am working on a laravel project, where I get data from an API then I want to display it on pages. I want the return to be spread out across 4 pages, each page with 10 results each. What I have so far, seems like it should work, but I am missing one piece, so any advice and help would be appreciated. So this is how it is suppose to work with code:
1) The users types in a book title in a search box.
<form method=POST action='/search'>
#csrf
<input type="text" name="search_term"/>
<input type="submit" value="Search"/>
</form>
2) there input is then sent to my controller, which queries the google books api.
class search extends Controller {
public function search(){
$current_page = LengthAwarePaginator::resolveCurrentPage();
echo $current_page;
$term = request('search_term');
$term = str_replace(' ', '_', $term);
$client = new \Google_Client();
$service = new \Google_Service_Books($client);
$params = array('maxResults'=>40);
$results = $service->volumes->listVolumes($term,$params);
$book_collection = collect($results);
$current_book_page = $book_collection->slice(($current_page-1)*10,10)->all();
$books_to_show = new LengthAwarePaginator($current_book_page,count($book_collection),10,$current_page);
return view('library.search')->with(compact('books_to_show'));
}
}
3) the results are then displayed on my blade
#extends('home')
#section('content')
#foreach($books_to_show as $entries)
<div class="row">
<div class="col-sm-auto">
<img class="w-50 img-thumbnail" src={{$entries['volumeInfo']['imageLinks']['smallThumbnail']}}/>
</div>
<div class="col-sm">
{{$entries['volumeInfo']['title']}}<br/>
#if($entries['volumeInfo']['authors']!=null)
by:
#foreach($entries['volumeInfo']['authors'] as $authors)
{{$authors}}
#endforeach
#endif
</div>
</div>
#endforeach
{{$books_to_show->links()}}
#endsection
This all works fine and as expected. I get 10 results on the view, and then I have a bar at the bottom which give shows me 4 different pages to choose from.
When I first type in a search term such as "William Shakespeare" My page url is:
localhost:8000/search
But, when I click on any of the pages my url becomes:
http://localhost:8000/?page=2
I understand that the ?page=* is how the pagination determines which page you are viewing, and that should be sent back to the controller. But, I am missing something on sending it back to the controller I think.
Still kind of fresh to this, so any advice is more then greatly appreciated.
LengthAwarePaginator accepts a 5th parameter in its constructor: an array of options.
the path option
$books_to_show = new LengthAwarePaginator($current_book_page, count($book_collection), 10, $current_page, [
// This will fix the path of the pagination links
'path' => LengthAwarePaginator::resolveCurrentPath()
]);
By the way, on a totally different matter, Laravel makes your life easier by slicing the collection for you, check it out:
$current_book_page = $book_collection->forPage($current_page, 10);
Hope it helps :)
in my show method in laravel i have a form that i want to submit and show the result on the same page so here is my show method first of all :
public function show(Property $property)
{
$property = Property::with('propertycalendars')->where('id', $property->id)->first();
foreach ($property->propertycalendars as $prop) {
$end_reserve = $prop->reserve_end;
}
// HERE NEW RELATION
$pdate = Property::with('dates')->get();
return view('users.properties.show', compact('property','pdate','end_reserve'));
}
and in the view of my show which for example is the url of a uniq property like below just as an example :
http://localhost:8000/properties/1
now i have a form to submit to search the Date table and bring me the dates so here is what i have wrote for the search function :
public function search (Request $request,$property_id){
//Send an empty variable to the view, unless the if logic below changes, then it'll send a proper variable to the view.
$results = null;
//Runs only if the search has something in it.
if (!empty($request->property_id)) {
$start_date = $request->start_date;
$search_date = Date::all()->where('date',$start_date);
}
return view('admin.properties.show')->with('search_date', $search_date);
}
and
thats my route :
Route::get('/properties/{{property_id}}','PropertyController#search');
and finally my form to submit the search :
<form action="/properties/search" method="get">
{{csrf_field()}}
<div class="row">
<div class="col-lg-5">
<input type="hidden" value="{{$property->id}}" name="property_id">
<input name="start_date" class="form-control m-input start_date" autocomplete="off"> </div>
<div class="col-lg-5">
<input name="finish_date" class="form-control m-input start_date" autocomplete="off"> </div>
<div class="col-lg-2">
<input type="submit" value="seach" class="btn btn-primary btn-block" autocomplete="off">
</div>
</div>
</form>
but now when i submit the form it returns a 404 not found with a link like below :
http://localhost:8000/properties/search?_token=R8ncSBjeZANMHlWMcbC6o5mYJZfwWgdfTwuviFo1&property_id=1&start_date=1398%2F1%2F12&title=
In your controller, change to the following:
public function search (Request $request){
//Send an empty variable to the view, unless the if logic below changes, then it'll send a proper variable to the view.
$results = null;
//Runs only if the search has something in it.
if (!empty($request->title)) {
$results = Property::all()->where('some search here')->get();
}
return view('admin.article.index')->with('results', $results);
}
This will send any (and all) results that your query finds to the view. Now in your view, you'll need to ensure there are actual results, or you'll get an error, so for example:
#if ($results)
//There are results, loop through them
#foeach($results as $item)
{{$item->title}}
#endforeach
#else
//There are no results, show the form maybe?
#endif
Without knowing your table structure, I can't give the exact way to loop through your results, but this should get you started.
Edit: Since OP's question nature changed a fair bit from the original question:
In order to achieve the new flow, you'd need to pass in a URL param in the route, and change it to be a get, since you're no longer posting it from a form:
Route::get('/properties/{search}','PropertyController#search');
This tells Laravel you've got something coming from a website.com/properties/xxxxx request - the xxxxx would contain the search key you'd then pass to your controller to lookup. The {search} portion in the route can be whatever name you want, just ensure the controller's second param matches it.
If you wanted to allow for a posting from your search form, you can (in addition) add the following to your routes:
Route::post('/properties','PropertyController#search');
Then in your controller, fetch whatever came from the form via the Request facade.
Then in your controller, you'd check if this is valid:
public function search (Request $request, $search){
//Send an empty variable to the view, unless the if logic below changes, then it'll send a proper variable to the view.
$results = null;
//Runs only if the second URL param has a value
if (!empty($search)) {
$results = Property::all()->where('some search here')->get();
}
return view('admin.article.index')->with('results', $results);
}
my problem exactly smiliar with this one cant't query json data in laravel 5.2
Already try to implement the right answer from it but still, no luck.
I don't know why....
Previous, i found this Laravel 5.2 Codeception functional test issue with PUT / PATCH requests too, already try to use suggestion from him, but no luck too.
Here's my Laravel Controller
public function update(Request $request, $id)
{
$phonebook = Phonebook::findOrFail($id);
$phonebook->update($request->all());
// even i try this
// Phonebook::findOrFail($id)->update($request->all());
// return Response::json() or return response()->json();
// No luck
}
My function in vue script for update data
editContact: function(id)
{
this.edit = true
var contactid = this.newContact.ID
this.$http.patch('/api/contact/' + contactid, this.newContact, function (data) {
console.log(data)
})
},
Change my vue script to be like the right answer from question above, same result. No effect.
And my button to do edit like this
<form action="#" #submit.prevent="addNewContact">
<div class="form-group">
<label for="contactName">Name : </label>
<input type="text" v-model="newContact.CONTACTNAME" class="form-control" id="contactName">
</div>
<div class="form-group">
<label for="phoneNumber">Phone number : </label>
<input type="text" v-model="newContact.PHONENUMBER" class="form-control" id="phoneNumber">
</div>
<div class="form-group">
<button class="btn btn-primary btn-sm" type="submit" v-if="!edit">Add new Contact</button>
<button class="btn btn-primary btn-sm" type="submit" v-if="edit" #click="editContact(newContact.ID)">Edit Contact</button>
</div>
</form>
Note :
My route file using resource or manual route always same
Route::resource('/api/contact/', 'PhonebookController');
or
patch('/api/contact/{id}', ['uses' => 'PhoneboookController#update']);
And then, there something strange.
(Maybe i am wrong) there no issue or error if we look the detail. But, if we change to response tab the result was empty
After all that process, nothing happen with the data.
CONTACTNAME should be "Mizukiaaaaaaaa" like first screenshot instead of "Mizuki"
Am I missing something??
Any advise?
Thanks
As I suggested to you, try to invert the params in your update method in your controller.
And to get a response, you have to send it back (with code 200, 400, 401, whatever you want).
public function update($id, Request $request)
{
$phonebook = Phonebook::findOrFail($id);
$phonebook->update($request->all());
// your treatment
return Response::json([
'param' => 'value'
], 200);
}
If you want to debug and see it in you response, you can make a dd('debug')in your method, you'll see it in the Ajax request response.
That should work for you !
After browsing and ask so much people about this, finally found it! There's nothing wrong with the request or response. My mistakes are mutator update that i used and my model.
Updated answer
Reason answered here and then I just changed update function on controller. Here the result
public function update(Phonebook $phonebook, Request $request, $id)
{
// You can add any fields that you won't updated, usually primary key
$input = $request->except(['ID']);
// Update query
$saveToDatabase = $phonebook->where('ID', '=', $id)->update($input);
return $saveToDatabase;
}
My previous answer updated all fields including the primary key, somehow it successful update data, but it leave error for sure (duplicate primary key). The query looks like UPDATE SET field = 'value' without condition.
This case is for model that doesn't have any relation with other models (tables), or the model act as master.
I'm having some trouble implementing pagination in Laravel 5. Though probably not what you would think.
I can get everything to work but can't understand how to get it to pull the correct information on the second page.
Here is what I have:
Routes:
Route::resource('find-a-wp-theme', 'searchController');
Controller:
public function store(){
$themes['themes'] = Fulls::where("tags", "like", "%".$_POST['theme']."%")->orwhere("tags", "like", "%".$_POST['free']."%")->orwhere("title", "like", "%".$_POST['free']."%")->paginate(12);
return view('find-a-wp-theme', $themes);
}
View:
#if($themes)
#foreach($themes as $theme)
{{$theme['title']}}<br />
<img style="width:250px;" src="{{$theme['image']}}"><br />
#endforeach
{!! $themes->render() !!}
#endif
Up till here everything works just fine. My problem is that when I click the paginating button it takes me to mypage?page=2 which actually takes me to the resource index() and I can't understand how to implement this correctly.
Any help would be much appreciated!
Look at append in the docs. http://laravel.com/docs/5.0/pagination
If your trying to pass variables in your URL you need to use appends().
<?php echo $users->appends(['sort' => 'votes'])->render(); ?>