• Home
  • About
  • Who Am I?
  •  

    PHP : CURL Insight and a PHP Alternative Example

    February 26th, 2007

    CURL has become increasingly popular over the past few years specially because of the fact that the web is becoming an active entity rather than a passive one , as it was in the yester years. CURL is a wonderful tool to communicate with other websites. CURL is also widely used in those “auto comment submit” type scripts. It makes the life of PHP developers easy. Alot of developers just consider it as a magic tool where as its nothing more than a way to format the request headers and play around with the response headers. Lets take a brief look at the insides of some of the CURL functions and what it really does. This article will be useful for situations where the curl library is not installed on the server.

    $ch = curl_init();
    Create the curl handle for use later.

    curl_setopt($ch, CURLOPT_URL,”http://www.abc.com/hello.php”);
    Tell curl the url you want to process.

    curl_setopt ($ch, CURLOPT_HEADER, true);
    Tell curl if it needs to return the response header as well along with the data.

    curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, true);

    Tell curl if it should oblige with the “Location:xyz.php” type response header command.

    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    This is the connection timeout limit.

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    Tell curl if it should return the data or not.

    curl_setopt($ch, CURLOPT_USERAGENT, “Mozilla/4.0 (compatible; MSIE 6.0;Windows NT 5.1)”);
    Put the user agent type in the request header. This identifies what type of browser is requesting the page

    curl_setopt($ch, CURLOPT_REFERER, “http://www.google.com”);
    Put the referer url in the request header.Referer carries the page url where the user clicked on a link to request this page.

    curl_setopt($ch, CURLOPT_COOKIEJAR, “cookies.txt”);
    Provide the file name where curl will store the cookies sent by the web server in response headers.

    curl_setopt($ch, CURLOPT_COOKIEFILE, “cookies.txt”);
    Provide the file name where cookies are stored , and curl will send the cookies in there in the request headers.

    curl_setopt($ch, CURLOPT_POSTFIELDS, array(’username’=>’abc’ , ‘pass’=>’xyz’));
    Provide the post data if any as array , curl will put it in the request headers.

    curl_setopt($ch, CURLOPT_PROXY, “11.11.11.11:8080″ );
    Tell curl if it should send the request via a proxy , provide the ip and port.

    curl_setopt($ch, CURLOPT_PROXYUSERPWD,”user:pass”);
    If the above proxy requires authentication , provise the username and password here.

    $data = curl_exec($ch);
    Execute curl with all the above options and put the data in the $data variable.

    curl_close ($ch);
    Close the connection

    Now lets try to make some code which attempts to do the above with PHP.Please note that i am not trying ot create a full fledge CURL alternative here , i am just showing by example that it can be done easily with PHP , all you need to do is have some experience with headers. This is a not a perfect example script , so feel free to experiment around with it to get desired results.

    You can download the below code if my visual presentation skills with wordpress dont strike you as too good :) - Download the PHP CURL Alternative Example

    Code (php)
    1. <?
    2. $proxyip = "abc.com" ;
    3. $proxyport = "8080";
    4. $proxyuser= "proxy";
    5. $proxypass = "pass";
    6. $urltoprocess = "http://www.xyz.com/testit.php";
    7. $cookiefile = "cookies.txt"; // file must be set to be writable
    8. $referer = "http://www.google.com";
    9. $useragent = "Mozilla/4.0 (compatible; MSIE 6.0;Windows NT 5.1)";
    10. $returntransfer = true; // — show return data
    11. $showresheader = true; // –show response header
    12. $shoreqheader  = true; // –show request header
    13. $parseurl = parse_url($urltoprocess);
    14. /////////////////
    15. //— make the post data string here
    16. $poststr = "";
    17. $postdata = array(‘username’=>‘abc’ , ‘pass’=>‘xyz’);
    18. foreach($postdata as $fldname => $fldval){
    19. $poststr .= "$fldname=".urlencode($fldval)."&";
    20. }
    21. /////////////////
    22. $contentlen = strlen($poststr);
    23. //– make the request header below
    24. //— check if proxy is to be used
    25. if($proxyip && $proxyport){
    26. $requestheader = "POST  $urltoprocess HTTP/1.1rn";
    27. $requestheader .= "Host: $proxyiprn";
    28. /////////////////
    29. if($proxyuser && $proxypass){
    30. $requestheader .= "Proxy-Authorization: Basic ".base64_encode("$proxyuser:$proxypass")."rn";
    31. }
    32. }else{
    33. $requestheader = "POST  $parseurl[path] HTTP/1.1rn";
    34. $requestheader .= "Host: $parseurl[host]rn";
    35. }
    36. //////////////////
    37. if($referer) $requestheader .= "Referer: http://www.google.comrn";
    38. if($useragent) $requestheader .= "User-Agent: $useragentrn";
    39. /////////////////
    40. //–add cookies to request header if cookies are to be used
    41. if($cookiefile){
    42. $allcookies = implode("" , file($cookiefile));
    43. if($allcookies){
    44. $requestheader .= "Cookie: $allcookiesrn";
    45. }
    46. }
    47. //////////////
    48. //–add post data to request header if any
    49. if($poststr){
    50. $requestheader .= "Content-Type: application/x-www-form-urlencodedrn";
    51. $requestheader .= "Content-Length: $contentlenrn";
    52. $requestheader .= "rn";
    53. $requestheader .= $poststr;
    54. }
    55. //////////////
    56. if($showreqheader){
    57. echo "<pre>";
    58. echo $requestheader;
    59. echo "</pre>";
    60. }
    61. /////////////////
    62. if($proxyip && $proxyport){
    63. $fp = fsockopen($proxyip , $proxyport , $errno , $errstr , 10);
    64. }else{
    65. if(!$parseurl[port]){
    66. if($parseurl[scheme] == "http") $parseurl[port] = 80;
    67. if($parseurl[scheme] == "https") $parseurl[port] = 443;
    68. }
    69. $fp = fsockopen($parseurl[host] , $parseurl[port] , $errno , $errstr , 10);
    70. }
    71. /////////////////
    72. /////////////////
    73. if(!$fp){
    74. echo "$errno : $errstr <br>";
    75. }
    76. /////////////////
    77. /////////////////
    78. fputs($fp , $requestheader);
    79. while(!feof($fp)){
    80. $raw .=fgets($fp , 1024);
    81. }
    82. fclose($fp);
    83. /////////////////
    84. /////////////////
    85. $setcookies = "";
    86. if($raw){
    87. $expl = preg_split("/(rn){2,2}/", $raw, 2) ;
    88. $header = $expl[0];
    89. $data = $expl[1];
    90. /////////////////
    91. /////////////////
    92. if($cookiefile){
    93. $headlines = explode("rn" , $header);
    94. foreach($headlines as $headline){
    95. if(substr_count($headline , "Set-Cookie")){
    96. $setcookies .= trim(str_replace("Set-Cookie: " , "" , $headline))."; ";
    97. }
    98. }
    99. }
    100. }
    101. /////////////////
    102. /////////////////
    103. if($setcookies){
    104. $fp = fopen($cookiefile , "w");
    105. fwrite($fp , $setcookies);
    106. fclose($fp);
    107. }
    108. /////////////////
    109. /////////////////
    110. if(!$returntransfer){
    111. $data = "";
    112. }
    113. /////////////////
    114. /////////////////
    115. if($showresheader){
    116. $data = $header."rnrn".$data;
    117. }
    118. /////////////////
    119. /////////////////
    120. echo $data;
    121. /////////////////
    122. ?>


    PHP : The “Headers Already Sent” error , a brief look at Headers!

    February 25th, 2007

    Every beginner PHP programmer comes across the “headers already sent” error and then they google to find out how to get rid of it. What they dont try to understand is the root level logic behind that error. Surprisingly alot of junior PHP programmers have no idea what headers are.

    I will try to explain in brief what headers are actually. I am not an expert on headers but what i put here is what i know from a little bit of experience.

    Every HTTP/HTTPS web page request goes to the relevant web server (Apache , IIS etc ) and then the web server responds with the requested page. COOL!!! BUT how do the web server know what page is requested and what form data has been posted etc? HEADERS!

    Headers are the means of communication between a browser and a web server. A normal web request from a browser for http://www.abc.com/index.php would look something like this in headers.

    GET /index.php HTTP/1.1
    Host: www.abc.com
    Connection: Close

    The first line tells the web server that what transmission method is used GET or POST. Then the page name wanted and the protocol version used.
    The second line tells the web server what domain that page should be under, this way apache can look inside its virtual hosts list and see what domain resides in which directory. So if www.abc.com resides in /home/abc/public_html , then the page requested becomes /home/abc/public_html/index.php.

    The third line tells the server that after the request is processed the connection will be closed.

    So that was a simple request. Now its the servers turn to respond, in our case the page is a .php page , so the php engine will process the requested page and send the response. Before any of the html is sent back to the browser , PHP sends in some information about the server and the data coming going through. Here is a sample response header.

    HTTP/1.0 200 OK
    Date: Sun, 25 Feb 2007 21:28:38 GMT
    Server: Microsoft-IIS/6.0
    Content-Type: text/html
    Content-Length: 4293
    Connection: close

    First line gives the HTTP status code of the response. “200 OK” in this case. Which means all good , i found the requested page and i have processed it for you and i am going to send it through. A list of status codes can be found here. Next line is ofcourse the date and time of the server, then comes the name of the web server in use. Next line is content type , which you are probably already familiar with. Content type tells the browser what sort of data is going to come through , so that the browser can show it accordingly. In this case it is text/html , which the browser will show happily. Next comes the content length , ofcourse this is byte size of the data that is going to flow through. Last line as before tells the browser the connection will be closed once the data goes through.

    Once the response header is complete , the php script output follows. So important thing to remember header first and then the data from your script.

    The PHP header() function basically you can add to the above header response from the server.For instance when you type in your php script..

    header(”Location:login.php”);

    You are basically adding a line to the above response header..

    Location:login.php

    Which means that please goto login.php for further processing and the browser obliges and heads to login.php.

    When your php script even sends one ” ” (space) basically the data has started to flow to the users browser, as we know before any data flow the header goes out first. Hence that means the header has been sent to the browser, followed by your ” “(space) character. Now once the header has been sent and PHP sees some command like header(”Location:goto.php”) , PHP says … excuse me sir but you have already started to send output from your script , thus i have already sent out the response headers , now how do you expect me to add that line to the reponse header ?

    To overcome this problem alot of programmers use ob_start() at the top , basically telling PHP to buffer the output untill the end of the script or flushed explicitly with ob_end_flush or ob_flush. So basically no output is actually sent to the browser and the header command works fine. Now gentlemen that works fine and its a wonderful utility to have at your disposal BUT ….. if you are using ob_start() to get rid of header already sent errors , then you have a flow problem in your script. Fix the flow instead of just using ob_start as a quick band aid , you wont become a good programmer and last in the long run relying on shortcuts!

    The ob_start function is best left to greater uses like using it for compression or using it with a callback function to process your output before sending out the script output or various other things.

    Hope this article helps someone out there!



    Practical Tips on Reducing Load of MySQL Queries

    February 13th, 2007

    Alot of PHP/MySQL programmers out there , specially the ones just starting out make some mistakes while using queries. The ideas i am going to outline aren’t just limited to MySQL , they can be equally applied elsewhere as well. We need to keep in mind the fact that MySQL will use more RAM and CPU than it should if inefficient queries are written.

    • For instance one common mistake is to use “SELECT * from table1” , unless you don’t need to use all of the fields i strongly suggest against it. Use something like “SELECT field1,field2 from table1
    • Make sure you know what you are doing when using JOINs. Use “explain” to see how many rows are actually being scanned for the query to execute and bring the result. A lot of times its better to break the query up into several queries. JOINS ARE HEAVY!
    • I have seen people use order by clause in queries where they need to get just the count of the records. That’s totally unintelligent. Order by clause uses up RAM as well to sort the data. Avoid it where it can be avoided.
    • Saving images in DB is probably not a really good idea after all. Atleast I think so. If you can , doesn’t mean you should.
    • Integer primary keys are faster than making username the primary key or something similar.
    • Fixed length fields are processed faster than variable length fields.
    • Use indexing wisely. Indexing helps in query the database faster BUT insertion and updates are slower.
    • Sometimes it better not to create text book database structure aka normalization , sometimes a little redundancy can help minimize number of queries AND/OR load on database, specially when dealing with large databases.
    • Keep in mind that in the loop while($array=mysql_fetch_array($queryresult)) , the transaction will keep the query open until the end of the loop. So if there is some heavy processing happening inside the loop on the result data, it is probably a good idea to first run the query loop and store the data you want to process in arrays and then later on process on the array. I find this technique helpful on many occasions.
    • Using mysql_pconnect doesnt always help .
    • Using mysql_free_result is probably a good idea.
    • mysql_insert_id is a useful function to get newest primary key of the record , rather than using “….order by id desc limit 1″
    • If you know you will be using some mysql field data alot , like the username of the logged in user , its always a good idea to store it in session , rather than banging on mysqls door again and again for it.
    • ENUM field type is very useful , just like fixed length fields. Data processing on ENUM fields is quite fast.
    • Using count(*) in queries instead of mysql_num_rows is faster i believe.
    • I believe if you are storing signup dates etc , its probably a good idea to have the field as integer instead of datetime and put in mktime() value. This only applies to current and future dates. In cases where past dates are possible datetime should be used. As you never know if that date can be earlier than 1970. Storing mktime gives you faster processing and manipulation of data is easier as well in PHP with the date() function.
    • Dont use fulltext unless you really have to.
    • And finally DO USE PRIMARY KEYS , dont be affraid to use them , they can help you down the road. For instance “DELETE from table1 WHERE id = 1″ and “DELETE from table1 where firstname=’php’ and lastname=’rox’” , the first query i reckon will run faster.

    Those are all i can think of right now. Please remember i am not an expert on MySQL , the above are based on professional experience with PHP and MySQL. Another thing to remember here is , all of these points might seem insignificantly small but when piled up together. They can cause major havoc. Specially when large databases are question.

    Hope the tips can really help someone.



    PHP - Recursive file and directory deletion

    February 2nd, 2007

    I use this 2 functions to delete files and directories recursively. Some of you may find it usefull when

    you have to delete a directory which has files and sub directories inside it. Can come in handy i guess :)

    Code (php)
    1.  
    2.    //use it like this.
    3.    $dirstodelete = array();
    4.    recursiveDelete("dir/to/delete"); // deletes the files and makes a list of directories to    delete
    5.    delDirs(); //deletion of directories
    6.         //////////////////
    7.         //////////////////
    8.    function recursiveDelete($dir){
    9.         global $dirstodelete;
    10.         $dirstodelete[] = $dir;
    11.         if (is_dir($dir)) {
    12.             if ($dh = opendir($dir)) {
    13.                 while (($file = readdir($dh)) !== false) {
    14.                     if($file != ‘.’ && $file != ‘..’){
    15.                         $fullpath = $dir."/".$file;
    16.                                                 if(is_dir($fullpath)){
    17.                             recursiveDelete($fullpath);
    18.                             $dirstodelete[] = $fullpath;
    19.                         }else{
    20.                             @unlink($fullpath);
    21.                         }
    22.                     }
    23.                 }
    24.                 closedir($dh);
    25.             }
    26.         }
    27.     }
    28.         //////////////////
    29.         //////////////////
    30.     function delDirs(){
    31.         global $dirstodelete;
    32.                 $dirstodelete = array_reverse($dirstodelete);
    33.         if(count($dirstodelete)){
    34.             foreach($dirstodelete as $onedir){
    35.                 @rmdir($onedir);
    36.             }
    37.         }
    38.     }