Showing posts with label PHP Interview Questions. Show all posts
Showing posts with label PHP Interview Questions. Show all posts

Thursday, 4 September 2014

PHP Interview Questions And Answers

This is the last portion of our PHP practice interview questions and answers. Here is part 3 of the PHP practice interview question:
Given the previous two portions of this question, can you name some of the drawbacks or disadvantages of the solution you provided?
And, here are parts 1 and 2 of the original question for your convenience:
Write a PHP script to report the total download size of any URL. You may not use any 3rd-party code that performs the entire task described below.
No HTML interface is necessary for this exercise; you can write this as a command-line script that accepts the URL as an argument.
For a single-file resource such as an image or SWF, the script would simply report on the total size of the document.
For a complex resource such as an HTML document, the script would need to parse it to find references to embedded, included resources: javascript files, CSS files, iframes, etc.
The goal of this exercise is to output the following information for a given URL:
- total number of HTTP requests
- total download size for all requests

The code should also be able to handle the URL in the src attribute of an iframe.
There are a lot of potential problems with the solution that we gave for this interview question. And, some of those problems are unavoidable given that this is an interview question, and you don’t have a few weeks to give a perfect answer. Try to see if you can think of any potential problems on your own.

No Javascript was executed to find additional resources


One disadvantage is the fact that our PHP code does not try to execute any Javascript in order to find additional resources. What exactly does that mean? Well, many websites have some Javascript code that, when executed, will request and display specific resources on their page – like gif’s, jpg’s, swf’s, or whatever else the Javascript want’s to display (it’s really up to whoever wrote the Javascript code).
One specific example of Javascript requesting and displaying resources are websites (like this one) which use Google Adsense to put Google’s ads on their website. In order to do this, a Javascript script is provided by Google. And, some Javascript variables are also passed to the script to tell the script what size the ad should be.
That Javascript is then executed by the browser and the correct ad is generated – it could be a SWF file (which is a Flash format), a jpg, a gif, or whatever file type Google determines is appropriate to display at the moment for whoever is viewing the webpage.
But, we can’t possibly be expected to run this Javascript in order to see what kind of resource is generated – doing this could be tricky. And, there’s no guarantee that trying to execute this Javascript would even be successful. This means that this will be one less resource that will be counted – and even more if there are multiple ads on a page (like there are on this page). So, that’s one drawback of the PHP code we came up with to answer this interview question. And, this means that less HTTP requests are counted than the true number of HTTP requests on pages that use Javascript to request additional resources.

Checking for duplicate resources

One thing we admittedly do not do in our implementation is check for duplicate resources – like images/CSS/Javascript files being referenced more than once in the HTML. Even though the files are referenced multiple times in the HTML file, they still result in only one HTTP request because browsers are smart enough to only make the request once. But, we are counting each one of those as a separate request – this should be fairly simple to fix, but it is an issue with our code which could result is double-counting of HTTP requests.

Checking for resources inside CSS documents

Another thing that we did not do is check for resources named inside external CSS documents – like “background-image”. That means our implementation will not count those resources, which would lead to a total number of HTTP requests that is lower than the actual number.

Checking for browser specific code

Another thing we did not do in our implementation is check for browser specific code – as in the HTML tags that look like this: “<!–[if IE]>”. This could also potentially affect the HTTP request count and total download size that our implementation reports, because certain files could conditionally be included depending on what browser the user is using. A common usage of this is to use a different stylesheet for older Internet Explorer browsers. This would mean that our implementation would double count – both the stylesheet for Internet Explorer and the stylesheet for non-Internet Explorer browsers.

Browser cache

One thing that may be challenging is accounting for the resources which are already cached by the browser. If a resource is cached, then it means that the browser will not generate a new HTTP request for that resource because the browser will just use the version of the resource that it has saved in it’s cache. This means that since we are not even taking browser caching into account in our implementation (something that would probably be very difficult), in situations where cached resources are used we would definitely be over-estimating the number of HTTP requests because we just count every single resource in the HTML as an HTTP request.

