APM
APM

Reputation: 115

increase limit of query by given amount using php and ajax

Re-frased question do to new info
I'm trying to show a limited set of results on a search (i.e. LIMIT 10 in query) then have a button that will load the next 10 (now LIMIT 20 in same query).

The problem is that when I press the button, it not only refreshes the the specified div - but it re-runs the doSearch at the very top of the page - and thereby resetting the LIMIT to 10...

So if I
1. load the result-page
2. comment out the doSearch at top of page
and first then...
3. click the button

It works as perscribed... it now show 20 results... and if I click again it shows 30... etc.

And if I uncomment the doSearch at the very top of page and click the button... it now shows 10 results again...

the code in question in the ajax-code is

var showResult = self.closest('#showResultsAll').find('[id^="showResults"]');
showResult.load(location.href + " #showResults>*", "");

I can't see why my code would re-run the doSearch at the top of page... but hopeully some of you wise folks can see the error of my ways and set me on the right path...

My basic setup:
page with results:

<?php // get search results limit 10 ?>
.
.
.
<div id="showResultsAll">
    .
    .
    .
    <div id="showResults">
        // Loop through and show results
        <div id="moreResultsButton">
            <input type="hidden" name="search" id="search" value="<?php // search terms ?>">
            <button id="moreResults" value="<?php // number of results found ?>">

jquery.js

$(document).ready(function(){
    "use strict";
    $(document).on('click','button[id^="moreResults"]', function(){
        var self = $(this);
        var closestDiv = self.closest('#moreResultsButton');
        var search = closestDiv.find('[id^="search"]').val();
        var count = self.val();
        var countNew = + count + 10;
        $.ajax({
            type: "POST",
            url:'../scripts/moreresults.php',
            data:"countNew="+countNew+"&search="+search,
            success:function(){
                var showResult = self.closest('#showResultsAll').find('[id^="showResults"]');
                showResult.load(location.href + " #showResults>*", "");
            }
        });
    });
});

moreresults.php

session_start ();

require ( "../scripts/functions.php" );

// Set variable
$search = $_POST['search'];
$limit = $_POST['countNew'];

doSearch ( $pdo , $search , $limit ); // same function that found the search results in the first place

