How do I pass variables to another action from a s

2019-09-11 01:09发布

问题:

I have two search pages. One is a condensed search form the other is an advanced search.

I would like the user to enter their search at on the condensed page and be redirected to the results page which contains the advanced search fields.

The two issues I currently have are:

  • How do I redirect?
  • What is the best practice for when a field is left blank?

Currently, I keep looking back to the index to get the first two search fields

Condensed Search

public function indexAction()
{
     $dbAdapter = $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter');
     $form = new HomeSearchForm($dbAdapter);        
     $request = $this->getRequest();   
     if ($request->isPost()) {    
         $homeSearch = new HomeSearch();          
         $form->setInputFilter($homeSearch->getInputFilter());                
         $form->setData($request->getPost());            
         if ($form->isValid()) { 
             $homeSearch->exchangeArray($form->getData());

             if($homeSearch->search_zip == null)
             {
              $homeSearch->search_zip = 'null';
             }

             if($homeSearch->industry_name == null)
             {
              $homeSearch->industry_name = 'null';
             }


           return $this->redirect()->toRoute('home/results',array(
                'zip'=>$homeSearch->search_zip ,
                'industry'=>$homeSearch->industry_name,
           ));

         }
          else {
              echo "Error";
          }           
    }
      return array('form' => $form);
}

Results/Advanced Search

public function resultsAction()
{        
     $search_zip      = $this->params()->fromPost('zip');
     $search_industry = $this->params()->fromRoute('industry');
     $search_language      = $this->params()->fromPost('language');
     $search_gender      = $this->params()->fromRoute('gender');
     $search_name      = $this->params()->fromRoute('name');

     echo var_dump($search_zip);
      echo var_dump($search_industry);
      echo var_dump($search_gender);
     echo var_dump($search_name);

     $dbAdapter = $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter'); 
     $proSearch = new SearchQuery($dbAdapter);
     $form = new SearchForm($dbAdapter); 

     $request = $this->getRequest();   
     if ($request->isPost()) {
         echo 'i post';
         $search = new MainSearch();          
         $form->setInputFilter($search->getInputFilter());                
         $form->setData($request->getPost());  

         if ($form->isValid()) { 
             $search->exchangeArray($form->getData());
             if($search->search_zip == null)
             {
              $search->search_zip = 'null';
             }

             if($search->industry_name == null)
             {
              $search->industry_name = 'null';
             }

             if($search->language_name == null)
             {
              $search->language_name = 'null';
             }

             if($search->pro_gender == null)
             {
              $search->pro_gender = 'null';
             }


         return $this->redirect()->toRoute('home/results', array(
            'action'     => 'results',
            'zip'   => $search->search_zip,
            'industry'   => $search->industry_name,
            'language'   => $search->language_name,
            'gender'   => $search->pro_gender,
            'name'   => $search->pro_name,
          )); 

         }  
     }

      return array(
          'form' => $form,
          'pros' => $proSearch->proSearch($search_zip,$search_industry,$search_language,$search_gender,,$search_name),
              );
}

Update

