title: Codeigniter pagination with search filters
body: <p>I have been working on implementing a search method within codeigniter that uses codeigniters pagination functionality.
  This required a bit of research up front since we are including filters and a user could select a variable number of filters,
  throwing off the uri_segment count. I have a working solution below (only posted code that i felt was relative to understanding
  the process so not to confuse. If I missed anything let me know) that would get someone started if they run across the same
  issue, but want to ask a few questions:</p>
  
  <p>QUESTIONS:</p>
  
  <ol>
  <li><p>Is there a better, more efficient way to go about having pagination on filtered search results?</p></li>
  <li><p>Is there anything anyone would do to improve THIS method?</p></li>
  <li><p>How could one display the current uri in the user's browser after the initial post? The way the pagination library functions
  it does not display the 'first_url' until it has been clicked via the generated links. I was tossing around a redirect idea, but
  wanted to get feedback before going that route.</p></li>
  </ol>
  
  <p><strong>VIEW</strong></p>
  
  <pre><code>&lt;!-- SEARCH FILTERS --&gt;
  &lt;form action="/account/classified/browse" method="post" id="searchForm"&gt;
  
  &lt;p&gt;Search
  &lt;br/&gt;
  &lt;input type="text" name="phrase" id="searchString" value="&lt;?php echo $selectedPhrase; ?&gt;"/&gt;&lt;/p&gt;
  
  &lt;p&gt;Type&lt;br/&gt;
  &lt;?php echo form_dropdown('type', $types, $selectedType); ?&gt;
  &lt;/p&gt;
  
  &lt;p&gt;County&lt;br/&gt;
  &lt;?php echo form_dropdown('location', $locations, $selectedLocation); ?&gt;
  &lt;/p&gt;
  
  &lt;p&gt;Market&lt;br/&gt;
  &lt;?php echo form_dropdown('market', $markets, $selectedMarket); ?&gt;
  &lt;/p&gt;
  
  &lt;p&gt;
      &lt;input type="submit" id="searchClassifiedButton" name="" value="Search"/&gt;
  
  &lt;/p&gt;
  
  &lt;/form&gt;
  &lt;table&gt;
  
  &lt;?
  
  /*
      Results returned
  */
  if (count($classifieds) &gt; 0) {
      foreach ($classifieds as $classified) {
          echo '&lt;tr&gt;';
  
          //rows returned from query using search filters
  
          echo '&lt;/tr&gt;';
      }
  } else {
      echo 'There are no classifieds posted at this time';
  }
  ?&gt;
  
  &lt;/table&gt;
  </code></pre>
  
  <p><strong>CONTROLLER:</strong></p>
  
  <pre><code>&lt;?
  public function browse() {
      $this -&gt; load -&gt; helper("url");
      $this -&gt; load -&gt; library("pagination");
      $this -&gt; load -&gt; model('classified_model');
      $post = $this -&gt; input -&gt; post();
  
      /*
          Here we determine if the post array contains values. If it does, then we know that the
          user has clicked the search button and wishs to view results by different filters.
  
          If the post array is empty, but the uri segment contains values, this would mean that we
          are viewing listings narrowed by the search filters. 
  
          If the post array is empty as well as the uri segment, then we are viewing all results
          with no filters applied.
      */
      if ($post) {
          foreach ($post as $key =&gt; $val) {
              if ($val != '') {
                  $filters[$key] = $val;
              }
          }
      } elseif ($this -&gt; uri -&gt; uri_to_assoc(4)) {
          $filters = $this -&gt; uri -&gt; uri_to_assoc(4);
      } else {
          $filters = array();
      }
  
      /*
          Here we create the config array for the pagination.
  
          We assign 'first_url' so that the first generated paginated link will contain the uri filter
  
          When filters array is not empty we assign 'suffix' so that the uri segment can be appended to the link AFTER the page offest
      */
      $pageConfig = array();
      $pageConfig['first_url'] = !empty($filters) ? '/account/classified/browse/0/' . $this -&gt; uri -&gt; assoc_to_uri($filters) : '/account/classified/browse/0';
      $pageConfig["suffix"] = !empty($filters) ? '/' . $this -&gt; uri -&gt; assoc_to_uri($filters) : '';
      $pageConfig["base_url"] = "/account/classified/browse/";
      $pageConfig["per_page"] = 15;
      $pageConfig["uri_segment"] = 3;
      $pageConfig["total_rows"] = $this -&gt; classified_model -&gt; approved_classifieds_count($filters);
  
  
      $this -&gt; pagination -&gt; initialize($pageConfig);
  
  
      $page = ($this -&gt; uri -&gt; segment(3)) ? $this -&gt; uri -&gt; segment(3) : 0;
  
  
      $data['classifieds'] = $this -&gt; classified_model -&gt; approved_classifieds($filters, $pageConfig["per_page"], $page);
      $data['links'] = $this -&gt; pagination -&gt; create_links();
  
  
      //PHRASE
      $data['selectedPhrase'] = (isset($filters['phrase'])) ? $filters['phrase'] : '';
  
      //TYPES
      $returnTypes = array('' =&gt; '-- View All --');
      foreach($this-&gt;classified_model-&gt;classified_search_types() as $type){
          $returnTypes[$type-&gt;id] = $type-&gt;name;
      }
      $data['types'] = $returnTypes;
      $data['selectedType'] = (isset($filters['type'])) ? $filters['type'] : '';
  
      //MARKETS
      $returnMarkets = array('' =&gt; '-- View All --');
      foreach($this-&gt;classified_model-&gt;market_types() as $market){
          $returnMarkets[$market-&gt;id] = $market-&gt;name;
      }
      $data['markets'] = $returnMarkets;
      $data['selectedMarket'] = (isset($filters['market'])) ? $filters['market'] : '';
  
      //COUNTIES
      $returnLocations = array('' =&gt; '-- View All --');
      foreach($this-&gt;classified_model-&gt;locations() as $key =&gt; $val){
          $returnLocations[$key] = $val;
      }
      $data['locations'] = $returnLocations;
      $data['selectedLocation'] = (isset($filters['location'])) ? $filters['location'] : '';
  
  
      //using phil sturgeon's template library
      $this -&gt; template -&gt; build('browse_classified', $data);
  
  
  }
  </code></pre>
  
  <p><strong>MODEL:</strong></p>
  
  <pre><code>public function classified_search_types(){
      $q = $this-&gt;db-&gt;query("SELECT * FROM classified_types");
      return $q-&gt;result();
  }
  
  public function market_types(){
      $query = $this -&gt; db -&gt; get('market_types');
      return $query -&gt; result();
  }
  
  public function locations(){
      $query = $this -&gt; db -&gt; get('locations');
      return $query -&gt; result();
  }
  
  public function approved_classifieds_count($filters){
      $result = $this-&gt;search($filters);
      return $result-&gt;num_rows();
  }
  
  public function approved_classifieds($filters, $limit, $start) {
      $result = $this-&gt;search($filters, $limit, $start);
      return $result-&gt;result();
  }
  
  function search($filters, $limit='', $start=''){
      $this-&gt;load-&gt;helper('security');
  
      /*
          Obtain values from filters array, set to '' if value not in array
      */
      $phrase = xss_clean((isset($filters['phrase'])) ? $filters['phrase'] : '');
      $type = xss_clean((isset($filters['type'])) ? $filters['type'] : '');
      $market = xss_clean((isset($filters['market'])) ? $filters['market'] : '');
      $location = xss_clean((isset($filters['location'])) ? $filters['location'] : '');
  
  
      /*
          QUERY LOGIC
      */
  
  
      $q = $this-&gt;db-&gt;query($query);
  
  
      return $q;
  
  }
  </code></pre>