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

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

Related

Undefined variable problem on Laravel 9.x

I'm trying to get a my title variable from my control page and display it on the about page.
I don't think I have a typo, but it might me. I'm not sure.
Here is my control page code;
class PagesController extends Controller
{
public function index(){
$title = 'Welcome to Laravel';
return view ('pages.index')->with('title', $title);
}
public function about(){
$title = 'About us';
return view ('pages.about')->with('title', $title);
}
public function services(){
$title = 'The services';
return view ('pages.services')->with('title', $title);
}
}
In this page, the index and services functions work fine, but I can't get the about page.
Here is my display pages;
This is Index page
#extends('layouts.app')
#section('content')
<h1>{{$title}}</h1>
<p>This is the Laravel Application</p>
#endsection
This is the about page:
#extends('layouts.app')
#section('content')
<h1>{{$title}}</h1>
<p>This is the About page</p>
#endsection
The error I have
Do this:
return view ('pages.index', compact('title'));
or:
return view ('pages.index', [
'title' => $title
]);
Since you are returning just the title, there isn't any need to call any verbs. Rather you should directly call the view:
route::view('/about', 'Pagecontroller#about');
or
pass the parameter by compact:
return view ('pages.index', compact('title'));
or
return view ('pages.index', ['title' => $title]);
Since this is a test application from a lesson, I forgot to delete some extra code in my route file.
This is my route file:
Route::get('/', 'App\Http\Controllers\PagesController#index');
Route::get('/about', 'App\Http\Controllers\PagesController#about');
Route::get('/services', 'App\Http\Controllers\PagesController#services');
The commented area shouldn't be here. That was the whole problem over here...
// Route::get('/about', function(){
// return view ('pages.about');
// });
This form of passing variables is a short-lived entry of a variable into the session. Then accessing the variable on the page should look like this:
{{ session('title') }}
If you want to pass data to the view, then you need to use the method
return view('pages.services', ['title' => $title]);
Laravel views

ZF2 add params to setPartial submenu

I use this partial to generate my submenu.
<?php foreach ($this->container as $page): ?>
<?php foreach ($page->getPages() as $child): ?>
<a href="<?php echo $child->getHref(); ?>" class="list-group-item">
<?php echo $this->translate($child->getLabel()); ?>
</a>
<?php endforeach; ?>
<?php endforeach; ?>
Which is called like this:
$this->navigation('navigation')->menu()->setPartial('partial/submenu')->render();
But when i render the menu the "$child->getHref()" renders the url without the needed "slug/id" parameter.
I tried to create the url with "$this->url()" in ZF1 you could pass the params in an array to the partial but in ZF2 that doesn't seem to work anymore.
Can anybody tell me how to add the params to the menu urls?
Thanks in advance!
PS!
I'm not referring to $this->Partial, i'm talking about $this->navigation('navigation')->menu()->setPartial('partial/submenu')->render() which apparently doesn't support a param array.
If I'm understanding your question, yes, you can pass params to partials. Example:
<?php echo $this->partial('partial.phtml', array(
'from' => 'Team Framework',
'subject' => 'view partials')); ?>
See http://framework.zend.com/manual/2.3/en/modules/zend.view.helpers.partial.html
I'm not sure this completely solves your issue, since you are not showing what the menu helper is. Is it your own view helper? Are you saying that setPartial method only accepts one argument?
All that said, have you considered Spiffy Navigation?
https://github.com/spiffyjr/spiffy-navigation
It's been sometime since this question was asked, however today I came across the same problem (using version 2.4).
If you have a segment route to be included within the menu that requires some parameters there is no way to pass these through to the navigation's view partial helper.
The change I've made allows a ViewModel instance to be passed to the menu navigation helper's setPartial() method. This view model will be the context for the navigation's partial template rendering; therefore we can use it to set the variables we need for the route creation and fetch them just like within other views using $this->variableName.
The change requires you to extend the Menu helper (or which ever navigation helper requires it).
namespace Foo\Navigation;
use Zend\Navigation\AbstractContainer;
use Zend\View\Model\ViewModel;
class Menu extends \Zend\View\Helper\Navigation\Menu
{
public function renderPartial($container = null, $partial = null)
{
if (null == $container) {
$container = $this->getContainer();
}
if ($container && $partial instanceof ViewModel) {
$partial->setVariable('container', $container);
}
return parent::renderPartial($container, $partial);
}
public function setPartial($partial)
{
if ($partial instanceof ViewModel) {
$this->partial = $partial;
} else {
parent::setPartial($partial);
}
return $this;
}
}
Because this extends the default implementation of the helper updated configuration is required in module.config.php to ensure the extend class is loaded.
'navigation_helpers' => [
'invokables' => [
'Menu' => 'Foo\Navigation\Menu',
],
],
The menu helper will then accept a view model instance.
$viewModel = new \Zend\View\Model\ViewModel;
$viewModel->setTemplate('path/to/partial/template')
->setVariable('id', $foo->getId());
echo $this->navigation()
->menu()
->setPartial($viewModel)
->render();
The only change in the actual partial script will require you to create the URL's using the URL view helper.
foreach ($container as $page) {
//...
$href = $this->url($page->getRoute(), ['id' => $this->id]);
//...
}