Final thoughts on Advanced PHP interview question and answer part 3

Now, those are just some of the potential drawbacks of our answer to the PHP interview question. Remember, Writing something that is very accurate given all the complexities would be very challenging and time consuming – and would certainly not be expected in a PHP interview question like this. Most likely, what interviewers are looking for with a question like this is that you have some essential PHP skills, and a good foundation of knowledge for how the web works.

PHP Interview Questions And Answers

This is a continuation of the practice PHP interview question from part 1. Here is the additional part of the question that we want you to try to answer:
The code should also be able to handle the URL in the src attribute of an iframe.
And, here is the original question for your convenience:
Write a PHP script to report the total download size of any URL. You may not use any 3rd-party code that performs the entire task described below.
No HTML interface is necessary for this exercise; you can write this as a command-line script that accepts the URL as an argument.
For a single-file resource such as an image or SWF, the script would simply report on the total size of the document.
For a complex resource such as an HTML document, the script would need to parse it to find references to embedded, included resources: javascript files, CSS files, iframes, etc.
The goal of this exercise is to output the following information for a given URL:
- total number of HTTP requests
- total download size for all requests

How to handle an iframe src


The second part of the question states that we will need to be able to handle the URL in the src attribute of an iframe tag. What exactly does that mean? Well, the src attribute of an iframe tag points to another HTML page. When an iframe tag is used in a page it’s like embedding another HTML page within that page. And since the whole point of this exercise is to find the number of HTTP requests being made along with the total download size for all requests, we basically have to follow the iframe src URL ourselves and figure out how many new HTTP requests are created from that URL and what their total download size will be.
For example, we actually use an iframe tag on this page to embed the Facebook likebox, which you can see on the bottom of the left hand sidebar. This is what our iframe tag looks like (you can also see this if you “View Source” for this page) – note that the iframe src actually points to a php page called “likebox.php”:

You can see the result on this page itself when the iframe is actually 
rendered – there is a like button, a count of likes, some text, and an 
image of a nerd.  The like button and the nerd will be 2 separate HTTP 
requests.  The iframe src itself counts as an HTTP request as well – 
because the browser will have to make a request for whatever URL the 
iframe src points to.

View source does not show you markup generated by iframe

But, the thing is that when we read the HTML on the page, we will only see the iframe tag – we will not see the markup that is created by the iframe. This is an important point to understand, and you can confirm this fact by just doing a view source on this page. Even if we tell cURL to retrieve the page for us, the HTML returned will have the iframe tag in it’s original form, and not in it’s rendered form. For that reason, if we want to find out the number of HTTP requests that the iframe will generate, we have to take a look at the URL in the source tag itself and evaluate just like we did for the original URL.
What this means is that we will essentially have to re-use the same code to find the requests and download size that we used for the top level (containing) document as we would use for the containing document that will hold the iframe tag. Think about that for a second and see if you can come up with a good approach to solve that problem on your own.
It turns out that we can actually use recursion to basically call our existing code, and pass in the URL value from the iframe src attribute. This way we can find the number of HTTP requests and total download size for the requests that will come from the iframe src URL, we just re-use the code that we have already written.
In order to use recursion here, we should have our code wrapped inside a function. So, with that in mind we create the function below that we call start – note that we deliberately left out the code which is used to find images/css/javascript since we just want to focus on the iframe piece and making a recursive call.

Using recursion to answer PHP Interview question part 2

So, we can just make a recursive call to the start function as shown below in red:
function start($URL){

if (!check_if_html($URL))
{
$totalSize = get_remote_file_size($URL);

echo "Final Total Download Size: $totalSize Bytes ";

$totalNumResources += 1;//single resource is an HTTP request

echo "Final total HTTP requests: $totalNumResources" ;

return;

}

/* at this point we know we are dealing with an HTML document
   which also counts as a resource, so increment the 
   $totalNumResources variable by 1:
*/

$totalNumResources += 1;

foreach($html->find('iframe') as $element)
{
     echo "IFRAME" . "$element->src.\n";    

    start($element->src); 

}

} //CLOSING BRACE FOR "START" FUNCTION