I am able to get the search to work with the method I have posted below. However I still cannot get the parameters to post in the url (I am able to get the url I want using this code however I have trouble applying the filter and binding the fields to the form $this->form->setAttributes(array('method' => 'GET'));

Isn't the Post Redirect plugin used to prevent users from going back? After reading the manual I am not sure how I go about using this plugin? I'm not sure why the segment is not setting with the below code, I have used this in the past.

'search_zip'=> $this->search_zip 

ModuleConfig

            'results' => array(
                'type' => 'segment',
                'options' => array(
                    'route' => 'results[/:search_zip][/:search_industry][/:language][/:gender][/:designation][/:name]',
                    'defaults' => array(
                        'controller' => 'Application\Controller\Index',
                        'action'     => 'results',

ResultsAction

  public function resultsAction()
    {   
         $dbAdapter = $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter'); 
         $proSearch = new SearchQuery($dbAdapter);
         $request = $this->getRequest();   
         $form = new SearchForm($dbAdapter);  
         if ($request->isPost()) {
             $search = new MainSearch();          
             $form->setInputFilter($search->getInputFilter());                
             $form->setData($request->getPost());  
             if ($form->isValid()) { 
                 $search->exchangeArray($form->getData());
                 $search_zip = $search->search_zip;
                 $search_industry = $search->search_industry;
                 $search_language = $search->search_language;
                 $search_gender = $search->search_gender;
                 $search_designation = $search->search_designation;
                 $search_name = $search->search_name;
             }  
         }

          return array(
              'form' => $form,
              'pros' => $proSearch->proSearch($search_zip,$search_industry,$search_language,$search_gender,$search_designation,$search_name),
                  );

    }

ResultsView

//Search Index

 $title = 'Search';
 $this->headTitle($title);
 ?>
 <h1><?php echo $this->escapeHtml($title); ?></h1>
 <?php
    $form->setAttribute('action', $this->url(
     'home/results',
     array(
         'action' => 'results',
         'search_zip'=> $this->search_zip

     )
 ));
 //$form->setAttributes(array('method' => 'GET'));
 $form->prepare();

 echo $this->form()->openTag($form);
 echo $this->formRow($form->get('industry_name'));
 echo $this->formRow($form->get('search_zip'));
 echo '<br>';
 echo $this->formRow($form->get('language_name'));
 echo $this->formRow($form->get('pro_gender'));
 echo '<br>';
 echo $this->formRow($form->get('designation_name'));
 echo $this->formRow($form->get('pro_name'));
 echo $this->formSubmit($form->get('submit'));

 ?>
 <h2>Results</h2>
 <table class="table">
 <tr>
     <th>First Name</th>
     <th>Last Name</th>
     <th>Street Address</th>
     <th>Office Number</th>
     <th>City</th>
     <th>State</th>
     <th>Zip</th>
     <th>&nbsp;</th>
 </tr>
 <?php foreach ($pros as $pro) : ?>
 <tr>
     <td><?php echo $this->escapeHtml($pro->pro_first);?></td>
     <td><?php echo $this->escapeHtml($pro->pro_last);?></td>
     <td><?php echo $this->escapeHtml($pro->pro_street_address);?></td> 
     <td><?php echo $this->escapeHtml($pro->pro_office_number);?></td> 
     <td><?php echo $this->escapeHtml($pro->pro_city);?></td> 
     <td><?php echo $this->escapeHtml($pro->pro_state);?></td> 
     <td><?php echo $this->escapeHtml($pro->pro_zip);?></td> 
 <?php endforeach; ?>
 </table>

回答1:

Firstly I wouldn't redirect ...

In your search view phtml you can simple do:

<?php $this->form->setAttribute('action', $this->url('your/results/route'))->prepare();?>

and you can then remove all the code from index that handles the post. I wouldn't use two form classes just use one and only render the items you need on the page!

echo $this->form()->openTag($form);
    echo $this->formRow($form->get('search_zip'));
    echo $this->formRow($form->get('industry_name'));
    echo $this->formSubmit($form->get('submit'));
 echo $this->form()->closeTag();

If a user doesn't enter anything in a field just leave it blank

**** UPDATE *****

If you do want to use the segment routing then you could make those sections optional in your routing

'options'   => array(
                'route'    => '[/:language]',
 )

Kind of hard to show you without seeing your routing but that should work.

see http://framework.zend.com/manual/2.0/en/modules/zend.mvc.routing.html#zend-mvc-router-http-segment



回答2:

I've refactored the code you provided to display how I would approach the issue.

Study the approach carefully; the key changes are encapsulating the functionality.

Prerequisites

  • Both forms should POST to the resultsAction()
  • You only need one 'type' of search object (called Search here)
  • Encapsulate! Both forms provide results and search, it will make your code considerably easier (to read and maintain) if you logically separate the functionality

Not tested, that's your job!

public function simpleSearchAction()
{
    $form = $this->getSimpleSearchForm();

    return new ViewModel(compact('form'));
}

public function advancedSearchAction()
{
    $form = $this->getAdvancedSearch();

    return new ViewModel(compact('form'));
}

public function resultsAction()
{
    $request = $this->getRequest();
    $form = $this->getAdvancedSearch();
    $results = array();

    if ($request->isPost()) {

        $form->setData($request->getPost());

        if ($form->isValid()) {

            $search = new Search();
            $search->exchangeArray($form->getData());

            // Execute the search and return the results
            $results = $this->search($search);

            // Populate the form with the search data
            $form->bind($search);
        }
    }

    return new ViewModel(array(
        'form'    => $form,
        'results' => $results,
    ));
}

protected function search(Search $search)
{
    // do search here, although this shouldn't be
    // in the controller, rather a service!
    return $yourResults;
}

// This should be injected into the controller
protected function getAdapter();

// Forms should be using the FormElementManager, not
// being created using new
protected function getSimpleSearchForm();

// Same as above
protected function getAdvancedSearch();

To Think about

  • Post Redirect plugin (if you want nice URL's with the search terms)
  • Dependency injection! Your missing out on the benefits of ZF2, create the DbAdapter and Forms in service factories and inject them into the controller's constructor.
  • Service layer - Moving out the search code will make it reusable and separate the controller logic from business logic.