Laravel Routing and Controller for Search

I'm building my first basic laravel web app, after following a few tutorials this is the first one I'm tinkering with on my own. I'm running into to some trouble with routing to a controller and then getting the correct url.
Ideally at this point I should only have two routes / and /{user}. On the homepage you can search via a form for the user and the form should take you to /{user}.
Routes (I have three cause I'm still trying to get this to work, and I think I need a POST):
Route::get('/', 'HomeController#index');
Route::get('/{user}', 'HomeController#student');
Route::post('/', 'HomeController#studentLookUp');
Home Controller:
public function index()
{
return View::make('helpdesk');
}
public function student($user) {
return View::make('selfservice')
->with('user', $user);
}
public function studentLookUp() {
$user = Input::get('ID');
return View::make('selfservice')
->with('user', $user);
}
Form:
{{ Form::open(array('class'=>'navbar-form navbar-left', 'role'=>'search'), array('action' => 'HomeController#student')) }}
<div class="form-group">
{{ Form::text('ID', '', array('placeholder'=>'ID', 'class'=>'form-control') ); }}
</div>
{{ Form::button('Search', array('class'=>'btn btn-default')) }}
{{ Form::close() }}
At this point I can search from the homepage ('/') and it will take me back to the homepage but with the searched for user which is how I want it to work except it doesn't have the right url of homepage.com/username.
Any help would be much appreciated!
First register a route to listen your search request:
1. Search Route:
Register search route.
//route search
Route::get('/search',['uses' => 'SearchController#getSearch','as' => 'search']);
2. Search View:-
Now create a search form in a view:-
<form action="/search" method="get">
<input type="text" name="q" placeholder="Search.."/>
<button type="submit">Search</button>
</form>
3. SearchController :
Now create SearchController to handle your searching logic.
SearchController :
<?php
class SearchController extends \BaseController {
public function getSearch()
{
//get keywords input for search
$keyword= Input::get('q');
//search that student in Database
$students= Student::find($keyword);
//return display search result to user by using a view
return View::make('selfservice')->with('student', $students);
}
}
Now you have to create one view selfservice to display your search result.
4. Selfservice View:
#foreach ($students as $key=> $student)
<div>
{{$student->name}}
</div>
#endforeach
Here for each student result, one link will be created. That link will be link:-
website.domain/{student}
5. Update Routes for Student
Route::get('/{student}',['uses' => 'HomeController#student','as' => 'student.show']);
UPDATE updated the answer to get student page directly
To redirect from search to website.domain\{user} follow these steps:-
1. Modify SearchController
<?php
class SearchController extends \BaseController {
public function getSearch()
{
//get keywords input for search
$keyword= Input::get('q');
//search that student in Database
$student= Student::find($keyword);
//redirect directly to student.show route with student detail
return Redirect::route('student.show', array('student' => $student));
}
}
2. Now add a function for Route student.show in HomeController
Route::get('/{student}',['uses' => 'HomeController#student','as' => 'student.show']);
In HomeController
public function student($student)
{
//here display student detail
}

Best way to search function in symfony 2

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

Best Practices: What's the Best Way for Constructing Headers and Footers?

What's the best way for constructing headers, and footers? Should you call it all from the controller, or include it from the view file? I'm using CodeIgniter, and I'm wanting to know what's the best practice for this. Loading all the included view files from the controller, like this?
class Page extends Controller {
function index()
{
$data['page_title'] = 'Your title';
$this->load->view('header');
$this->load->view('menu');
$this->load->view('content', $data);
$this->load->view('footer');
}
}
or calling the single view file, and calling the header and footer views from there:
//controller file
class Page extends Controller {
function index()
{
$data['page_title'] = 'Your title';
$this->load->view('content', $data);
}
}
//view file
<?php $this->load->view('header'); ?>
<p>The data from the controller</p>
<?php $this->load->view('footer'); ?>
I've seen it done both ways, but want to choose now before I go too far down a path.
Actually, after researching this quite a bit myself, I came to the conclusion that the best practice for including headers and footers in MVC is a third option - namely extending a base controller. That will give you a little more flexibility than the text's suggestion, particularly if you're building a very modular layout (not just header and footer, also sidebar panels, non-static menus, etc.).
First, define a Base_controller class, in which you create methods that append your page elements (header, footer, etc.) to an output string:
class Base_controller extends Controller
{
var $_output = '';
function _standard_header($data=null)
{
if (empty($data))
$data = ...; // set default data for standard header here
$this->_output .= $this->load->view('header', $data, true);
}
function _admin_header($data=null)
{
if (empty($data))
$data = ...; // set default data for expanded header here
$this->_output .= $this->load->view('admin_header', $data, true);
}
function _standard_page($data)
{
$this->_standard_header();
$this->_output .=
$this->load->view('standard_content', $data, true);
echo $this->_output; // note: place the echo statement in a
// separate function for added flexibility
}
function _page_with_admin_header($data)
{
$this->_admin_header($data);
$this->_output .=
$this->load->view('standard_content', $data, true);
echo $this->_output;
}
}
Then, in your page controllers, simply extend the base class and call your functions to build the page.
class Page_controller extends Base_controller
{
function index()
{
$data = ...; // Set content data here
$this->_standard_page($data);
}
function admin()
{
$data = ...; // Set content and header data here
$this->_page_with_admin_header($data);
}
}
Using a base controller, you can achieve very clean code in your individual page controllers AND have separate views for elements on the page (allowing code reuse in both views and controllers). All you need to do is define your common page 'sections' (what you might be tempted to call 'fragments') as functions in your base controller.
And if the base controller should start to grow uncontrollably (which can happen on large sites), you can rearrange some of its less-general functions by placing them in subclasses and letting the corresponding page controllers extend those instead of the original base controller.
Enjoy!
You could also try it this way -- define a default view template, which then pulls in the content based on a variable ('content' in my example) passed by the controller.
In your controller:
$data['content'] = 'your_controller/index';
// more code...
$this->load->vars($data);
$this->load->view('layouts/default');
Then define a default layout for all pages e.g. views/layouts/default.php
// doctype, header html etc.
<div id="content">
<?= $this->load->view($content) ?>
</div>
// footer html etc.
Then your views can just contain the pure content e.g. views/your_controller/index.php might contain just the variables passed from the controller/data array
<?= $archives_table ?>
<?= $pagination ?>
// etc.
More details on the CI wiki/FAQ -- (Q. How do I embed views within views? Nested templates?...)
I think the first way you are doing it is cleaner. Simply from a point of view of knowledge that is going to be rendered. Rather than having to enter the view file to find the rest.
It's bad practice to call views inside of other views. This could be a form of controller view mixing. The view function in CI allows you to pass a third parameter that causes it to return that view's output as a string. You can use this to create a compound view.
For example:
class Page extends Controller {
function index() {
$data['page_title'] = 'Your title';
$this->load->view('default_layout', array(
'header' => $this->load->view('header' , array(), true),
'menu' => $this->load->view('menu' , array(), true),
'content' => $this->load->view('content', $data , true),
'footer' => $this->load->view('footer' , array(), true),
));
}
}
default_layout.php
<? echo $header, $menu, $content, $footer; ?>
You may want to combine your header and footer to make a template like this.
class Page extends Controller {
function index() {
$data['page_title'] = 'Your title';
$this->load->view('default_template', array(
'menu' => $this->load->view('menu' , array(), true),
'content' => $this->load->view('content', $data , true),
));
}
}
default_template.php
<html><head></head><body><span>Some Header HTML</span> // this is your header html
<? echo $menu, $content; ?>
<span>some footer HTML</span></body></html> // this is your footer html

Categories