Thursday, 12 April 2012

21 errors of a PHP-programmer. Part II




The following 7 errors (#14-8) are treated as serious ones. They result into considerable reduction of code execution and scripts safety; the code becomes even more confused.
One of the main advantages of PHP is its disadvantage at the same time: PHP is very easy to learn. This attracts many people but in spite of its false easiness its rather difficult to learn right and effective usage of this language.
As a rule we deal with insufficient programming praxis. Inexperienced programmers face the necessity of complicated web-applications creation. Thus the mistakes are frequently done which an experienced programmer could evade such as unjustified usage of printf() function or wrong usage of PHP semantics.
In this series including three articles the most typical from our point of view errors are presented. These errors may be classified on some categories from non-critic to the fatal ones. Together with these errors analysis the ways of their evading are described and also some little tricks which have been collected for many years of programming praxis are presented. 

Audience of the article

This series of articles is meant for those PHP-programmers who want to evade the mostly common errors in the code writing. The reader is at least supposed to know general PHP syntax; some experience of practical language usage is also very desirable.

Introduction

One of the main advantages of PHP is its disadvantage at the same time: PHP is very easy to learn. This attracts many people but in spite of its false easiness its rather difficult to learn right and effective usage of this language.
As a rule we deal with insufficient programming praxis. Inexperienced programmers face the necessity of complicated web-applications creation. Thus the mistakes are frequently done which an experienced programmer could evade such as unjustified usage of printf() function or wrong usage of PHP semantics.
In this series including three articles the most typical from our point of view errors are presented. These errors may be classified on some categories from non-critic to the fatal ones. Together with these errors analysis the ways of their evading are described and also some little tricks which have been collected for many years of programming praxis are presented.
Part I: 7 childish errors are described (21-15 backwards according to the grade of their importance in our classification). Such errors dont cause serious problems but they reduce effect of programs work and are also expressed in a bulky difficult to read code which is also difficult to change.
Part II: The next 7 error (14-8) which are classified as serious. They lead to the considerable reduction of codes completion speed and scripts safety reduction; the code becomes even more complicated.
Part III: Description of the last seven fatal errors. These errors are conceptual on their nature and cause errors described in the 1st and 2nd part of the article. They include such errors as insufficient attention paid to the project as a whole and to the programs code as their part.

14. Neglecting rules of names giving

One of the most serious mistakes of a programmer is unreasoned system of names giving for the variables of a project. You often have to spend a lot of time on the codes analysis only because of the reason the author decided to insert into a program variables $fred and $barney instead of expected $email and $name. Now Im telling about a real project in which a real programmer decided to name all the variables of the project after the characters of cartoon "Flinstones" (it isnt a joke).
The name which youll give to the variables and functions of a program will mostly define readability of its code. The mostly widespread errors are the names which can be:
  • too long or, on the contrary, too long;
  • without notional connection with the context of a program;
  • not taking account of register dependence;
  • slowing down analysis and reading of a code (especially this concerns functions names).

Naming of variables

Register dependence
In PHP names of variables depend from register which means that $user and $User are two entries in the script variables list. But some programmers use this fact actively and produce variables having the same names but using different registers letters. Its a disgusting habit. Register of letters never should be the only difference between two variables. Each variable must have a unique name within its action field.
Extremely short names
For definition of variables many programmers use abbreviation which can be understood by themselves only. They are sorry afterwards as the sense of contraction in lost in the time of its creation. A name of a variable should reflect the character of its meaning i.e. its contents and by signified with full words or common shortenings.
Extremely long names
On the other hand, there are some cases of long names misusage. The mostly common rule: name of a variable should consist of maximum two words. We can separate these words by putting understrike (i.e. "_") or writing the second word beginning with capital letter.
Example #1. Positive.
Correct naming of variables:
<?php
$username 
"sterling";  $password "secret"
$teachers = array ("Sadlon",  "Lane",  "Patterson",  "Perry",  "Sandler",  "Mendick",  "Zung"); 

foreach (
$teachers as $teacher); ?> 
Example #2. Negative.
Now well treat slightly exaggerated examples of the wrong variables naming:
<?php
$username_for_database 
"sterling";  $guMbi "secret"// for the $password 
$thelastnamesofteachers = array ("Sadlon",  "Lane",  "Patterson",  "Perry",  "Sandler",  "Mendick",  "Zung"); 

foreach (
$thelastnamesofteachers as  $TeaChER);  ?> 
Functions names
All the rules applied for the variables names are also suitable for functions. But in the case of functions the grammar realities are of great importance.
Remember that all the functions built-up and determined by a developer arent register dependent.
Usage of verbs
PHP functions can be compared with some actions done in the real world. Thus the names of the functions should reflect this action orientation i.e. be expressed with verbs. Its better in the present tense.
As an example well treat function which generates Gaussian random numbers. We are supposed to understand from its name which exactly formula is used in the number generation. Like this: generate_gaussian_rand().
Mention verbs usage in the name of the function. Its namely a verb that puts the function into the correct context:
<?php list ($num1$num2) = generate_gaussian_rand(); 
list (
$num3$num4) = generate_gaussian_rand();  ?> 
Heres another example to compare:
<?php list ($num1$num2) = gaussian_rand_generator(); 
list (
$num1$num2) = gaussian_rand_generator();  ?> 
Do you see the difference? In the second example noun is used to signify an action. And even in case the purpose of the function still can be observed such name makes reading code more difficult.
The moral is following: use verbs!

13. Insufficiently considered work with data: data base and SQL

Its amazing to observe how many different tricks people find to organize access to data bases and get selection of results. Among all the others combinations of if-branches, dowhile cycles, multi-requests and function sql_result() calls inside of for-cycle are especially significant.
What from their point of view they are doing?
The code based on the scientific conjecture method testifies to insufficient clarity of work with data base organization. Those who spend all their efforts on the code writing (not on the correct code writing) are the clear example of this fact. Some programmers dont spend much time on the thoughtful thinking over this moment. Of course, there can be no the only true method of data selection but lots of the false ones are always sure to be found.
Errors in the organization of the data selection can be divided into three classes:
  • wrong usage of the functions for data base addressing
  • SQL errors: we request not for what we need
  • selection results treating by means of PHP
Wrong usage of the functions for data base addressing
One of the PHP-initials offered following method for getting results of selection from data base (the code given below is situated in the project after the generated SQL-requests):
<?php if (!($row sql_fetch_row ($result))) { 
    print 
"Error: no rows are found "
    exit; 


do { 
    print 
"$row[0]: $row[1]\n<br>\n"

while (
$row sql_fetch_row ($result));  ?> 
Notice: in the given and following examples $result is a descriptor of selection or indicator on it. In other words, a request has been done and definite host of rows has been got. The examples demonstrate methods of effective treating for this host.
There are two mistakes in this part of the code:
  • assertion against zero rows is an attempt to get at least one of them;
  • received data arent saved in the associative massive.
Assertion against zero rows ($result) is a wrong approach
Having set in action function sql_fetch_row() the given codes part offers indirect assertion of selection against the presence of at least one data row. But there is also direct method; this is calculation of rows quantity in the selection $result by function sql_num_rows() as it is showed below:
<?php
if (sql_num_rows ($result) <= 0) { 
    print 
" Error: no rows are found "
    exit; 


while (
$row sql_fetch_row ($result)){ 
    print 
"$row[0]: $row[1]\n<br>\n"
}  
?> 
Get rid of dowhile
First of all disappears the necessity of usage of boring dowhile as for the assertion against zero rows function sql_num_row() doesnt pull out the first row in $row and indicator is set on the beginning as before.
Once similar codes fragment was presented in PHP Source. If the selection wasnt equal to zero, function sql_fetch_row() inside of conditional block transported the first row. For fetching the rest of them you had to use dowhile because extracting of a row from the selection shifts the indicator inside of it. Thus youll first have to treat the row youve already got (do) and also after that get the second row and so on.
So what is fault of dowhile?
  • in the given example only one operator (simple output) is placed inside of dowhile cycle. Now imagine that there can be not one but ten operators. Then redactor of the code will have to search while-condition after operator do and the whole actions block inside of the cycle. This is rather unpleasant work.
  • while-condition is usually placed in at the beginning of the block, not at its end. So the codes redactor will have to pay especial attention to it when reading in order not to mix dowhile function with the pre-condition while of an ordinary cycle.
Make everything easy and clear
In the case of zero-selection function sql_num_row() unlike sql_fetch_row() does exactly what you need:
  • action sql_fetch_row(): By attempt to get the first row no rows were found. This means they dont exist in the given selection;
  • action sql_num_row(): The number of rows in the selection is equal to zero.
But how does it influence the code writing?
Lets analyze the following example where the operators within condition are written by pseudocode:
  • if(!($row = sql_fetch_row($result))){Print Error}:
  • We get the first selection row.
  • If the selection is empty, we add 0 to the variable $row; zero is logically expressed as False; hence!(0)=True; indicate an error message.
  • if(!($row = sql_fetch_row($result))){Print Error}:
  • calculation of selection rows.
  • If their quantity is less or equal to zero, we indicate an error message.
  • Otherwise we go further.
So which of two expressions is easier faster to understand? Undoubtedly, the calculation of rows is the shortest and simplest way.
What is the practical advantage of the second method? There is an inconsiderable difference in what we place within this condition we cannot get much from it.
However over 10 000 strings of your code well considered and thus simply and clearly described ideas will save a lot of time for the codes redactor (that is the first advantage). There are some other advantages: development of scripts becomes considerably faster and measured.
If your database management incentive doesnt support sql_num_row()
In fact some data base management incentive cannot support this function. We should feel sorry for all the owners of such systems. Theyll have to check selections against zero rows by means of request for the first row. But here we also recommend using Bulls variables:
<?php
$found 
false

while (
$row sql_fetch_array($result)){ 
    
$found true


if (!
$found){ 
    print 
"Error"
}  
?> 
Getting data rows: rules of effective work
The second problem of our code is usage of function sql_fetch_row() in order to fetch rows. As a result of its work this function returns an enumerated massive only. However there is also function sql_fetch_array() which returns two massivs: an enumerated and an associated one:
<?php
$row 
sql_fetch_array ($result); 
print 
$row[1]; // Second column print $row[name]; // Column name?> 
Notice: there are two points of view about advisability of single inverted commas usage by the string arguments insertion. They arent used in the given example (column name) and in the rest of the article.
Which of the functions is the most convenient for a developer? Associative massivs let the editor of the code understand clearly and unambiguously which exactly selection from the data base will be done in each concrete case. For example:
<?php if (sql_num_rows ($result) <= 0) { 
    print 
"Error: no rows are found "
    exit; 


while (
$row sql_fetch_array ($result)) { 
print 
"$row[name]: $row[phone_number]\n<br>\n"
}  
?> 
Usage of sql_fetch_row($result)
So function sql_fetch_row() has a plenty of disadvantages. However, the situation exists when in can be use without any damage for the codes clarity: when sql-request is formed by a user.
Up to the present moment we examined examples with noted request and defined by a developer. But sometimes we have a necessity in request formed by a user himself. In such cases the number selection columns is unknown to a developer.
For their effective processing its useful to use function sql_fetch_row() together with count():
<?php for ($i 0$i count($row); $i++){ 
    print 
"Column". ($i 1). $row[$i]. "\n<BR>\n"
}  
?> 
SQL errors: we request not for what we need
Practice shows that treatment of the data base selection by means of PHP is also an error. There were some cases when for the simple search by 2Mb programmers and afterwards were outraged with its snowlines. And doing a simple selection weighing two meters takes a whole eternity.
Structured Questions Language (SQL) has been specially developed for requests and fetching data from the tables within data base. The idea is concluded in the eliminating the data which arent necessary for you (by means of SQL) and fetching only those of them which are really needed for the further procession (for example, by means of PHP).
If you mention that you fetch more data than you need in your selection, this is true sign of unfinished SQL-requests.
WHERE-condition
The classical example of effective SQL-requests applying is the usage of WHERE-condition in the syntax of SQL.
Lets examine the example of the code which makes selection and puts out names and phone numbers list for all the users with id equal to 5:
<?php // In the foregoing lines
// the connection is set up $conn
// is defined as descriptor of the connection
$statement "SELECT name, phone, id FROM samp_table";  $result = @sql_query ($statement$conn); 

if (!
$result) { 
    die (
sprintf ("Error[%d]: %s"sql_errno (), sql_error ())); 


if (@
sql_num_rows ($result) <= 0) { 
    die (
"No results received"); 


while (
$row = @sql_fetch_array ($result)){ 
    if (
$row[id] &amp5) { 
        print 
"Name: $row[name]\n<br>\n"
        print 
"Phone number: $row[phone]\n<br>\n"
        break; 
    } 
}  
?>  
The given code has following drawbacks: for the search on the whole data base PHP is used; you may leave it without attention when working with data bases of smaller seize but with growth of data base you are sure to mention sudden reduction of scripts working speed.
Salvation is simple: include WHERE-condition into SQL-request:
<?php
    $statement 
"SELECT name, phone FROM samp_table"
    
$statement .= " WHERE id='5'";  
WHERE allows you applying stricter selection criteria. The arguments meaning acts in the given case as a filter. In our example it is "id=5".
Having fetched the necessary selection youll use PHP for the simple results output:
<?php if (@sql_num_rows ($result) != 1) { 
    die (
"Wrong rows number received"); 

$row = @sql_fetch_array ($result); 
print 
"Name: $row[name]\n<br>\n"
print 
"Phone number: $row[phone]\n<br>\n";  ?> 
Selection results processing by means of PHP
Often a programmer doesnt sort out the selection by request advisedly redirecting this work to PHP. Such approach isnt effective thus the sorting out by means of SQL occurs much faster than in PHP.
For sorting out the results we recommend you to use SQL (ORDER BY) syntax instead of PHP-function ksort().
Lets treat the example of ksort() usage for sorting out on name:
<?php
$statement 
"SELECT name, email, phone FROM some_table ";  $statement .= "WHERE name IS LIKE '%baggins'"
$result = @sql_db_query ($statement"samp_db"$conn); 

if (!
$result) { 
    die (
sprintf ("Error [%d]: %s"sql_errno (),sql_error ())); 


while (
$row = @sql_fetch_array ($result)){ 
    
$matches$row[name] ] = array ($row[email], $row[phone]); 

ksort ($matches);  ?> 
A question appears: why shouldnt we sort out the results during the selection? This saves us from necessity to run over the whole results massive twice.
So we delete ksort() and correct SQL-request by adding ORDER BY:
<?php
$statement 
"SELECT name, email, phone FROM some_table ";  $statement .= "WHERE name IS LIKE '%baggins' ORDER BY name";  ?> 

12. Low error resistance

There is a plenty of scripts which cannot deal with users errors at all. Their appearance such scripts owe those programmers who find no time for the correct planning of the future project and defining all the places for possible errors. At that it should be done before the scripts writing. Such imperfections result into program fail that can lead not only to getting of incorrect results but to even to the break down of a system!
Foresee the worst
Every script can break down at some critical circumstances. To minimize these risks you should:
  • check results of functions call;
  • check results of system calls;
  • set level error_reporting on E_ALL in the php.ini file.
Checking of functions call results
By the call of a function which results are further processed make sure that returnable data lie within admissible value interval.
In the example given below on the sixth cycle coil error zero division appears as $i increases on 1and $j decreases on 1. By the sixth passage $i=$j=1.
<?php
mt_srand
((double)microtime() * 10000000); 

function 
do_math ($a$b) { 
    return ((
$a $b) * 2) / mt_rand(); 


for (
$i 5$j = -5$i > -5$i--, $j++){ 
    print 
$j do_math ($i$j) . "\n"
}  
?> 
Checking of system calls results
By addressing external files and processors always check if everything works correctly.
Marvelous example to it is checking of systems reply by calling of function sql_connect(). You are to check this answer and make sure that data base connection really took place. If you dont do it, all requests to the data base cannot be completed and some data can be lost and you wont be notified about it.
<?php
$conn 
= @sql_connect ($host$user$pass); 

if (!
$conn) { 
    die (
sprintf ("Error [%d]: %s"sql_errno (), sql_error ())); 
}  
?> 
Setting up error_reporting level in file php.ini on E_ALL
Make sure that PHP has right configuration that means level error_reporting (error messages reflection) is set on the highest level. By other configuration at least while scripts debugging many error like wrong regular expression, impossible meaning slip away from your attention.
Lets turn once more to the example given in the part Checking of functions call results. Suppose that error_reporting isnt set on maximum but on, for example, E_ERROR.
Pay your attention to that in what way script realizes function do_math but doesnt inform about zero division error which nevertheless has taken place (by $i=$j=0 there simply wasnt any result output).
<?php
error_reporting 
(E_ERROR); 
mt_srand ((double)microtime() * 1000000); 

function 
do_math ($a$b) { 
    return ((
$a $b) * 2) / mt_rand(); 


for (
$i 5$j = -5$i > -5$i--, $j++){ 
    print 
$j do_math ($i$j) . "\n"
}  
?> 
Result of scripts work:
-5148.25
-5271
-323.75
-4931
-7713.5

-4702.5
-488.5
-928.5
-1394.75 
Own errors processors
As a rule PHP transmits error messages immediately into browser and doesnt let a developer suppress and intercept them. However in PHP4 youve got an opportunity to intercept such messages by means of function set_error_handler().
Function set_error_handler() is used for recording errors of your script. Now you can intercept all errors and program your own processors users warnings wont disturb you any more.
In the following example set_error_handler() appoints function error_handler() as processor on default. In case of error error_handler() is called and integrated function error_log() registers fail in the file of the log error_file.
If error of E_ERROR class occurs, scripts work finishes and an error message shows up.
<?php
// void error_handler(string type, string message, string file, int line) 
// Individual error processor is determined by function
// set_error_handler() 
function error_handler ($type$message$file __FILE__$line __LINE__) { 
    
error_log("$message, $file, $line"3"error_file"); 
    if (
$type E_ERROR) { 
        print 
"Error happened, registered."
        exit; 
    } 

set_error_handler("error_handler");  ?>  

11. Unjustified usage of objective oriented programming

Paradigm of objective oriented programming is a wonderful approach to the writing of a code. Objective oriented programming has a lot of incontestable advantages the most considerable of which is a possibility of repeated usage of a once written code. However some day we realize the fact that PHP isnt an objective oriented language.
In spite of the fact that PHP has correctly working objects support, its short-sighted and ineffective to use objects in cases where we can deal without them. Whats the reason? The reason is that support of objective oriented programming paradigm in PHP isnt full-volume.
In spite of basic elements presence, there is lack of many advanced functions in PHP (such as protected terms or covered variables) which are obligatory for real objective oriented languages (such as Java, C++).
Besides that objects support in PHP isnt perfect and very effective. This means that usage of objective oriented programming paradigm can appreciably reduce speed of program accomplishment.
Notice: In other words, working on objects script will be accomplished slower as the code inside eval() in comparison with an ordinary code. For more illustrative examples where usage of objective oriented programming has some disgusting forms we have to address advanced functions of PHP conception some of which arent even documented. So we have to stop at this.
What can we do without objective oriented programming?
If you came to PHP from Java or C++ where its difficult to create something serious without objects, you would have many difficulties in working without them in PHP as well. But be sure that serious applications can be written without methods and modes of objective oriented programming (PHP was written by means of C which, as we know, doesnt support objects).
So for those who didnt use to do without objective oriented programming well show alternative technologies for writing connected and extended applications beyond objective oriented programming paradigm:
  • Creation of API
  • Developing of naming conception (and working within it).
  • Grouping of interrelated functions into one file.
Creation of API.
Correlate programs code with three levels:
1st the working functions themselves.
2nd API functions. This level includes functions for the concrete application building.
3rd the application itself.
<?php  // MortgageRate.php (mortgage credit)

// 1st level  inner functions
// Inner functions for the optimal interest rate calculation based on time and amount of monthly payment 
function _mort_find_interest_rate ($total) { 
    if (
$total 30000
        return (
7.4); 
    elseif (
$total 30000
        return (
3.2); 
    elseif (
$total 50000
        return (
2.5); 
    else 
        return (
1.7); 

// 2nd level  API functions 

// double calculate_mortgage_rate (int money, int time, int month) 
// Calculates interest rate based on the loan value, repayment period and payment interval
function calculate_mortgage_rate ($money$time$month) { 
    
$rate _mort_find_interest_rate ($money) / 100
    
$money /= ($time $month); 
    return (
$rate $money) + $money

?> 
<?php // CalcMortgage.php

// 3rd level  application
// $money, $time and $period we get from form
include_once 'MortgageRate.php'
$price calculate_mortgage_rate ($money$time$period); 

print 
"Your interest rate for $period is equal to $price";  ?>  
Developing of naming conception and working within it.
One of the most annoying moments in developing of large applications are conflicts of names space. Classes segment it. In such a way different classes can:
  • have properties with the same names or
  • contain methods with similar names.
For example, class Phillips and class Normal can simultaneously contain method named screwdriver.
Generally before beginning of a big project its recommended to think over nomenclature for everything, particularly ways of global and regular variables distinguishing, determination of library functions and so on.
Grouping of interrelated functions into one file.
Its better to gather all interrelated API functions into one file in the same way as interrelated methods are united into a class. Such files may be represented by classes where each function represents a method of this class. So each function will have clear definition and transparent structure.
For example, you may gather all the functions connected with addressing to data base into file DB.php.

10. Unjustified usage of regular expressions

Regular expressions are a powerful tool for search and organization of data such as, for example, checking of e-mail address against correctness or URL search. But at the same time regular expressions work slower than other PHP functions which are meant for simpler tasks.
For example, for transfer of a whole string into capital letters a PHP-beginner could write following:
<?php
$URL 
"http://www.php.net"
$fp = @fopen ($URL"r"); 
if (!
$fp) { 
    die (
"Fail by opening $URL!"); 


while (
$line = @fgets ($fp1024)){ 
    
$data .= $line


@
fclose ($fp) or warn ("Fail by closing descriptor $URL"); 
$data ereg_replace ("[a-z]""[A-Z]"$data); 

print 
$data;  ?> 
However in this case using bulky and slow ereg_replace() he would have spent a lot of precious accomplishment time on the task which lighter function strtoupper() would have solved much more quickly.
$data = strtoupper ($data); 
So you are always to search more light substitute for the regular expressions as your scrips accomplishment speed increases sharply in such cases.
Everybody should know these functions
Some vitally important functions which reduce time necessary for your scripts accomplishment are enumerated here:
strtoupper(); strtolower(); ucfirst(); strtr(); str_replace(); trim(); explode(); implode(); substr(); strcmp()
By successful substitution of a regular expression with one of these functions you can expect sharp speed increase, especially in cases when strings of big size are analyzed.
9. Programming in PHP as in any other language.
Many come to PHP having big programming experience in other language such as PERL, C, Java or ASP. And they often import techniques and approaches which are not always combine well with PHP methodics.
Unfortunately some programmers dont manage to learn PHP-programming namely in the PHP-style. Instead of this they provide themselves with a minimal set of conceptions which are new to them and force PHP.
As a result of such approach we often get slow and difficult to support code. Such cases arent rare:
  • single-strings PERL. PHP is a language which is insufficiently adapted to the method all in the single string. We recommend you to split complicated cobwebs of combined functions and present them into more structured form
    Perl
    while () {
    @_ = split /:/;
    $quotes{shift} = shift;
    }
    print map { "$_: ", reverse split //,$quotes->{$_},"\n"; } keys %quotes;  
    PHP
    <?php

    $fp 
    = @fopen('php://stdin''r'); 
    if (!
    $fp) { 
        die (
    ' Fail by opening STDIN'); 


    while (
    $line = @fgets ($fp1024)){ 
        list(
    $name$quote) = explode (':'$line); 
        
    $quotes$name ] = $quote


    foreach (
    $quotes as $name => $quote){ 
        print 
    "$name: "
        print 
    implode (" "array_reverse (preg_split ('//'$quote))); 
        print 
    "\n"


    @
    fclose ($fp);  ?>  
  • Evasion from integrated functions. Many PHP-programmers who came from C dont seem to understand that PHP contains a lot of integrated functions. There aim is to set us free from kilometer-long scripts. If you wrote in C before, you would be obligatory recommended to examine technical description of PHP and find out which functions PHP can offer you to make your life easier.
  • Renaming of standard PHP-functions. Some programmers rename standard PHP functions only in order to memorize them easier. This not only reduces the speed of scripts accomplishment but also makes reading of a code more difficult.
  • Unjustified usage of objective oriented programming. PHP isnt an objective oriented language although some objects support is present. You should always remember that usage of objective oriented programming support functions considerably reduces speed of scripts accomplishment.

8. Insufficient attention paid to the safety questions

Users will never work according to our rules. So creation of an error tolerable and resistible system is completely responsibility of developers that means ours.
By development of an application you should imagine yourself on the place of an ordinary user. Examine attentively all places where users error may uncover a safety hole. Then correct the code in such a way to make program neutralize all the errors itself and get rid of potential holes. Its also important to memorize that although all errors and attacks are users guilt only you are responsible for holes or unverified data on some level.
Example: many scripts dont use integrated PHP-function mail() which provides safe e-mails sending. Instead of this mail is sent through the program sendmail by means of popen(). This makes code rather irresistible to the data distortion and represents a hole in the safety of the system (you may send /etc/passwd to the addressee).
Lets enumerate the mostly widespread holes which permit data distortion:
  • system calls. Its worth being repeated one more time. Every time you should make sure that user sends to you safe data for the system call. NEVER TRUST THE DATA YOU GET FROM USER AND CHECK THEM BEFORE PLACE THEM INTO THE SYSTEM CALL.
  • users registration. If you want to get correct results, you are to check the data youve got and its better if this checking includes some stages. First of all, this is checking of e-mail address: make sure that user rendered to you a properly working accuant. Besides that, its worth to make sure that indicated age is placed within some limits. You can be absolutely sure that there arent any people on our planet who are two hundred years old and able to use computer at the same time.
  • reception of credit cards numbers. Some programmers satisfy with the simplest algorithms; they are easy to trick. There are large specialized organizations for the credit cards verification; we recommend to use their help or resources and only after that decide if the card is accepted or not. NEVER RELY ON ALGORITHMS ONLY.
System calls safety
If the necessity in placing got from user data into system call appears, you are to check and recheck them. Make sure that data given to the system by a user dont contain dangerous elements and wont break the system with undesirable commands. For this PHP offers special function EscapeShellCmd().
Every time by a sys tem call with potentially unsafe data deactivate them by means of EscapeShellCmd():
Notice: deactivation happens by putting backslash ("\") before potentially unsafe for the system symbols (and namely: #&;?'\"|*?~<>^()[]{}$\\\x0A\xFF).
<html> 
<head> 
<title>Accuant search </title> 
</head> 
<body> 
<h1>Accuant search </h1>  
<?php  if ($name) { 
    
system (EscapeShellCmd ("lookup $name")); 
    print 
"<br>\n\n"
}  
?> 
<form action="
<?php print $PHP_SELF?>" method="GET"> 
Insert accuant for search: 
<input type="text" name="name"> 
<input type="submit" value="Find accuant"> 
</form> 
</body> 
</html>  
Notice: although EscapeShellCmd() is a very useful function you should nevertheless do special assertions depending on the type of data when you need to make sure the data youve got are safe. EscapeShellCmd() wont check the data against their correctness, it only prevents unauthorized users actions.
Intensive data verification
As a rule youd better check the string against presence of admissible symbols rather than against absence of inadmissible.
For example, check that variable $name contains only letter symbols. At that new paths of system penetration have fewer chances to leak out of your filter.
E-mail addresses verification
One of the mostly widespread types of data verification is validation of e-mail address. The most beginners limit themselves only to filter of regular expressions which they have taken from some cemetery of free of charge scripts. But regular expressions themselves arent enough if you intend to get really correct results. For the most safety you may apply some other methods:
  • verification of connection
  • interactive verification
Verification of connection
One of the methods for accuants checking against reliability without involving a user himself is an attempt to open connection with server which is indicated in the address youve got and check the presence of accuant on the given server.
Advantages
  • No users actions are needed as the operation is carried out on the program level.
  • Non-existent addresses are revealed that cannot be done by a regular expression (for example, joe@fgsdh.com).
Disadvantages
  • Only non-existent addresses are revealed. For example, if John Doe sends e-mail of these lines author (sterling@php.net), the data will be accepted in spite of the fact the address is wrong.
  • The given method works slower than regular expressions.
  • The post server of a user can be temporary out of work and thus working address will be treated as incorrect.
Interactive verification
Another way of verification is to send on the address indicated a special key and ask a user to insert this key in order to continue the registration procedure. The given method lets check not only existence of an address but also users rights to access to it.
Advantages
Its the best way to make sure that a user rendered to you correct and his own address (user should have access to the accuant indicated by registration).
Disadvantages
  • Some users actions are needed. This irritates those people who are trying to trick you.
  • As any other method this one doesnt offer us 100 per cent guarantee of safety. A user can create temporary accuant on Hotmail or Netaddress and then indicate it by registration.

Summary

In this article weve examined seven serious from the 21 mostly common errors of a PHP-programmer. So you are to evade following errors:
  • Neglecting rules of names giving: Correctly developed system of naming for variables and functions in the project results into clear and easy to extend code.
  • Insufficiently considered work with data: data base and SQL: Incorrect work of data selection testifies to insufficiently clear determined organization of work with data base. In the real life there can be no the only true method of data selection, but there always can be found a lot of the false ones.
  • Low error resistance: A code should be developed together with neutralization and consideration to all the potential errors and fails. Especial attention should be paid to the functions calls and to the system calls.
  • Misusage of objective oriented programming: PHP is a language in which objects support isnt provided in the full volume. You are not to use objective oriented programming methods as easy as you do it in Java or C++ (or even in Perl).
  • Unjustified usage of regular expressions: Regular expressions work slowly. Before you insert regular expression into a code, make sure that there is no simpler and faster salvation.
  • Programming in PHP as in any other language: You shouldnt program in PHP in the same way as you do it in C or Perl. PHP is a completed programming language and it exists on its own. So you are to learn namely the PHP-programming and not to do it in a way that could be correct for the other language.
  • Insufficient attention paid to the safety questions: Always take into account human element. Dont insert into system requests unverified data strings. Check e-mail addresses. Dont rely on the algorithms when accepting credit cards.