But, wait a second. What will happen to the $totalSize and $totalNumResources variables? Well, with the implementation above they will actually get reset during the recursive call, and when the recursive call returns, the values will be back to what they were originally, before the recursive call. This makes no sense – what we really want is to count the number of HTTP requests and calculate the download size of the requests that are added by the iframe. Remember – we want a cumulative sum of the HTTP requests and download size, including whatever resources are added to the page by the iframe.

Saving the values of the PHP variables

So, there clearly needs to be a way to save the value of those variables while the recursive call is made – so that the recursive call can just add on to those values. The way to do this is to pass in the values of the $totalSize and $totalNumResources variables into the recursive call to the start function – so the start function will now have to be modified so it can accept two extra parameters.
But, just passing the variables $totalSize and $totalNumResources into the recursive call is not enough – we also need to return those variables from the function itself. If those values are incremented during the recursive call, we need to be sure to retain the modified values even after the recursive call is over. So, we will have to use the code below – note the changes are in red:
function start($URL, $totalSize, $totalNumResources){

if (!check_if_html($URL))
{
$totalSize = get_remote_file_size($URL);

echo "Final Total Download Size: $totalSize Bytes ";

$totalNumResources += 1; //single resource is HTTP request

echo "  Final total HTTP requests: $totalNumResources" ;

return;
}

/* at this point we know we are dealing with an 
    HTML document which also counts as a resource, 
   so increment the $totalNumResources variable by 1
*/

$html = file_get_html($URL);


$totalNumResources += 1; 

foreach($html->find('iframe') as $element)
{
       echo "IFRAME:" . "$element->src.\n";
  
      list($totalSize, $totalNumResources)  = 
      start($element->src, $totalSize, $totalNumResources);      

}

     return array($totalSize, $totalNumResources) ;


} //closing brace for 'start' function...

Note that we use the list function in PHP to hold the variables that will be returned once the start function returns from the recursive call.
Another interesting thing that we should point out in the code above is the fact that we do not have any code inside the iframe foreach loop that increments the $totalNumResources by 1. This is because during the recursive call the $totalNumResources variable will be incremented by 1 anyways, because the iframe URL is counted as a separate HTML document.

The final answer to Advanced PHP Interview Question Part 2

Now, here is what the complete PHP code looks like which includes the recursive call to the start function, and is our final answer to part 2 of the PHP interview questions:
include('simple_html_dom.php');

$URL = $argv[1];

$totalSize = 0;

$totalNumResources = 0;

 list($totalSize, $totalNumResources)  = 
start($URL, $totalSize, $totalNumResources);


echo "Final total download size: $totalSize Bytes  " ;

echo "Final total HTTP requests: $totalNumResources";



