Keep Search Parameters Through Pagination - forms

Somewhat new to Laravel(4.2) and I'm having issues with pagination on my search function. So far I've been able to successfully carry out a search, though in the rare cases it actually goes over onto a second page it resets to simply "?page=2"
Below is the code for the form.
{{ Form::open(array('method' => 'post', 'name' => 'all', 'novalidate' => 'novalidate')) }}
<input type="text" name="srch_lname" class="input-large" value="{{ Input::old('srch_lname', Session::get('srch_lname')) }}" />
<input type="text" name="srch_fname" class="input-large" value="{{ Input::old('srch_fname', Session::get('srch_fname')) }}" />
.
.
.
<?php echo $employees->links(); ?>
And the controller handling the search.
public function getIndex() {
$srch_lname = Session::get('srch_lname');
$srch_fname = Session::get('srch_fname');
$employees = vEmployees::co()->restrictions()
->where('lastname', 'LIKE', $srch_lname . '%')
->where('firstname', 'LIKE', $srch_fname . '%')
->orderBy('lastname')
->orderBy('firstname')
->paginate(10);
return View::make('index')
->with('employees', $employees)
->with('title', 'Users')
->with('pagetitle', 'Employees')
->with('pagedescription', '')
}
public function postIndex() {
if (Input::has('btnSearch')) {
return Redirect::to('/employees')->with('search', 1)
->with('srch_lname', Input::get('srch_lname'))
->with('srch_fname', Input::get('srch_fname'))
I've been trying some other solutions found throughout SO though it either ends up causing issues or bringing me back to the same problem.
Any sort of push in the right direction would be awesome!

Append the search data to the pagination links()
<?php echo $employees->appends(array("srch_lname" => ...))->links(); ?>
http://laravel.com/docs/4.2/pagination#appending-to-pagination-links

Related

laravel 4 changing url structure with parameter passing

I'm just a beginner in laravel framework. i created a simple form and controller methods . i think by default the form method is post. but now i need to make it as get method and also wants to pass the selected inputs to controller and shows that parameters in the url also. currently i did like below but failed.
index.blade.php
<?php echo Form::open(array('url' => 'home/find','method' => 'get')); ?>
<select class="location" id="location" name='location'>
<?php
$id1 = /* get user db details based on locations*/
$location_id_drop_down='';
foreach($idl as $lrow)
{
$city_name=Location::where('location_id','=',$lrow['loc_id'])->first();
if($city_name==array()) continue;
if(Input::old('location')==$lrow['loc_id'])
{
$location_id_drop_down.="<option value='" . $city_name['location_name'] . "' selected='selected'>" .$city_name['location_name'] . "</option>";
}
else
{
$location_id_drop_down.="<option value='" . $city_name['location_name'] . "'>" . $city_name['location_name']. "</option>";
}
}
echo $location_id_drop_down;
?>
</select>
<input type="submit" name="search" id="search_submit" class="search_submit" value="Search" />
{{ Form::close() }}
HomeController.php
public function anyFind($s='',$d='',$l='') {
if(Input::get('search'))
{
$location=Input::get('location');
}
else
{
if($l!='~')
$location=$l;
}
/* queries to get the user details and images based on selected location and list them*/
}
Routes.php
Route::get('/find/{location}','HomeController#anySearch');
But this shows the url as mysite.com/home/find?location=Test&search=Search
I need mysite.com/home/find/location
is there any mistake in my code?
Edit
As a part of experiment i tried this method. i gave a redirect like below at the end of my controller function anyfind()
return Redirect::to('/home/find/'.$location);
But this redirects me but did anyone knows how to load the search.search_new.blade.php with this custom url??
Having a field from the form in your url (not query string) is simply not possible with Laravel. What you can do though, is just use javascript for that.
First lets put a placeholder in the action url
<?php echo Form::open(array('url' => 'home/find/%location%','method' => 'get')); ?>
jQuery
$('form').on('submit', function(){ // you maybe need to be a bit more precise with the selector here
var location = $('#location').val();
$(this).prop('action', $(this).prop('action').replace('%location%', location));
});
Vanilla Javascript (if you can't / don't want to use jQuery)
document.getElementsByTagName('form')[0].onsubmit = function(e){
var location = document.getElementById('location').value;
e.target.setAttribute('action', e.target.getAttribute('action').replace('%location%', location));
};
By the way: the code in your question has still some weird stuff in there. I'm just assuming this has happened because of copy paste etc. So if it still doesn't work, make sure you post the correct code
Insert at the end of your method anyFind() inside the HomeController.php where you set the view for the page:
if (Input::get('location') != '') {
return Redirect::route('home.findByLocation',Input::get('location'));
}
return View::make('home', compact('location));
Also in your routes.php add the following code:
Route::get('home/find/{location?}', array('as'=>'home.findByLocation', 'uses'=>'HomeController#anyFind'));

CodeIgniter form_open() action not working correctly

I have have a view in which there's a form that manages products (either add new product or -if an id passed- editing an existing one). If an id is passed then the form action should be eg 'admin/product/manage/5', if no id passed then it should be like this 'admin/product/manage'.
<?php echo form_open('admin/product/manage/{optional product id}', array('class' => 'ajax-form')); ?>
I have also created and this route:
$route['admin/product/manage'] = "admin/product/manage";
$route['admin/product/manage/(:num)'] = "admin/product/manage/$1";
How can I make my form action work correctly? is it possible to put inside the action the route somehow??
This is my Controller:
public function manage($id = NULL){
//fetch a single product to edit or create a new one
if (isset($id) === true) {
$data['prod'] = $this->product_model->get($id);
$data['vers'] = $this->product_version_model->get_by('product_id',$id);
} else {
$data['prod'] = $this->product_model->make_new();// this returns $product->product_name = ''; in order to be empty the input field and not throughing errors
}
$this->product_model->save_product();
$this->product_version_model->save_version();
// load the view
$this->layout->view('admin/products/manage', $data);
}
This is my view:
<?php echo form_open('admin/product/manage', array('class' => 'ajax-form')); ?>
<p>
<label for="product_name">Product *</label>
<input type="text" name="product_name" value="<?php echo set_value('product_name', $prod->product_name); ?>" />
<?php echo form_error('product_name'); ?>
</p>
<?php echo form_close() . PHP_EOL; ?>
You need to declare both possible routes in order of importance, so:
$route['admin/product'] = "admin/product/manage";
$route['admin/product/(:num)'] = "admin/product/manage/$1";
From the Codeigniter Docs:
Routes will run in the order they are defined. Higher routes will always take precedence over lower ones.
Edit:
According to the changes you have made to your question I can say the following:
First of all isset() returns boolean only, so you don't need the type check "=== true". isset($id) is sufficient.
In order to have your form action set to the id you need to include it either in a hidden field or in the action itself.
So for example:
$action_id = (isset($id) ? '/'.$id : ''); // Using ternary operators here
echo form_open('admin/product/manage'.$action_id, array('class' => 'ajax-form'));
and add the id to the view data in your controller:
$data['id'] = $id;
As a side note: In order to comply with SoC (Separation of Concerns) you'd prepare all data in your controller (with e.g. models all having their own task) and pass the processed data to the view instead of partially generating data in the view itself.

Why is CakePHP 2.3.0 adding a '1' to my Form Post Values?

I'm using cakephp 2.3.0. I searched in the manual for quite awhile, but I haven't found the answer. Also, I've searched the Internet, but still haven't found what I'm looking for. SO, I'm posting my question here. Note, I'm fairly new to cakephp.
Scenario:
I have a simple form with two fields: activity and zip code.
I'm using POST on the form.
When I type in some value in those fields and submit, I echo those 'post' values/parameters and display in the browser screen. What I typed in, I can see on the screen, but the number '1' is added to the end of what I typed in the form.
Here is an example. I type in these values in the form, 'walk' and '44555'. Then I click 'Submit'. The post goes to my controller's action, which then calls my view. My view is displayed on the browser screen and I echo out those 'post' values. The results on screen are 'walk1' and '445551'.
Example #2: If I follow the steps above and don't enter any values in my form (I'll add error checking later), what I see on the browser screen is '1' and '1'.
I am unable to figure out why I am getting the value of '1' added to my form's POST values?
I'll be glad to include any other additional php code to this posting, if requested by someone trying to help.
Here is my FORM code (from my view)...I know there are DIV helpers, but I'll get to that later:
echo $this->Form->create(null, array('url' => array('controller'=>'activities', 'action'=>'results'))); ?>
<div class="box1" style="position:relative; top:10px; left:10px; float: left;">
Search here.... <br>
<hr>
<?php echo $this->Form->input('activityName', array('size'=>'30',
'label'=>'Activity Name:', 'value'=>'i.e. walking, etc.'));?>
<br>
<?php echo $this->Form->input('zip', array('size'=>'7', 'label'=>'Postal Code:')); ?>
<br>
</div>
<div class="box1" align="right">
<?php echo $this->Form->end('Go Search');?>
</div>
Here is my controller code:
<?php
class ActivitiesController extends AppController {
public $helpers = array('Html', 'Form');
public function index() {
//other code....
}
public function results() {
$this->layout = 'second';
$name = $this->request->data['Activity']['activityName'];
$pCode = $this->request->data['Activity']['zip'];
$this->set('theName', $name);
$this->set('theZip', $pCode);
$this->set('results', $this->Activity->
find('all', array('conditions' => array('name' => $name, 'postal_code' => $pCode))));
$this->set('title_for_layout', 'Results');
$this->render();
}
}
?>
My final view code. I left off some of the code...just showing the part that matters:
<div style="position:relative; top:10px; left:5px; ">
<?php echo print_r($theName); ?>
<br>
<?php echo print_r($theZip); ?>
Thanks
The 1 comes from printing the return value of print_r() which is true (i.e. 1).
In other words: you shouldn't do echo print_r(), just do print_r(). The function handles the printing by itself, you don't have to print the results manually.
(Also, print_r() is almost never the best choice to print out values except when debugging and even then CakePHP's debug() is much more suitable.)

modify form action with symfony2 and phpunit

I'm currently working with Symfony2 and I'm testing my project with PHPUnit.
I want to test an exception when a form is submitted with the wrong parameters or the URL isn't complete.
I went trough the documentation of Symfony2 and PHPUnit but didn't find any class/method to do so.
How can I change the value of a form's action? I want to use PHPUnit so the report created is up to date and I can see the coverage of my code.
EDIT:
To clarify my question, some new content.
How do I test the line starting with '>' in my controller? (throw $this->createNotFoundException('Unable to find ParkingZone entity.');)
When the user modifies the action link, in the controller the process will go trough the exception (or error message, if this action is chosen). How can I test this case?
Controller
/**
* Edits an existing ParkingZone entity.
*
* #Route("/{id}/update", name="parkingzone_update")
* #Method("post")
* #Template("RatpGarageL1Bundle:ParkingZone:edit.html.twig")
*/
public function updateAction($id)
{
$em = $this->getDoctrine()->getEntityManager();
$entity = $em->getRepository('RatpGarageL1Bundle:ParkingZone')->find($id);
if (!$entity) {
> throw $this->createNotFoundException('Unable to find ParkingZone entity.');
}
$editForm = $this->createForm(new ParkingZoneType(), $entity);
$deleteForm = $this->createDeleteForm($id);
$request = $this->getRequest();
$editForm->bindRequest($request);
if ($editForm->isValid()) {
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('parkingzone_edit', array('id' => $id)));
}
return array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
);
}
View:
<form action="{{ path('parkingzone_update', { 'id': entity.id }) }}" method="post" {{ form_enctype(form) }}>
<div class="control-group">
{{ form_label(form.name, 'Name', { 'attr': {'class': 'control-label'} } ) }}
<div class="controls error">
{{ form_widget(form.name, { 'attr': {'class': ''} } ) }}
<span class="help-inline">{{ form_errors(form.name) }}</span>
</div>
</div>
<div class="control-group">
{{ form_label(form.orderSequence, 'Rang', { 'attr': {'class': 'control-label'} } ) }}
<div class="controls error">
{{ form_widget(form.orderSequence, { 'attr': {'class': ''} } ) }}
<span class="help-inline">{{ form_errors(form.orderSequence) }}</span>
</div>
</div>
<div class="control-group">
{{ form_label(form.image, 'Image', { 'attr': {'class': 'control-label'} } ) }}
<div class="controls error">
{{ form_widget(form.image, { 'attr': {'class': ''} } ) }}
<span class="help-inline">{{ form_errors(form.image) }}</span>
</div>
</div>
{{ form_rest(form) }}
<div class="form-actions">
<button type="submit" class="btn btn-primary">Enregistrer</button>
Annuler
</div>
</form>
Symfony itself does not have any objects through which it is possible to manipulate the form's action as it is set in the html (twig files). However, twig provides the capability to dynamically change the form's action in the twig file.
The basic approach is for the controller to pass a parameter into the twig file via the render call. Then the twig file can use this parameter to set the form action dynamically. If the controller uses a session variable to determine the value of this parameter then by setting the value of this session variable in the test program it is possible to set the form action specifically for the test.
For example in the controller:
public function indexAction()
{
$session = $this->get('session');
$formAction = $session->get('formAction');
if (empty($formAction)) $formAction = '/my/normal/route';
...
return $this->render('MyBundle:XXX:index.html.twig', array(
'form' => $form->createView(), 'formAction' => $formAction)
);
}
And then, in the twig file:
<form id="myForm" name="myForm" action="{{ formAction }}" method="post">
...
</form>
And then, in the test program:
$client = static::createClient();
$session = $client->getContainer()->get('session');
$session->set('formAction', '/test/route');
$session->save();
// do the test
This isn't the only way, there are various possibilities. For example, the session variable could be $testMode and if this variable is set the form passes $testMode = true into the render call. Then the twig file could set the form action to one of two values depending on the value of the testMode variable.
Symfony2 makes a distinction between unit testing of individual classes and functional testing of application behaviour. Unit testing is carried out by directly instantiating a class and calling methods on it. Functional testing is carried out by simulating requests and testing responses. See symfony testing for further detail.
Form submission can only be tested functionally as it is handled by a Symfony controller which always operates in the context of a container. Symfony functional tests must extend the WebTestCase class. This class provides access to a client which is used to request URLs, click links, select buttons and submit forms. These actions return a crawler instance representing the HTML response which is used to verify that the response contains the expected content.
It is only appropriate to test that exceptions are thrown when carrying out unit tests as functional tests cover interaction with the user. The user should never be aware that an exception has been thrown. Therefore the worst case scenario is that the exception is caught by Symfony and in production the user is presented with the catch-all response "Oops, an error has occurred" (or similar customised message). However, this should really only occur when the application is broken and not because the user has used the application incorrectly. Therefore it is not something that would typically be tested for in a functional test.
Regarding the first scenario mentioned in the question - submitting a form with the wrong parameters. In this case the user should be presented with an error message(s) telling them what was wrong with their input. Ideally the controller should not be throwing an exception but symfony validation should be used to automatically generate error messages next to each field as appropriate. Regardless of how the errors are displayed this can be tested by checking that the response to submitting the form contains the expected error(s). For example:
class MyControllerTest extends WebTestCase
{
public function testCreateUserValidation()
{
$client = static::createClient();
$crawler = $client->request('GET', '/new-user');
$form = $crawler->selectButton('submit')->form();
$crawler = $client->submit($form, array('name' => '', 'email' => 'xxx'));
$this->assertTrue($crawler->filter('html:contains("Name must not be blank")')->count() > 0,
"Page contains 'Name must not be blank'");
$this->assertTrue($crawler->filter('html:contains("Invalid email address")')->count() > 0,
"Page contains 'Invalid email address'");
}
}
Regarding the second scenario - where the URL isn't complete. With Symfony any URL which does not match a defined route will result in a NotFoundHttpException. In development this will result in a message such as 'No route found for "GET /xxx"'. In production it will result in the catch-all 'Oops, an error has occurred'. It would be possible to test in development that the response contains 'No route found'. However, in practice it doesn't really make sense to test this as it's handled by the Symfony framework and is therefore a given.
EDIT:
Regarding the scenario where the URL contains invalid data which identifies an object. This could be tested (in development) like this in the unit test program:
$client = static::createClient();
$page = $client->request('GET', '/update/XXX');
$exceptionThrown = ($page->filter('html:contains("NotFoundException")')->count() > 0) && ($page->filter('html:contains("Unable to find ParkingZone entity")')->count() > 0);
$this->assertTrue($exceptionThrown, "Exception thrown 'Unable to find ParkingZone entity'");
If you just want to test that an exception has been thrown rather than a specific type / message you can just filter the html for 'Exception'. Remember that in production the user will only see "Oops, an error has occurred", the word 'Exception' will not be present.
Thanks to #redbirdo with his last answer, I found a solution without messing out with the controllers.
I only changed few lines in the templates.
ControllerTest
public function testUpdate()
{
$client = static::createClient();
$session = $client->getContainer()->get('session');
$session->set('testActionForm', 'abc');
$session->save(); // This line is important or you template won't see the variable
// ... tests
}
View
{% if app.session.has('testActionForm') %}
{% set actionForm = path('parkingzone_update', { 'id': app.session.get('testActionForm') }) %}
{% else %}
{% set actionForm = path('parkingzone_update', { 'id': entity.id }) %}
{% endif %}
<form action="{{ actionForm }}" {{ form_enctype(form) }} method="POST" class="form-horizontal">
// ... rest of the form

Codeigniter: getting select option from form

I'm trying to get the option item selected in a form select element using Codeigniter...
I have a controller named results with this code in it
//get form data
if($_SERVER['REQUEST_METHOD'] == "POST"){
$data['searchdata'] = array(
"ionum" => $this->input->post('ionum'),
"thisdb" => $this->input->post('thisdb')
);
}
which loads into a view, the 'ionum' is a text input which I can retrieve, the 'thisdb' is the select, I get no results for it...how do I pull that?
Ensure your html looks like:
<form action="<?= site_url('mycontroller/myfunction');?>" method='post'>
<input type='text' name='ionum'/>
<select name='thisdb'>
<option value='db1'>DB1</option>
<option value='db2'>DB2</option>
</select>
</form>
Then in your controller, you would write:
class Mycontroller extends CI_Controller{
function myfunction(){
$p = $this->input->post();
if($p){
//you can now access the ionum and thisdb... try echo
echo $p['ionum'];
echo $p['thisdb'];
}
}
}
It is unnecessary to run the if($_SERVER['REQUEST_METHOD'] == "POST") conditional. Just check if $p exists as above.