Update
So found a solution loosely based on an answer given below by @delCano (although I'm still curious as to why my original code insisted on rerunning the doSearch at the top of the page)

Solution:
I split everything up by first dropping the limit in the doSearch and just let it find all results and then did the 'limiting' in the show-results part of the page, and then just added 10 to that in my jQuery

New code:
page with results

<?php // doSearch no limit ?>
.
.
.
<div id="showResultsAll">
    .
    .
    .
    <div id="showResults">
        // Loop through and show results - limiting like this
        // if isset $_POST['show'] (ie. button clicked)
            // if $_POST['show'] less than $_SESSION['totalResults'] (ie. more results coming)
                // $show = $_POST['show'] (ie. 20, 30, etc.)
            // else
                // $show = $_SESSION['totalResults'] (ie. 11, 12, ..., 21, 22, ..., 31, 32, ..., etc.)
        // else (if button not clicked limit results to max. 10) 
            // if $_SESSION['totalResults'] more than 10
                // $show = 10 
            // else
                // $show = $_SESSION['totalResults'] (ie. 1, 2, 3, etc.)
        // loop trough $show number of results

        <div class="<?php if $show == $_SESSION['totalResults'] echo "disabled" // Only active if more results are available ?>" id="moreResultsButton">
            <button id="moreResults" value="<?php echo $show; ?>">

jQuery.js

$(document).ready(function(){
    "use strict";
    $(document).on('click','button[id^="moreResults"]', function(){
        var self = $(this);
        var show = self.val();
        var showNew = + show + 10;
        $.ajax({
            type: "POST",
            url:'',
            data:"show="+showNew,
            success:function(){
                self.closest('#showResultsAll').find('[id^="showResults"]').load(location.href + " #showResults>*", "");
            }
        });
    });
});

Upvotes: 0

Views: 631

Answers (1)

delCano
delCano

Reputation: 385

OK, this is not the best answer, just a development from the comments above. I'll try and write a better answer tomorrow.

However, for the time being, my quick workaround would be:

  1. Remove, as you mention, the doSearch from the top of the page, and set all the initial numbers to 0.
  2. Replace your jQuery with this:

$(document).ready(function(){
    "use strict";
    $('button#moreResults').click(addResults);

    function addResults(){
        var self = $(this);
        var closestDiv = self.closest('#moreResultsButton');
        var search = closestDiv.find('[id^="search"]').val();
        var count = self.val();
        var countNew = + count + 10;
        $.ajax({
            type: "POST",
            url:'../scripts/moreresults.php',
            data:"countNew="+countNew+"&search="+search,
            success:function(){
                var showResult = self.closest('#showResultsAll').find('[id^="showResults"]');
                showResult.load(location.href + " #showResults>*", "");
            }
        });
    }
    
    // load the first ten results
    addResults();
});

Please note I did minimal changes to your Javascript. This is not necessarily the most optimal way to do it; I'll revise and edit it tomorrow.


Edit: major refactoring

  1. doSearch is a PHP function that prints the search results to screen. I would change this into a function that returns an array of results. I don't have your code on this, and I don't know how it looks, but it should return something similar to: array( array( 'name' => 'One', 'surname' => 'Smith' ), array( 'name' => 'Two', 'surname' => 'Smythe' ), .... )
  2. moreresults.php is the PHP that is called to load new results. Since all the rest of the logic will be done in Javascript, this is for now the ONLY PHP code we call. I would include doSearch() in this file now.

    session_start ();

    require ( "../scripts/functions.php" );

    function doSearch( $pdo, $search, $limit) { /* do logic here */ return $array_of_results; }

    // Set variable $search = $_POST['search']; $limit = $_POST['countNew'];

    $results = doSearch ( $pdo , $search , $limit );

    header('Content-Type: application/json'); // This will tell the client the type of content returned. echo json_encode($results); // It is a good idea to make all data transmissions between your server-side code (PHP) and your front-end code (Javascript) in JSON. It's also a good idea to never output anything in your PHP code until the very end, where you have all the required data. It makes it easier to debug later on.

  3. Now, the HTML. It doesn't need any PHP preprocessing now, since it will always start the same. We also don't need the tracking of the variables here, since all the logic would be in the Javascript part now.

.
.
.
<div id="showResultsAll">
    .
    .
    .
    <ul id="showResults">
    </ul>
    <button id="loadMore">Load more results</button>
</div>
.
.
.

  1. The Javascript now bears the weight of most of the logic.

$(function() { // Shorthand for "$(document).ready(function()..."
    var count = 0;
    $("#loadMore").click(loadMoreResults);
    
    function loadMoreResults() {
       var url = "../scripts/moreresults.php";
       var search = $("#search").val();
       count += 10;
       var data = {
          'countNew': count,
          'search': search
       };
       $.post(url, data, showResults, 'json' );
    }
    
    function showResults(data) {
        $("#showResults").empty().append(`
        <li>${data.name} ${data.surname}</li>
        `);
    }
});

Notes:

  • Since I didn't know what kind of data you're working with, I used a list of names and surnames as an example.
  • Likewise, I presented the results as a unordered list () and list items(
  • ); you might prefer a table, or something different.
  • The code is completely untested. I tried to be careful, but I may have made some typos or other mistakes.
  • If I were you, I would try to start by learning some jQuery basics before launching myself into Ajax. The FreeCodeCamp has a nice jQuery course.
  • Code architecture is extremely important, and not often well explained in online courses. As a summary:

    1. Always plan ahead your code. Pick up a pen&paper, or your favourite text editor, and answer yourself the question: "What must the code do?". Then decompose the answer in smaller steps. Then separate each step into smaller steps, and so on.
    2. Whenever you have a piece of code you might need twice, wrap it into a function. Think of functions as small "tasks"
    3. Separate as much as possible the logic from the presentation. You should have part of your code working on the data itself, and part of it working on showing the data, and they should be almost independent from each other. You might want to look at the MVC pattern (Model-View-Controller); it may be in process of replacing, but it is a good starting point. This, by the way, is valid both on the backend (doSearch would be the logic, moreresults the presentation) and the frontend (html is the presentation, javascript the logic).
  • To finish, the code I gave you is not perfect, but I think is a better start. You'll assuredly find many ways to improve it

Upvotes: 1

Related Questions