function start($URL, $totalSize, $totalNumResources){



if (!check_if_html($URL))
{
$totalSize = get_remote_file_size($URL);

echo "Final Total Download Size: $totalSize Bytes ";

$totalNumResources += 1; //a single resource is an HTTP request

echo "  Final total HTTP requests: $totalNumResources" ;

return;
}


$html = file_get_html($URL);



// find all images!!
foreach($html->find('img') as $element){

    $size = get_remote_file_size($element->src);
  
    $totalSize = $totalSize + $size;  
    
    $totalNumResources += 1;

    //echo "Here is the total size: $totalSize.\n"; 
    
  // echo "total resources: $totalNumResources .\n";      
}


// Find all css
foreach($html->find('link') as $element)
{

 if (strpos($element->href,'.css') !== false) {

    $size = get_remote_file_size($element->href);
    
       //    echo "SIZE: $size.\n";

      $totalSize = $totalSize + $size; 
        
      $totalNumResources += 1;
  
     //echo "total resources: $totalNumResources .\n"; 

        
       //  echo "Here is the total size: $totalSize.\n"; 
  
    //echo "$element->href.\n"; 

 }
     //only output the ones with 'css' inside...
}



foreach($html->find('script') as $element)
{

if (strpos($element->src,'.js') !== false) {

   $size = get_remote_file_size($element->src);
   
   
       $totalSize = $totalSize + $size;   
       
       
       $totalNumResources += 1;

       
      // echo "Here is the total size: $totalSize.\n"; 
       
        //    echo "total resources: $totalNumResources .\n"; 


    //echo "$element->src.\n";  

 }

}


foreach($html->find('iframe') as $element)
{

       //echo "IFRAME" . "$element->src.\n"; 
       
     
      /* DON't count iframe as request, because it 
         will be counted as an HTML document
         which means it will be counted above, so
         get rid of the increment line in the 
         actual code, and explain this point as well!!
      */
       
      list($totalSize, $totalNumResources)  = 
      start($element->src, $totalSize, $totalNumResources);
           
}



return array($totalSize, $totalNumResources) ;



} //CLOSING BRACE FOR THE FUNCTION "START"...


function get_remote_file_size($url) {
    $headers = get_headers($url, 1);
    
    if (isset($headers['Content-Length'])) 
    return $headers['Content-Length'];
    
    //THIS ONE CHECKS FOR LOWER CASE L IN CONTENT-length (DIFFERENT FROM ABOVE!!)
    if (isset($headers['Content-length'])) 
    return $headers['Content-length'];

    $c = curl_init();
    curl_setopt_array($c, array(
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => array('User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3'),
        ));
    curl_exec($c);
    
    $size = curl_getinfo($c, CURLINFO_SIZE_DOWNLOAD);
    
    return $size;
        
    curl_close($c);

}



function check_if_html($url){
     $ch = curl_init($url);

     curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
     curl_setopt($ch, CURLOPT_HEADER, TRUE);
     curl_setopt($ch, CURLOPT_NOBODY, TRUE);

     $data = curl_exec($ch);
     $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE );

     curl_close($ch);
     
     
     if (strpos($contentType,'text/html') !== false)
   return TRUE;  // this is HTML, yes!
  else
     return FALSE;
 
}
Feel free to add your comments below if you see anything wrong or have any questions. Note that the code above is meant to run from a command line, and you may see some PHP warnings depending on which site you are trying to analyze with the code.

PHP Interview Questions And Answers

The answer to Advanced PHP Interview Question Part 1

Finally, we present our complete answer to the advanced PHP interview question part 1 below – with all the source code you need to answer the first portion of the question. You can also continue on to Part 2 of the PHP Interview Questions and Answers, or just click the next button below.
include('simple_html_dom.php');

$URL = $argv[1];

$totalSize = 0;

$totalNumResources = 0;

/*
check to see if the URL points to an HTML page,
if it doesn't then we are dealing with a single
file resource:
*/

if (!check_if_html($URL))
{
$totalSize = get_remote_file_size($URL);

echo "Final Total Download Size: $totalSize Bytes ";

$totalNumResources += 1;  //a single resource is still an HTTP request

echo "  Final total HTTP requests: $totalNumResources" ;

return;

}


/* at this point we know we are dealing with an HTML document
   which also counts as a resource, so increment the $totalNumResources
   variable by 1
*/

$totalNumResources += 1; 

$html = file_get_html($URL);

// find all images:
foreach($html->find('img') as $element){

    $size = get_remote_file_size($element->src);
  
    $totalSize = $totalSize + $size;  
    
    $totalNumResources += 1;

    /*
    echo "Total Size So Far: $totalSize.\n"; 
    
    echo "total resources: $totalNumResources .\n"; 

           echo "IMAGE SIZE: $size.\n";

           echo "$element->src.\n";
       */
}

