Best way to search function in symfony 2 - php

I have a search function on my website implemented with elasticsearch.
Now I have a little question about design.
I have a searchAction with route /search that takes a parameter in the query string. Like /search?terms=....
I would like to make the results list filterable, but I have some doubts about the right design to achieve this.
What is the best solution to make a list of filtered results?
If I pass the filter parameter I need to specify a form action with the current url and append the current query string like a link, right?
Example:
<form action="{{ current_pat }} ~ {{ query_string }}" method="post">
<input type="checkbox" name="filter_one">....
In this case the url will like: /search?terms=... and in $post I have the filter. Is this the right solution, or is a list of links better?
Example:
<ul>
<li><a href="{{current_path}} ~ {{ query_string }} ~ {{ this_filter }}">...
<li><a href="{{current_path}} ~ {{ query_string }} ~ {{ this_another_filter }}">
...
In this case the url will be like: /search?terms=...&this_filter=...
In the form case with the get parameter and post filter I need to take both type of parameters in the search action. Is this good?
Instead the link will now have all parameters in the $get request, but I don't like to build the url with query strings in the template.
What's the best way?

Use KNP paginator bundle with search action. On search form make the post action to your searchAction in Controller and after sorting data with matching criteria, re-render the page.
public function searchAction(Request $request,array $arguments = array())
{
$em = $this->getDoctrine()->getManager();
$paginator = $this->get('knp_paginator');
$parameter = $request->get('board_search');
$boardRepo = $this->getDoctrine()->getRepository('PNCMISDashboardBundle:ExaminationBoards')->loadBoardByName($parameter);
$boards = $paginator->paginate($boardRepo, $this->get('request')->query->get('page', 1), 10);
return $this->render('PNCMISDashboardBundle:ExaminationBoards/CRUD:index.html.twig', array(
'boards'=> $boards,
)
);
}
public function loadBoardByName($name)
{
$q = $this
->createQueryBuilder('boards')
->where('upper(boards.name) LIKE upper(:search)')
->setParameter('search', '%'.$name.'%')
->getQuery()
;
try {
// The Query::getSingleResult() method throws an exception
// if there is no record matching the criteria.
$user = $q->getResult();
} catch (NoResultException $e) {
throw new UsernameNotFoundException(sprintf('Unable to find an board identified by "%s".', $name), null, 0, $e);
}
return $user;
}

I prefer to have all the parameters in the query string which will allow the user to bookmark the url or send it in an email.

It depends.
1 If you don't need to index (SEO for instance - google bot) the filtered results page, in my opinion you should use AJAX to achieve this.
Routing:
search_result:
pattern: /search
defaults: { _controller: AcmeExampleBundle:Ajax:searchResult }
requirements:
_method: POST
JavaScript (pseudo Code)
filterResults() {
var queryString = $('input#toSearch').val();
var filters = new Object();
filters['someKey'] = someVal;
$.post('/search', {filters: filters, queryString: queryString}, function(data) {
$('#resultList').html(data);
});)
}
Of course, you should not harcode url '/search'.
Controller:
// src/Acme/ExampleBundle/Controller/AjaxController.php
// ...
public function searchResultAction()
{
$filters = $this->getRequest()->get('filters', array());
$searchObject = new searchObj();
// or smt like $this->get('service_name'); if you use search object as service
// you can also use entity manager
$searchObject->setQueryString($this->getRequest()->get('queryString'));
$searchObject->setFilters($filters);
return $this->render('AcmeExampleBundle:Ajax:searchResult.html.twig', array(
'records' => $searchObject->getResults()
));
}
Of course you can return json response, but in my opinion, return ready to inject part of template is simplest to manage
And View:
{% for record in records %}
<div class="record">{{ record.title }}</div>
{% endfor %}
2 If you wanna index filtred results page you should use user-friendly URLs instead AJAX methods
Routing:
search_result:
pattern: /search/{queryString}/{make}/{model}
defaults: { _controller: AcmeExampleBundle:Ajax:searchResult }
requirements:
_method: GET
Controller:
// src/Acme/ExampleBundle/Controller/AjaxController.php
// ...
public function searchResultAction($queryString, $make, $model)
{
$filters = array('make' => $make, 'model' => $model);
$searchObject = new searchObj();
// or smt like $this->get('service_name'); if you use search object as service
// you can also use entity manager
$searchObject->setQueryString($queryString);
$searchObject->setFilters($filters);
return $this->render('AcmeExampleBundle:Ajax:searchResult.html.twig', array(
'records' => $searchObject->getResults()
));
}

