0

I have a working AJAX request call, that calls to a PHP file(which has some looping) and depending on some parameters in can take several minutes for the request to be ready. But waiting several minutes is not really user friendly.

How should i modify my code in order to have results outputed in HTML after after each for loop is over?

I understand this streaming effect could be accomplished with API's like web-sockets or socket.io, but I hope I can manage to accomplish this without needing to implement the use of these API's .

Live example witch the effect i am going for:

http://www.brokenlinkcheck.com/

I have made a demo of my code with the core of my logic in it:

PHP File :

<?php

$html = file_get_html($url);

function check_url($a)
{

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $a);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $data    = curl_exec($ch);
    $headers = curl_getinfo($ch);
    curl_close($ch);

    return $headers['http_code'];
}
$good_array = array();
$number = 1;
foreach ($html->find('a') as $element) { // this one should return results first

    $a = $element->href;
    $check_url_status = check_url($a);
    if (!preg_match('/404/', $check_url_status)) {
        echo "<p style='color:green'>" . $number . '. ' . $a . " - Works (Response: $check_url_status) </p>";
        $good_array[] = $a;
    } else {
        echo "<p style='color:red'>" . $number . '. ' . $a . " - Broken (Response : $check_url_status) </p>";
    }
    $number++;
}
array_unique($good_array);

for ($x = 0; count($good_array) > $x; $x++) { // from then on for every ending of this loop - it should add new html output via ajax.

    $html = file_get_html($good_array[$x]);
    foreach ($html->find('a') as $element) {

        $a = $element->href;

        $check_url_status = check_url($a);
        if (!preg_match('/404/', $check_url_status)) {
            echo "<p>" . $number . '. ' . $a . " -  Works (Response : $check_url_status) | src: $good_array[$x] </p>";
        } else {
            echo "<p>" . $number . '. ' . $a . " - Broken (Response : $check_url_status) | src: $good_array[$x]  </p>";
        }
        $number++;
    }
}
?>

jQuery AJAX:

 $(document).ready(function () {

     $("#ajax-btn").click(function () {
         $.ajax({
             url: "../broken_links",
             type: "get",


             success: function (result) {
                 $("#div1").load('http://website.dev/php');
                 //  alert('works');
             },
             error: function (jqXHR, textStatus, errorThrown) {
                 console.log(textStatus, errorThrown);
             }

         });
     });
});

(Would be perfect if the solution involved jQuery AJAX, but vanilla JS would also do)

HTML:

<div class="panel panel-default">
    <div class="panel-body">
        <h2 id='div1'>test</h2>
        <button id='ajax-btn'> Change Content</button>
    </div>
</div>

Between I'm using Laravel 5.3 Framework so any solutions that involves built in framework features are also welcome!

ρяσѕρєя K
  • 132,198
  • 53
  • 198
  • 213
Dr. House
  • 483
  • 7
  • 23
  • Why are you doing this with PHP and not directly with JavaScript? I don't think you can send partial results using AJAX. – Richard Jan 29 '17 at 19:23
  • If this is on your own site would be best done as a cron job and store results Really not clear exactly what you are trying to accomplish at a higher level – charlietfl Jan 29 '17 at 23:33
  • I also have a cron job that results are being converted from html to pdf and are sent to the user/stored, but this feature is also needed as an online real time scan as in the website example i've provided. – Dr. House Jan 30 '17 at 00:40

1 Answers1

0

You won't be able to send partial AJAX updates using PHP. Why don't you get all of the URLs from JavaScript and test them one by one.

$('a').each(function(){
    var $anchor = $(this);

    // Do Ajax call to check for this URL, directly to that page or your own PHP

    $.ajax({
         url: "../broken_links",
         type: "get",
         data: { url: $anchor.attr('href') },
         success: function (result) {
             $("#div1").load('http://website.dev/php');
             //  alert('works');
         },
         error: function (jqXHR, textStatus, errorThrown) {
             console.log(textStatus, errorThrown);
         }

     });

});

PHP

<?php

$url = $_GET['url'];


    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $data    = curl_exec($ch);
    $headers = curl_getinfo($ch);
    curl_close($ch);

    if (!preg_match('/404/', headers['http_code'])) {
        echo "<p style='color:green'>" . $number . '. ' . $url . " - Works (Response: $check_url_status) </p>";
        $good_array[] = $a;
    } else {
        echo "<p style='color:red'>" . $number . '. ' . $url . " - Broken (Response : $check_url_status) </p>";
    }

?>
Richard
  • 4,341
  • 5
  • 35
  • 55
  • Because I'm using curl and php lib - simplehtmldom . As I understand your solution is to use javascript for my spindering, replacing php? I'm afraid that it's not really an option - that's similar to going from linux to win to fix you problem. – Dr. House Jan 29 '17 at 19:52
  • So don't use cUrl, but use Javascript instead... You can do an AJAX call to the URLs and check the response code, like you are doing in PHP. Alternatively, do several calls to your own PHP code, but do 1 request per URL from javascript in the loop that I posted. Then the PHP code just tests 1 URL per request and will return the result everytime. That way you will get what you want, and get updates after each check – Richard Jan 29 '17 at 20:02
  • Updated answer with PHP. Obviously not tested, but should be able to work from this. – Richard Jan 29 '17 at 20:08
  • Ok, looks interesting. My main Q is how do you assign/define/parse $url values, because you haven't done any of these in your js and because of this i get an internal error in the console and can't really evaluate this answer. – Dr. House Jan 30 '17 at 00:48
  • Not sure what your question is exactly? Parse from where? JS or PHP? PHP checks the URL and returns some HTML based on the test... – Richard Jan 30 '17 at 07:28
  • In your JS part - how do you get URL value? – Dr. House Jan 30 '17 at 09:41
  • http://stackoverflow.com/questions/5344145/how-to-get-response-status-code-from-jquery-ajax – Richard Jan 30 '17 at 11:12
  • This doesn't really helps - please give more details. I need to scrape the html document from the website and find all the a tags and it's hrefs . **$html = file_get_html($url);** - How would I replace this part in JS is not mentioned in your solution... – Dr. House Jan 30 '17 at 13:42