// Find all CSS:
foreach($html->find('link') as $element)
{

 if (strpos($element->href,'.css') !== false) {

   $size = get_remote_file_size($element->href);
    
   $totalSize = $totalSize + $size; 
        
   $totalNumResources += 1;
 
   /*
    echo "total resources: $totalNumResources .\n"; 

    echo "Total Size So Far: $totalSize.\n"; 
  
    echo "$element->href.\n";    
    */
 }
     //only output the ones with 'css' inside...
}


//find all javascript:
foreach($html->find('script') as $element)
{

//check to see if it is javascript file:
if (strpos($element->src,'.js') !== false) {

   $size = get_remote_file_size($element->src);
   
   //echo " JS SIZE: $size.\n"; 

  $totalSize = $totalSize + $size;   
       
  $totalNumResources += 1;
  
 /*

   echo "Total Size So Far: $totalSize.\n"; 
       
  echo "total resources: $totalNumResources .\n"; 

        echo "$element->src.\n";  
 */
 }
}

echo "Final total download size: $totalSize Bytes" ;

echo "Final total HTTP requests: $totalNumResources";

function get_remote_file_size($url) {
    $headers = get_headers($url, 1);
    
    if (isset($headers['Content-Length'])) return $headers['Content-Length'];
    
    //this one checks for lower case "L" IN CONTENT-length:
    if (isset($headers['Content-length'])) return $headers['Content-length'];

    $c = curl_init();
     
    curl_setopt_array($c, array(
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => array('User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3'),
        ));
   
   curl_exec($c);
    
    $size = curl_getinfo($c, CURLINFO_SIZE_DOWNLOAD);
    
    return $size;
        
    curl_close($c);

}


/*checks content type header to see if it is
   an HTML page...
*/

function check_if_html($url){
     $ch = curl_init($url);

     curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
     curl_setopt($ch, CURLOPT_HEADER, TRUE);
     curl_setopt($ch, CURLOPT_NOBODY, TRUE);

     $data = curl_exec($ch);
     $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE );

     curl_close($ch);
     
     if (strpos($contentType,'text/html') !== false)
   return TRUE;  // this is HTML, yes!
  else
     return FALSE;
}

PHP Interview Questions And Answers

Using the HTTP Content-Type Header

But how do we check to see if a webpage is an HTML page? Clearly we can’t just look at the URL by itself, because a PHP page, JSP page, etc. are all HTML pages, but the file extension does not tell us that. Well, once again we can use the HTTP headers to our advantage – in this case, we just have to take a look at the HTTP Content Type header.
And, if the Content-Type header is equal to “text/html”, then we know that we are dealing with an HTML page. But if the Content-Type header for the URL is not equal to “text/html”, then we know that we are dealing with a single file resource, and we can just return the size.
Let’s write some code in PHP that will tell us if a given URL is actually an HTML page by checking the HTTP headers. Here is a PHP function that will do that for us:
function check_if_html($url){
     $ch = curl_init($url);

     curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
     curl_setopt($ch, CURLOPT_HEADER, TRUE);
     curl_setopt($ch, CURLOPT_NOBODY, TRUE);

     $data = curl_exec($ch);
     $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE );

     curl_close($ch);
     
     if (strpos($contentType,'text/html') !== false)
   return TRUE;  // this is HTML, yes!
  else
     return FALSE;
}
In the code above, we just use a simple cURL connection to the URL to retrieve the headers, and then check the contentType header to see if it has the text “text/html”. If it does, then we return true, otherwise we return false.
Then, we can add some code that will actually call the function to determine if a URL points to just a single resource file:
/*
check to see if the URL points to an HTML page,
if it doesn't then we are dealing with a single
file resource:
*/
if (!check_if_html($URL))
{
$totalSize = get_remote_file_size($URL);

echo "Final Total Download Size: $totalSize Bytes ";

$totalNumResources += 1;  //single resource is an HTTP request

echo "  Final total HTTP requests: $totalNumResources" ;

return;
}

