phphtmlsearchcodeigniter-3

Placing Search Results in Pieces into Separate Divs? Is this Possible?


I am not sure if there is an answer to my question or if it even possible but here goes:

I am working on an old Codeigniter 3.1.9 site in PHP 8.2.12. My question is is it possible to have search result from a database be split up into smaller pieces to be placed in separate divs for legibility or would I be confined to using table tds?

At present, the search on the site searches a database that contains a "recipe" table and that table has 14 fields and contains 58 records. I am only trying to request 5 of those fields per search. The issue right now is that as it stands, I am only able to get a recipe name and link to it. I have categories and subcategories for each recipe listed but I don't like the idea of having that all be crammed into a single div or even a single column. Is there any way I can rectify this?

I am still new to PHP and this project was dumped in my lap to figure out and trying to decipher this monster of a site has been quite the challenge. I have kept it running since Codeigniter 1.83. Please be kind as I navigate my way through this.

Also I didn't initially write the code for this site so I am having to reverse engineer nearly everything. I will provide any files you might need to see. I just don't want to make my post any longer than it already is and overwhelm you all with needless code.

Recipe.php Controller

function search(){
   if($this->input->method() === 'post'){
    $search = $this->input->post('query');  
    $results = $this->recipe_model->search($search);
    $data = array(
     'title' => "Shirley's Recipes:Search Results", 
     'columns' => array('toc', 'public/page/search_results'), 
     'recipes' => $results  
    );
    $this->load->view('templates/main', $data);
   }
   else{ 
    redirect('recipe');
   }
  } 

Recipe_model

function search($search){
 $terms = explode(' ', $search);    
 $match = " ";   
 foreach($terms as $term){    
  $match .= $term;
 }
   
 $querystr = "SELECT *, MATCH(name, category, subcategory, keywords) AGAINST('".$match."') as score  FROM recipe WHERE MATCH(name, category, subcategory, keywords) AGAINST('".$match."') ORDER BY score DESC;";
   $q = $this->db->query($querystr);
   return $q->result();
  }

search_results.php

<link rel="stylesheet" type="text/css" href="/assets/css/public/page/searchresults.css" media="screen" />
<div id="sitecontent" class="grid-item2 grid-container">
  <?php
   if($admin){
    $this->load->view('admin/nav/notesnav');
   }
  ?>
  <div id="contents" class="grid-item1 grid-container scrollbar <?php if($admin){echo 'grid-item2';} ?>">
   <div id="spiral" class="grid-item1">
    <img class="spiral" src="/assets/img/lines/spiral1trans.png"/>
   </div> 
   <div id="searchresults" class="grid-item2 grid-container">
    <h1>Search Results</h1>
    <div id="results" class="grid-item1 grid-container">
     <div id="resultsheading" class="grid-item1 heading">Your Results:</div>
     <div id="numheading" class="grid-item2 heading">#:</div>
     <div id="resultlistheading" class="grid-item3 heading">Results:</div>
     <div id="categoryheading" class="grid-item4 heading">Category:</div>
     <div id="subcategoryheading" class="grid-item5 heading">Subcategory</div>
     <div id="num1" class="grid-item6">1</div>
      <div id="result1" class="grid-item7">
       <ol>
       <?php     
         if(!empty($recipes)): 
         foreach($recipes as $recipe): 
        ?>
        <li><a href="/recipe/<?= $recipe->id ?>"><?=$recipe->name ?></a></li>       
        <?php endforeach; ?>
       </ol> 
       <?php else: ?>
       No matching recipes
       <?php endif; ?>
      </div>
      <div id="category1" class="grid-item8"></div>
      <div id="subcategory1" class="grid-item9"></div>
      <div id="num2" class="grid-item10">2</div>
      <div id="result2" class="grid-item11">
       
      </div>
      <div id="category2" class="grid-item12"></div>
      <div id="subcategory2" class="grid-item13"></div>
      <div id="num3" class="grid-item14">3</div>
      <div id="result3" class="grid-item15">Eventually I will have each result appear on its own line.</div>
      <div id="category3" class="grid-item16"></div>
      <div id="subcategory3" class="grid-item17"></div>
      <div id="num4" class="grid-item18">4</div>
      <div id="result4" class="grid-item19">Eventually I will have each result appear on its own line.</div>
      <div id="category4" class="grid-item20"></div>
      <div id="subcategory4" class="grid-item21"></div>
      <div id="num5" class="grid-item22">5</div>
      <div id="result5" class="grid-item23">Eventually I will have each result appear on its own line.</div>
      <div id="category5" class="grid-item24"></div>
      <div id="subcategory5" class="grid-item25"></div>
       <div id="num6" class="grid-item26">6</div>
      <div id="result6" class="grid-item27">Eventually I will have each result appear on its own line.</div>
      <div id="category6" class="grid-item28"></div>
      <div id="subcategory6" class="grid-item29"></div>
       <div id="num7" class="grid-item30">7</div>
      <div id="result7" class="grid-item31">Eventually I will have each result appear on its own line.</div>
      <div id="category7" class="grid-item32"></div>
      <div id="subcategory7" class="grid-item33"></div>
       <div id="num8" class="grid-item34">8</div>
      <div id="result8" class="grid-item35">Eventually I will have each result appear on its own line.</div>
      <div id="category8" class="grid-item36"></div>
      <div id="subcategory8" class="grid-item37"></div>
       <div id="num9" class="grid-item38">9</div>
      <div id="result9" class="grid-item39">Eventually I will have each result appear on its own line.</div>
      <div id="category9" class="grid-item40"></div>
      <div id="subcategory9" class="grid-item41"></div>
       <div id="num10" class="grid-item42">10</div>
      <div id="result10" class="grid-item43">Eventually I will have each result appear on its own line.</div>
      <div id="category10" class="grid-item44"></div>
      <div id="subcategory10" class="grid-item45"></div>      
    </div>
    </div>
   </div>
   <div id="updated" class="grid-item2">Updated 05/27/2023 @ 2:34 EDT</div>
  </div>    