Related

How to select an id in route pass it into the controller and fetch data against that id and redirect it view again in laravel 5.6

How to pass id from veiw into controller in then into another view again??
First of all this a basic question you should be able to search it anywhere on the internet. any how below is the solution.
web/routes.php:
Route::get('user/{id}','USerController#find')->name('user.get');
Or by passing user object in the route:
Route::get('user/{user}','USerController#find')->name('user.get');
UserController:
the below function accepts user object as a parameter in the route we defined above.
public function find(user $user)
{
return view('user.detail',compact('user'))
}
or
public function find($id)
{
$user = USer::find($id);
return view('user.detail',compact('user'))
}
resources/view/user/detail.blade.php:
{{ $user -> name }}
{{ $user -> email }}
and in order visit the route user.find use the below line:
View Detail
No you can use this code as reference to your project.
first solution is .
change route
Route::get('/show_vedio/{$id}', 'VedioController#show')->name(show_videos);
and use this {{ route('show_vedios', $vedio->id )}} in href
it's not entirely clear what you are trying to do, maybe i will help you:
public function show(int $id): View
{
$video = Video::find($id);
return view('video.show', ['video' => $video]);
}

symfony2 render controller with get parameters

How to render a controller with get parameters in twig?
{{ render(controller('AutoBundle:MyController:main', { 'id': id, 'active': true } )) }}
to call controller like this: https://example.com/users/323?active=true
In accordion with the doc the query argument is the third parameters.
{{ controller(controller, attributes, query) }}
So try this:
{{ render(controller('AutoBundle:MyController:main', {}, { 'id': id, 'active': true } )) }}
Hope this help
Yes, it doesn't send the parameters as a GET request, but seems to call the method directly.
Twig template part:
<div id="question-choose-semester">
{{ render(controller('UnswCamsBundle:Semester:choiceAjax', { 'redirect': path(app.request.attributes.get('_route'), app.request.attributes.get('_route_params'))} )) }}
</div>
Create an optional parameter. If using annotations to define the route, you don't have to add it to the annotation specification.
public function choiceAjaxAction($redirect = "", Request $request) {
Then check the GET parameter:
if (empty($redirect)) {
$redirect_uri = $request->query->get('Redirect');
} else {

pass multiple parameters to controller from route in laravel5

I want to pass multiple parameters from route to controller in laravel5.
ie,My route is ,
Route::get('quotations/pdf/{id}/{is_print}', 'QuotationController#generatePDF');
and My controller is,
public function generatePDF($id, $is_print = false) {
$data = array(
'invoice' => Invoice::findOrFail($id),
'company' => Company::firstOrFail()
);
$html = view('pdf_view.invoice', $data)->render();
if ($is_print) {
return $this->pdf->load($html)->show();
}
$this->pdf->filename($data['invoice']->invoice_number . ".pdf");
return $this->pdf->load($html)->download();
}
If user want to download PDF, the URL will be like this,
/invoices/pdf/26
If user want to print the PDF,the URL will be like this,
/invoices/pdf/26/print or /invoices/print/26
How it is possibly in laravel5?
First, the url in your route or in your example is invalid, in one place you use quotations and in the other invoices
Usually you don't want to duplicate urls to the same action but if you really need it, you need to create extra route:
Route::get('invoices/print/{id}', 'QuotationController#generatePDF2');
and add new method in your controller
public function generatePDF2($id) {
return $this->generatePDF($id, true);
}

Configure Symfony Route to match database fields

I'm new to Symfony2 and am learning by making a concert finder application.
Currently I have a couple of yaml routes:
london_hello_bands:
path: /hello/{band}
defaults: { _controller: LondonHelloBundle:Hello:band }
london_hello_multiple:
path: /hello/{venue}/{band}
defaults: { _controller: LondonHelloBundle:Hello:more }
These are mapped to the following Actions within my HelloController:
public function bandAction($band)
{
$repository = $this->getDoctrine()
->getRepository('LondonHelloBundle:Gig');
$bandinfo = $repository->findByArtist($band);
return $this->render(
'LondonHelloBundle:Hello:band.html.twig',
array('band'=>$bandinfo)
);
}
public function moreAction($venue, $band)
{
$repository = $this->getDoctrine()
->getRepository('LondonHelloBundle:Gig');
$venueinfo = $repository->findBy(
array('venueName'=>$venue, 'artist'=>$band)
);
return $this->render(
'LondonHelloBundle:Hello:venue.html.twig',
array('venues'=>$venueinfo)
);
}
This seems to all work fine and I can use Doctrine to pull out all the info about a band from the database at /hello/blur (for example) and I can show all the info about a particular band at a particular venue at hello/02/blur (for example - 02 is the name of an arena in the UK).
However I also want to be able to show all the bands playing a particular venue at a URL like hello/02, however this conflicts with my first route:
path: /hello/{band}
Is there a way I can associate a route with a particular field in the database (I was thinking maybe something like conditions https://symfony.com/doc/current/routing.html#matching-expressions)? or do I just have to live with this and put some logic in the Twig template to handle things?
Unless you can use some rules to distinguish between band and venue names (eg. band names start with lowercase, venues uppercase) you have to use logic in your controller (not template!).
public function bandOrVenueAction($band_or_venue)
{
$repository = $this->getDoctrine()
->getRepository('LondonHelloBundle:Gig');
$bandinfo = $repository->findByArtist($band_or_venue);
if(empty($bandinfo) === false) {
return $this->render(
'LondonHelloBundle:Hello:band.html.twig',
array('band'=>$bandinfo)
);
}
$venueinfo = $repository->findByArtist($band_or_venue);
if(empty($venueinfo) === false) {
return $this->render(
'LondonHelloBundle:Hello:venue.html.twig',
array('venueinfo'=>$venueinfo)
);
}
// display 404
}

FuelPHP: Trying to implement Search. Routes doesn't work

folks. I'm kinda stuck with Routes
there is a search-form in a top-navigation.
<form action="/search/" class="navbar-search pull-right">
<input type="text" name="q" id="search-query" class="search-query span3" placeholder="Go for it...">
</form>
So if I make a request, the URL looks like
fuelphp.dev/search/?q=qwerty
which is fine. With that URL the user should get results for his/her request provided by action_index()
but if the user goes to fuelphp.dev/search/ (without any parameters), he/she should see the "advanced Search-form" provided by action_advanced()
I alredy created a Controller_Search
classes/controller/search.php (Controller)
class Controller_Search extends Controller_Hybrid
{
public function action_index() {
$this->template->title = 'Results for » '.Input::get('q');
$this->template->content = View::forge('search/index.twig');
}
public function action_advanced()
{
$this->template->title = 'Search » Advanced Search';
$this->template->content = View::forge('search/index.twig', array(
'advancedForm' => true
));
}
}
views/search/index.twig (View)
{% if advancedForm %}
{% include 'advancedSearchForm.twig' %}
{% endif %}
<h4>Hello Template nesting :) </h4>
the problem is - I don't know how to (re)write routes for that.
if I add 'search' => 'search/advanced' to the routes.php it doesnt work correctly.
Requestin fuelphp.dev/search/?q=qwerty triggers action_advanced() of Controller_Search too, whereas it should trigger action_index()
How should I rewrite my routes (or maybe Controller logic) to get this working ?
UPDATE:
The solutuon was found! No routes configuration needed!
public function action_index() {
if (Input::get('q')) {
$viewTitle = 'Results for » '.Input::get('q');
$viewData = null;
}else{
$viewTitle = 'Search » Advanced Search';
$viewData = Array('advancedForm' => true);
}
$this->template->title = $viewTitle;
$this->template->content = View::forge('search/index.twig', $viewData);
}
But if one of you have a "nicer" way, I'll be glad to see it
Try add 2 routes one of them with a named parameter:
'search' => 'search/advanced',
'search/:q' => 'search/index/'
So when it has some parameter goes to search/index with the given parameter, but if you don't have parameters it routes to search/advanced
Then on search/index you can get the search paramer (q) with $this->param('q')

Categories