How to find the total number of HTTP requests

We mentioned that we would need to find the total number of HTTP requests generated by a given URL – let’s figure out how to write some code that will do that for us. It’s clear that we must have some variable that maintains a total count of all HTTP requests, and this variable will be incremented as we come across more and more HTTP requests.
We know that images will be wrapped in an “img” tag – so if we just do a search for all img tags we can take a look at the src attribute, and find the size of any given image. For each image we find, we can increment the variable that holds the total count of the HTTP requests. We can also do the same for CSS files – they will be referenced inside “link” tags, and also for JavaScript files, which will be referenced inside “script” tags.
We will need to use the simple HTML DOM parser that we discussed earlier in order to find all of the references to CSS, Javascript, and image files. Here’s what the code looks like – note that we are using the simple HTML DOM library functionality to parse through the HTML. Also note that we are using a variable called $totalNumResources to hold the total number of resources, and another variable called $totalSize to hold the total size of all of the resources:
include('simple_html_dom.php');

$URL = $argv[1];

// Create DOM from URL or file
$html = file_get_html($URL);

// find all images!!
foreach($html->find('img') as $element){

    $size = get_remote_file_size($element->src);
  
    $totalSize = $totalSize + $size;  
    
    $totalNumResources += 1;

    /*
    echo "Total Size So Far: $totalSize.\n"; 
    
    echo "total resources: $totalNumResources .\n"; 

           echo "IMAGE SIZE: $size.\n";

           echo "$element->src.\n";
       */
}

// find all CSS files
foreach($html->find('link') as $element)
{
    if (strpos($element->href,'.css') !== false) {

    $size = retrieve_remote_file_size($element->href);
    
     echo "SIZE: $size.\n";

     $totalSize = $totalSize + $size; 
        
     $totalNumResources += 1;
     }
}

// find all script tags
foreach($html->find('script') as $element)
{
  //make sure this is javascript
  if (strpos($element->src,'.js') !== false) {
    $size = get_remote_file_size($element->src);
   
     echo " Javascript SIZE: $size.\n"; 

     $totalSize = $totalSize + $size;   
       
      $totalNumResources += 1;
   }
}

PHP Interview Questions And Answers

Understanding resources

If you are confused by what exactly is meant by the term “resource” in the question above, then you should just think of a web resource as a generic term for a file. So, a CSS file, a Javascript file, an HTML file, a SWF (a file used for Adobe Flash) file, an image file (jpg, png, etc) – each of these is a different type of resource, and as you know there are many more types of resources on the web.

The difference between single file resources and other resources

The question specifically calls HTML files complex resources because of the simple fact that HTML documents are complex – they can contain many references to single file resources like image files, and SWF files. A single file resource does not contain references to other resources – a jpg or gif file can not contain a reference to another file, and that is why they are both considered single file resources. An HTML file, on the other hand, is also considered a resource itself, but because it contains references to other resources, it is not considered to be a single file resource.
In order to retrieve a resource from the web server where that resource is stored, a web browser has to make an HTTP request. Read on to understand more about HTTP requests.

What exactly is an HTTP request?

The question asks for two major things from a URL – the total number of HTTP requests and the total download size for all requests. The download size is easy enough to understand, but you may be confused by what exactly is meant by an HTTP request. HTTP is the protocol used to communicate on the web. When you visit a webpage, your browser will make an HTTP request to the server that hosts that webpage, and the server on which the webpage is hosted will respond with an HTTP response.
But, what is important to understand here, is that your browser will probably have to make multiple HTTP requests in order to retrieve a single HTML page at a given URL, because that webpage will probably have some CSS files to go along with it, some Javascript files, and probably some images as well. Each one of those resources is a separate HTTP request – 2 image files, 2 Javascript files, and 2 CSS files means 6 separate HTTP requests. In HTTP, only one resource can be requested at a time – so we can not have 1 request for 6 different resources, instead we must have 6 requests for those 6 different resources.
So, for the purpose of this interview question, we have to find out the number of HTTP requests that will be made for a given URL – hopefully what that means is now clear to you. We’ll go more in depth on this later – and show some actual code – as we cover some other things as well.