Thank you all for any help you can offer.


Solution

  • I've looked up your site via Google, so I think I understand what you're trying to do. Your current layout uses display:grid with grid-template-areas in css so that's why you're using all the numbered ids and classes in html. If you want to keep the numbered ids and classes, you can change your code like this:

      <div id="results" class="grid-item1 grid-container">
        <div id="resultsheading" class="grid-item1 heading">Your Results:</div>
    
        <div id="numheading" class="grid-item2 heading">#:</div>
        <div id="resultlistheading" class="grid-item3 heading">Results:</div>
        <div id="categoryheading" class="grid-item4 heading">Category:</div>
        <div id="subcategoryheading" class="grid-item5 heading">Subcategory</div>
    
        <?php
        if (!empty($recipes)):
          $itemNumber = 6;
          foreach ($recipes as $key => $recipe):
            $rowNumber = $key + 1;
        ?>
            <div id="num<?= $rowNumber ?>" class="grid-item<?= $itemNumber++ ?>"><?= $rowNumber ?></div>
            <div id="result<?= $rowNumber ?>" class="grid-item<?= $itemNumber++ ?>">
              <a href="/recipe/<?= $recipe->id ?>"><?= $recipe->name ?></a>
            </div>
            <div id="category<?= $rowNumber ?>" class="grid-item<?= $itemNumber++ ?>"><?= $recipe->category ?></div>
            <div id="subcategory<?= $rowNumber ?>" class="grid-item<?= $itemNumber++ ?>"><?= $recipe->subcategory ?></div>
          <?php endforeach; ?>
        <?php else: ?>
          <div style="grid-column: 1 / -1" class="heading">No matching recipes</div>
        <?php endif; ?>
    
      </div>
    

    I've moved the foreach loop so it surrounds the 4 divs that hold the data for one recipe, and moved the if/else around that.

    Then added an $itemNumber variable that starts at 6 (because your first recipe num div has the grid-item6 class), this is then used to print the numbers in all grid-item# classes. (<?= $itemNumber++; ?> prints the $itemNumber and then increases its value by one.)

    I've also added a $rowNumber variable for the numbering of the ids and the value of the num div, this is based on the $key in the recipes array (this is numbered starting at 0).

    The name of the recipe (including link) is printed in the result div with:

    <div id="result<?= $rowNumber ?>" class="grid-item<?= $itemNumber++ ?>">
      <a href="/recipe/<?= $recipe->id ?>"><?= $recipe->name ?></a>
    </div>
    

    And the category and subcategory of the recipe in their respective divs with:

    <div id="category<?= $rowNumber ?>" class="grid-item<?= $itemNumber++ ?>"><?= $recipe->category ?></div>
    <div id="subcategory<?= $rowNumber ?>" class="grid-item<?= $itemNumber++ ?>"><?= $recipe->subcategory ?></div>
    

    If no recipes are found, a div is displayed that spans the entire width of the grid (style="grid-column: 1 / -1"). I gave it the heading class to give it some styling, but you might want to change that.


    You do however have a lot of duplicate code in your css for the numbered ids and classes, so I would suggest changing your html to this instead:

      <div id="results" class="grid-item1 grid-container">
        <div id="resultsheading" class="grid-item1 heading">Your Results:</div>
    
        <div id="numheading" class="grid-item2 heading">#:</div>
        <div id="resultlistheading" class="grid-item3 heading">Results:</div>
        <div id="categoryheading" class="grid-item4 heading">Category:</div>
        <div id="subcategoryheading" class="grid-item5 heading">Subcategory</div>
    
        <?php
        if (!empty($recipes)):
          foreach ($recipes as $key => $recipe):
        ?>
            <div class="grid-item num"><?= $key + 1 ?></div>
            <div class="grid-item">
              <a href="/recipe/<?= $recipe->id ?>"><?= $recipe->name ?></a>
            </div>
            <div class="grid-item"><?= $recipe->category ?></div>
            <div class="grid-item"><?= $recipe->subcategory ?></div>
          <?php endforeach; ?>
        <?php else: ?>
          <div class="grid-item no-result">No matching recipes</div>
        <?php endif; ?>
    
      </div>
    

    This gives each num div a num class and I've added a no-result class to the "No matching recipes" div. All divs also get the grid-item class for shared styling.

    Then change the css for the grid-container to remove the fixed number of rows for the recipes:

    #results.grid-container{
     display:grid;
     grid-template-columns:2% 32.6% 32.6% 31.9%;
     grid-template-rows:repeat(2, 25px);
     grid-auto-rows: 24px; 
     grid-template-areas:
     'resultsheading resultsheading resultsheading resultsheading'
     'numheading resultlistheading categoryheading subcategoryheading';  
     grid-gap:4px;         
     padding:4px;
     margin:0;       
    }
    

    The styling for the recipe divs can then be shortened to this (in searchresults.css, remove everything starting from /* ~~~~~~~~> RESULTS COMMON NUM DIV STYLES <~~~~~~~~ */ to the end of the file, and replace with the following):

    /* ~~~~~~~~> RESULTS COMMON NUM DIV STYLES <~~~~~~~~ */
    #results .grid-item.num {
     /* Permalink - use to edit and share this gradient: https://colorzilla.com/gradient-editor/#91b3e5+0,6890cb+44,91b3e5+100;Blue+3D+%2314 */
     background: #91b3e5; /* Old browsers */
     background: -moz-linear-gradient(top,  #91b3e5 0%, #6890cb 44%, #91b3e5 100%); /* FF3.6-15 */
     background: -webkit-linear-gradient(top,  #91b3e5 0%,#6890cb 44%,#91b3e5 100%); /* Chrome10-25,Safari5.1-6 */
     background: linear-gradient(to bottom,  #91b3e5 0%,#6890cb 44%,#91b3e5 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
     filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#91b3e5', endColorstr='#91b3e5',GradientType=0 ); /* IE6-9 */
     font-weight:bold; 
     text-align:center;
    }
    

    Common styling for all recipe divs:

    #results .grid-item {
     background: #91b3e5;
     text-align:left;
     color:navy;   
     padding:2px;            
     border:1px solid blue; 
     border-radius:4px;        
    }
    

    Alternate background for "even" rows:

    #results .grid-item:nth-child(8n + 11),
    #results .grid-item:nth-child(8n + 12),
    #results .grid-item:nth-child(8n + 13) {
     background:#6890CB;       
    }
    

    And styling for the "No matching recipes" div:

    #results .grid-item.no-result {
     grid-column: 1 / -1;
     text-align:center;
    }
    

    Made a fiddle here: https://jsfiddle.net/ys6k84ug/

    Hope this helps!


    To add the search term to the page, change the controller method to pass the $search variable to the view:

      function search(){
       if($this->input->method() === 'post'){
        $search = $this->input->post('query');  
        $results = $this->recipe_model->search($search);
        $data = array(
         'title' => "Shirley's Recipes:Search Results", 
         'columns' => array('toc', 'public/page/search_results'), 
         'recipes' => $results,
         'search' => $search
        );
        $this->load->view('templates/main', $data);
       }
       else{ 
        redirect('recipe');
       }
      } 
    

    And then print it in the view:

    <div id="resultsheading" class="grid-item1 heading">Your Search Results for: <?= $search ?></div>