How to find the download size of a file?

The question also asks us to find the total download size of a URL. But what if that URL passed into the script just points to a single file resource like a JPG file or a GIF file? Well, for a single file resource we just need to find the size of that particular file and then return it as the answer, and we are done. But, for an HTML document we will need to find the total size of all resources that are embedded and included on the page and return that as the answer – because you must remember that we want the total download size of a URL.
So, let’s write a PHP function that will return the download size of a single file resource. How should we approach writing this function – what is the easiest way to find the download size of a single file resource on the web?
Well, there is an HTTP header called “Content-Length” which will actually tell us the size of a particular resource file in the HTTP response (after the resource is requested). So, all we have to do is use PHP’s built in “get_headers” function, which will retrieve all the HTTP headers sent by the server in response to an HTTP request.
The get_headers function accepts a URL as an argument. So, the PHP code to retrieve the “Content-Length” header would look like this:
function get_remote_file_size($url) {

$headers = get_headers($url, 1);
    
if (isset($headers['Content-Length'])) 
       return $headers['Content-Length'];
    
    //checks for lower case "L" in Content-length:
if (isset($headers['Content-length'])) 
       return $headers['Content-length'];


}
But, there is actually a problem with this code: you will not always receive the Content-Length header in an HTTP response. In other words, the HTTP Content-Length header is not guaranteed to be sent back by the web server hosting that particular URL, because it depends on the configuration of the server. This means that you need an alternative that always works in case the approach above fails.

An alternative to using the content-length header

Well, we can actually download the file ourselves and then just get the download size for that URL. How can we do this? Well, this is where we can use cURL as we discussed above. Once we download the resource, we can retrieve the download size using the CURLINFO_SIZE_DOWNLOAD parameter. So, using this approach as a backup to our first approach, we can come up with this code (the code in red below is the new code):
function get_remote_file_size($url) {

 $headers = get_headers($url, 1);
    
    if (isset($headers['Content-Length'])) 
       return $headers['Content-Length'];
    
    //checks for lower case "L" in Content-length:
    if (isset($headers['Content-length'])) 
       return $headers['Content-length'];

//the code below runs if no "Content-Length" header is found:


    $c = curl_init();
    curl_setopt_array($c, array(
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => array('User-Agent: Mozilla/5.0 
        (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.3) 
        Gecko/20090824 Firefox/3.5.3'),
        ));
    curl_exec($c);
    
    $size = curl_getinfo($c, CURLINFO_SIZE_DOWNLOAD);
    
    return $size;
        
    curl_close($c);

}

How should we parse HTML in PHP?

What exactly is meant by the sentence “For a complex resource such as an HTML document, the script would need to parse it to find references to embedded, included resources: javascript files, CSS files, iframes, etc.”?
Well, as you probably know, an HTML page often uses other files to render the HTML page – like CSS file(s) for styling, Javascript file(s) for adding more functionality to the HTML page, and so on. But the question is how do we take an HTML page and find all of those resources in the HTML page. Of course, this is easy to do if we are reading the HTML page with the human eye. But, we want to find these resources using a program that will read the HTML for us. This is actually more complicated than it seems – and the process by which a program (like PHP) reads an HTML file and analyzes the text to extract meaningful data (like resources) is known as parsing the HTML. Any text can be parsed, but we are exclusively focused on HTML for the purpose of this interview question.
Parsing HTML in PHP is definitely something that you do not want to do on your own, because it is so complex. The best way to parse HTML in PHP is to use a library that already exists – because writing an entire library from scratch to do this would obviously be considered way too much work for an answer to an interview question.
Note that the question states that “You may not use any 3rd-party code that performs the entire task described below”. This just means you can not use 3rd party code to perform the entire task – but using a PHP library to help you with part of this question is perfectly OK. Of course, you should clarify this with your interviewer if you are in doubt, but we know for sure that for this particular question there’s no way that the interviewers would be expecting you to perform this task without using a library to help you parse the HTML.
Note that the instructions say: “For a single-file resource such as an image or SWF, the script would simply report on the total size of the document.”
This means that if the URL is single file resources like an image file, we can just return the size of the file and we are done. But, how can we distinguish between a single-file resource and a non-single file resource? Well, we could just say that all non-HTML pages are single file resources. That statement is not entirely true, as you can read about in part 3, but we will pretend it is for the sake of keeping things simple.
But wait, you might be thinking – what about PHP, JSP, ASP and all of those pages? Well, of course there is some application specific logic embedded in those pages, but once those pages are rendered in a browser they are all HTML pages, regardless of what their file extension may be.
So, all we have to do in order to determine if a URL points to a single file resource is to see if it is an HTML page – if it is not an HTML page, then we know that the file is a single resource file.

PHP Interview Questions And Answers

Here we present some more challenging practice PHP interview questions and answers that were asked in a real interview for a PHP web developer position. These questions are really good to not just test your PHP skills, but also your general web development knowledge. We think that you will benefit a lot, and gain some good practice by going through these questions. The questions are for intermediate to somewhat advanced PHP software engineers, but even if you are just a beginner or fresher you should be able to understand the answers and explanations we give – but you may not be able to come up with the answers on your own. Here is the first part of the question – read it carefully to really understand it, and we give a simple, easy to understand explanation of everything in this question:
Write a PHP script to report the total download size of any URL. You may not use any 3rd-party code that performs the entire task described below.
No HTML interface is necessary for this exercise; you can write this as a command-line script that accepts the URL as an argument.
For a single-file resource such as an image or SWF, the script would simply report on the total size of the document.
For a complex resource such as an HTML document, the script would need to parse it to find references to embedded, included resources: javascript files, CSS files, iframes, etc.
The goal of this exercise is to output the following information for a given URL:
- total number of HTTP requests
- total download size for all requests

So, there are 2 primary goals that this question asks us to solve: For any URL, find the total number of HTTP requests generated by that URL, and also find the total download size for all requests. You may not understand what is meant by an HTTP request, but don’t worry we explain it all below.
We’ll have to break down this question into more manageable pieces since it is a lot to comprehend. So, we’ll go with the divide and conquer approach. Let’s start with the easier parts of the question first.

Accepting arguments in PHP scripts


The question says that “No HTML interface is necessary; you can write this as a command-line script that accepts the URL as an argument”.
So, let’s just say that we want to just write this as a command line script. The question is how do we retrieve arguments inside a PHP command-line script?
Well, if we plan on having the script called from the command line as “ourscript.php www.theurl.com”, where the URL is passed as an argument, then inside the PHP script we can grab the URL value by using the PHP variable “$argv[1];”. Inside our PHP script the code to retrieve the URL passed in as an argument would look like:
/*  If this script is invoked as ourscript.php www.theurl.com,
     then $argv[1] will hold the value www.theurl.com, and 
     that value will be stored in the $URL variable as well
*/

$URL = $argv[1];

That’s very simple code – now, let’s move on to other parts of the question.

How to connect to a URL in PHP?

It should also be clear that we will need to somehow be able to connect to a URL and view the contents of the page that the URL points to. What is the best way to do this? Well PHP provides a library called cURL that may already be included in your installation of PHP by default. cURL stands for client URL, and it allows you to connect to a URL and retrieve information from that page – like the HTML content of the page, the HTTP headers and their associated data, etc. You will see the use of cURL in our code below – don’t worry if you’ve never used cURL before, it’s fairly easy to understand!