|Access||Adobe photoshop||Algoritmi||Autocad||Baze de date||C||C sharp|
|Calculatoare||Corel draw||Dot net||Excel||Fox pro||Frontpage||Hardware|
|Php||Power point||Retele calculatoare||Sql||Tutorials||Webdesign||Windows|
|Asp||Autocad||C||Dot net||Excel||Fox pro||Html||Java|
Top PHP Programming Mistakes - Part 2: Seven Serious Mistakes
This article is intended for the PHP programmer interested in avoiding some of the most common mistakes when applying PHP. The reader is expected to at least be familiar with PHP syntax, but should have a working knowledge of PHP functionality as well.
One of PHP's greatest strengths happens to be one of its greatest weaknesses as well: PHP is easy to learn. A lot of people are attracted to the language because of this, not realizing that it's a lot tougher to learn how to do it right.
There just hasn't been enough emphasis on good programming practice. Inexperienced coders are being asked to create and distribute complex web applications. Mistakes that an experienced programmer would avoid are all too common, such as the improper use of the printf() function or the misapplication of PHP's semantics.
In this three part article series, I present a list of 21 mistakes that I believe are frequently made and ranging in severity from non-critical down to those that can break the farm. I offer solutions, suggestions and/or comments on how to solve and prevent these errors, in addition to other tricks of the trade that I have gained over the years.
The series is comprised of the following three articles:
Part 1: Covers the first 7 'textbook' mistakes (#21-15, in reverse order of severity) on our rating list. Committing one of these mistakes, while not critical, will lead to slower and less maintainable code.
Part 2: Covers the next 7 'serious' mistakes, representing # 14-8 on our rating list. Committing one of these mistakes will lead to drastically slower run times and less secure scripts, in addition to less maintainable code.
Part 3: Covers the last 7 'deadly' mistakes. These mistakes are conceptual in nature and can represent the root cause for committing any one of the mistakes listed in Series Parts I and II. They include blunders such as not allotting enough time for a project and not having a thorough code review.
One of the most serious errors that a programmer can commit is to define a poor naming convention. I've taken over projects where I've had to spend numerous hours just trying to understand the program because the programmer decided to name its variables $fred and $barney instead of common sense names such as $email and $name. I am referring to a project where the incumbent programmer decided to give the entire program a Flinstones naming theme (no joke).
How you assign names to your variables and functions is central to building readable scripts. Many programmers make the mistake of defining variables and functions with names that:
Are too brief or too long.
Do not relate to the script's context.
Do not take into account case sensitivity.
Inhibit code readability (functions in particular).
In PHP, variable names are case sensitive, meaning $user and $User are completely different symbol table entries. Some users exploit this feature by having variables with the same name but using different cases. This is a horrible practice. Case should never be used to differentiate between variable names. Every variable name in the current scope should be absolutely unique.
Many users assign cryptic acronym names to their variables and then later regret having forgotten what they meant in the first place. Variable names should describe the content that they (will) contain, using either complete words or understandable abbreviations.
On the other hand, some users use variable names that are far too long. Generally speaking, a variable name should not be longer than two words. The two words can be separated by a '_' or delimited by having the second word begin with an uppercase letter.
The following are good examples of variable names:
$username 'sterling' $password 'secret' $teachers=array('Sadlon' 'Lane' 'Patterson' 'Perry' 'Sandler' 'Mendick' 'Zung');
The following are some exaggerated examples of poor variable naming:
$username_for_database 'sterling' $guMbi 'secret' //forthe$password
$thelastnamesofteachers=array('Sadlon' 'Lane' 'Patterson' 'Perry' 'Sandler' 'Mendick' 'Zung');
All of the concepts that apply to variable naming also apply to function naming. However, grammar is particularly relevant for functions.
Note that PHP functions whether built-in or user-defined are not case sensitive.
PHP functions are equivalent to a spoken language's verbs. Function names, therefore, should be action oriented. They should also be defined in the present tense.
For example, if you have a function that generates a gaussian random number, it should convey that it uses the gaussian distributed random number formula as follows: generate_gaussian_rand()
Note the usage of the action verb in the function name. This places the function in its proper context:
list($num1 $num2 generate_gaussian_rand();
list($num3 $num4 generate_gaussian_rand ?>
By way of comparison, consider the following:
list($num1 $num2 gaussian_rand_generator();
list($num1 $num2 gaussian_rand_generator ?>
See the difference? This second example uses a noun as the function title rather than an action statement. While the function's purpose is still conveyed, its title inhibits a fluid reading of the code.
Use a verb!
It is truly amazing the number of ways people concoct to access a database and retrieve a result set. Examples that I have seen include combinations of if statements with do .. while loops, multiple calls, and sql_result() functions inside of a for loop.
What do these people think they are doing?
Writing hit-or-miss code demonstrates a lack of focus. Individuals who direct their efforts on just getting the job done rather than on getting the job done right, end up costing their benefactors plenty of time and money down the road.
Incorrect data sampling is a good example of this problem. Some coders do not take the time to think things through. True, there might not be a single 'correct' way of data sampling, but there are plenty of incorrect ways.
This section covers the following areas under this topic:
Misapplying database functions
Misusing SQL: Not fetching what you need
Using PHP to sort the results
One PHP source advocated the following syntax for retrieving result sets from a database (presented below using a generalized set of SQL functions):
if(!($row sql_fetch_row $result)))
dowhile($row sql_fetch_row $result
Note: In the above, and subsequent examples, $result represents the handle or pointer to a query's result set. In other words, a query has already been submitted and a set of results has been extracted from a database. The examples deal with how we should effectively work with this result set.
There are a couple of problems with this code:
It checks for the 'no incidents' case by fetching rows.
It does not store the result set into an associative array.
By using sql_fetch_row() , the PHP source advocated an implicit approach to determining whether or not there are any incidents of $result. A more direct or explicit method is to count the number of rows having $result using sql_num_rows()as shown below:
if(sql_num_rows $result)<= )
while($row sql_fetch_row $result ?>
First and foremost, the nasty do..while loop is no longer needed because when using sql_num_row(), we do not initially fetch the first row of the result set into $row when checking for the empty set.
The PHP Source presented an example where, if the result set was not empty, the set's first row would be received by executing sql_fetch_row() within the if statement. The do..while structure is required under these circumstances because a fetch to the database will always advance the counter. Therefore, you must process the first row ('do') initially since it has already been retrieved. The next fetch execution would retrieve the second row and so on.
Why is the do..while considered 'nasty'?
The example only presents one loop action – a single print statement. Imagine if we had 10 actions in the loop. A code reviewer would have to search through the code for the while condition after the do statement. An annoying exercise.
While conditions generally begin a structure rather than completing it. A reviewer must be extra careful not to confuse the ending while condition of a do..while structure for the beginning while condition for a standard loop.
For the emply result set case sql_num_rows()gets straight to the point, while sql_fetch_row() does not:
sql_fetch_row()says 'I found no rows in the result set. This must mean that there are none.'
sql_num_rows()says 'The number of rows in the result set is 0.'
But what difference does this really make?
Consider the same comparison, but this time within the context of the if condition and expressed in Pseudo-code:
if(!($row = sql_fetch_row($result)))
Fetch a row from the result set.
If the result set is empty, assign $row a value of 0; Zero has the boolean value of False, so consequently !(0) = True; Print the error message.
Otherwise, if the set is not empty, retrieve the first row and assign it to $row $row is not zero and has a boolean value of True. Consequently !(True) = False, and continue with the do..while structure.
Count the number of rows in the result set.
If less or equal to 0, Print the error message.
Which expression is easier to comprehend? Clearly, counting the number of rows is more straight-forward.
What is the practical difference now? From one simple if statement, there is not much to be gained one way or the other.
However, for over 10,000 lines of script code, taking the time to think of the clearest way of writing code can save a reviewer hours of analysis (to name just one benefit). Other benefits can include faster and more fluid development of your scripts.
Some DBMS's may not support the sql_num_row() function. I offer my sympathies to you if your DBMS happens to be one of them. You will have to search for the empty set case by fetching rows. However, even under these circumstances it is preferable to use a boolean variable as follows:
while($row sql_fetch_array $result))
A second problem with this code is its use of the sql_fetch_row() function to fetch the result set. The sql_fetch_row() function will only return a numerically indexed array. The sql_fetch_array() however, returns both a numerically and string indexed array as follows:
$row sql_fetch_array $result);
print$row name //Thenamecolumn
Note: There are different conventions regarding the use of quotation marks when adding a string argument. In the name column above and throughout this article, it was decided to leave them out.
From a developer's point of view, which function will provide a coder with a more useful result? String indexed arrays enable a reader to understand exactly what is being fetched from the database just by reading the code, as shown in the corrected example below:
if(sql_num_rows $result)<= )
while($row sql_fetch_array $result ?>
I'm not really a fan of the sql_fetch_row() function. However, there is one situation in which it may be used without decreasing readability – when the user defines the query.
The examples to this point have been dealing with a known query that was generated by the developer. Sometimes you may have the user define his/her own query. Under these circumstances you will not know the number of columns in the result set.
Therefore, you can use the sql_fetch_row() function along with the count() function, to effectively process the columns in a row:
for($i $i<count $row $i ?>
As a matter of practice, it is simply wrong to use PHP to process the rows of an entire database. I've seen cases where people had used PHP to run a simple search over a 2MB database and then wonder why the language was so slow. Fetching 2 MB of data from the database will take forever.
Standard Query Language (SQL) was specifically designed to query and retrieve data samples from your tables. The idea is to filter out the unnecessary data (using SQL), leaving a relevant data set from which to work (using PHP).
If you are fetching more data records than are necessary, it's a sure sign that the SQL code being applied has not be optimized.
A classic example of the effective use of SQL is in regards to the where clause.
Consider the following section of code that retrieves a result set and prints out the user's name and phone number whenever it encounters a row where the id field is equal to 5:
$statement 'SELECTname,phone,idFROMsamp_table' $result sql_query $statement $conn);
if(@sql_num_rows $result)<= )
while($row sql_fetch_array $result ?>
The code above is not optimized; we're using PHP to search through an entire database set! While this might not be significant when working with smaller sized databases, as the size of your database increases you'll definitely feel a big performance hit.
The solution is simple: modify your SQL statement to contain a WHERE clause:
$statement 'SELECTname,phoneFROMsamp_table' $statement 'WHEREid='5''
The WHERE clause enables you to be more selective when extracting results from a database. The where clause's limit of the selection is a function of it's argument. In the above example that argument is 'id=5'.
Now that you've selected the desired data set, you can use PHP to simply print out your data thereafter:
if(@sql_num_rows $result $row sql_fetch_array $result);
print'Name:$row name]n<br>n ;
Many people grab their result sets unsorted, with the intention of subsequently using PHP to do the sorting. This is simply inefficient as SQL sorting facilities are faster than PHP.
Use SQL's ORDER BY syntax over that of PHP's ksort() function.
Consider the following which uses PHP's ksort() function to sort a result set by the name:
$statement 'SELECTname,email,phoneFROMsome_table' $statement 'WHEREnameISLIKE'%baggins'' $result sql_db_query $statement 'samp_db' $conn);
while($row sql_fetch_array $result ksort $matches
But why not sort the result set at the time it is defined? This can save us from having to run through the set of records a second time.
Therefore, remove the ksort() function from the above script and replace the SQL code with the following, which features the ORDER BY syntax:
$statement 'SELECTname,email,phoneFROMsome_table' $statement 'WHEREnameISLIKE'%baggins'ORDERBYname'
I have seen many scripts lacking a sufficient amount of error checking. It results mostly from programmers that do not take the time to properly plan their script and identify all the possible places where something can go wrong. Error checking should not begin after the code has been written. This lack in foresight can lead to fatal bugs that will not only generate incorrect results but may even cause your system to crash!
All scripts have the possibility of failure under the 'wrong' conditions. In order to minimize such a risk, you should plan to:
Check the results of function calls
Check the results of system calls
Set the error_reporting level to E_ALL in your php.ini file
Whenever you call a function that returns data to be manipulated, always check to make sure that the return data is in a range of allowable values.
In the example below, an illegal division by zero error is generated on the 6th iteration of the for loop, as $i is incremented by one while $j is decremented by one. On the sixth time through $i $j
functiondo_math $a $b)
for($i $j $i>- $i $j ?>
Always ensure when you're dealing with processes or files external to PHP that everything has functioned correctly.
A perfect example is checking the output of a system call when using a sql_connect() function. Validate the output to ensure that the connection to the database actually took place. Failure to do so can result in failed queries and lost data without you even knowing it.
$conn sql_connect $host $user $pass);
Be sure to configure PHP to provide you with the highest level of error reporting possible. If you don't set it to the highest level at least when debugging, you might miss errors such as invalid regular expressions and incorrect values.
Consider once more the example I gave for checking the output of function calls, shown below. Assume you set the error reporting to a lower level, say E_ERROR
Take note from the sample output below how the script executes the do_math function but does not report the illegal division by zero error that took place (no output was generated for $i $j
error_reporting E_ERROR mt_srand((double)microtime );
functiondo_math $a $b)
for($i $j $i>- $i $j ?>
PHP often displays execution errors to the browser, preventing you from suppressing and capturing them. However, with PHP4 you can now catch errors using the set_error_handler() function.
The set_error_handler() function can be used to log errors that occur in your script. Instead of troubling the user with error messages, you can capture all of the errors for yourself, by setting a custom error handling function.
In the example below, set_error_handler()is used to designate the error_handler() function as the default error handler.
When an error takes place, error_handler()is called and PHP's error_log() function is used to log the error to the error_file file.
If the error is of type E_ERROR, we exit out of the script and print an error message.
functionerror_handler $type $message $file __FILE__ $line __LINE__ set_error_handler 'error_handler' ?>
The OO paradigm is a wonderful concept. It has numerous benefits, the most notable being the ability to reuse code easily. However, as we've all come to understand: 'PHP is not an OO language'.
While PHP does offer adequate object oriented support, it is neither efficient nor wise to use its object oriented features when you can make use of other methods to achieve the same result. The reason for this is that PHP's OO support is not full blown.
While most of the major elements are present, PHP still lacks some of the more advanced features (such as protected membersor private variables) that a 'true' OO language (For example, C++ , Java) would have.
Nor is the code behind PHP's OO support very efficient or fine tuned. This means that when you use the OO paradigm with PHP, you may in fact be slowing down the execution time of your programs considerably.
Note: Generally speaking, an application that uses OO support will be slower just as using eval() will be slower than normal code. To amply show places where OO support gets somewhat ugly, I'd have to use advanced PHP features and concepts, some of which have not even been documented yet.
If you are coming to PHP from a language such as Java or C++ where you can't really create complex programs without using object oriented features, bypassing PHP's OO support may be difficult. Let me assure you, however, that powerful applications can be written without the use of any OO concepts and methodologies (PHP was written in C, which has no OO support).
So for those of you unaccustomed to using non-OO practices, here are some different techniques for creating cohesive and extensible applications without the use of OO paradigms:
Creating an API.
Creating a naming sequence (and sticking by it).
Grouping related functions into the same file.
Apply three layers to your program:
First, functions that actually do the work.
Secondly, a function API. These are the functions that you use to build the specific application,
Thirdly, the application itself:
function_mort_find_interest_rate $total //TheAPIislayer2
functioncalculate_mortgage_rate $money $time $month ?>
include_once'MortgageRate.php' $price calculate_mortgage_rate $money $time $period);
One of the major problems in any large project is namespace collision. Classes segment the namespace. Therefore, different classes can:
Be assigned a property with the identical name, or
Contain a method with the identical name.
For example class Phillips and class
In general, before starting a large project you should define a naming sequence for everything, namely, how you separate global variables from regular variables, how you define library functions, etc.
Group similar API functions into the same file just as you would group similar methods into a class. Try to think in terms of every file you create being a class in and of itself, with each function being a method. In this manner, your functions will have a clear definition and structure.
For example you might want to group all functions related to database access in a file named DB.php.
Let me just clarify something. I'm not advocating that you abandon PHP's object oriented features entirely. Rather, I'm just trying to warn you not to use PHP like it was Java or C++ where one would freely use OO.
Carefully balance the benefits with the drawbacks before you decide to use an object oriented approach with PHP.
Regular expressions are powerful tools for searching and organizing data, such as validating an e-mail address or matching a URL. However, they are also slower than some of the other tools that PHP offers for simple tasks.
For example, if you wanted to capitalize an entire string, the novice PHP user might do the following:
$URL 'https://www.php.net' $fp fopen $URL 'r');
while($line fgets $fp fclose $fp)
orwarn 'Cannotclosewebsitehandle,$URL' $data ereg_replace '[a-z]' '[A-Z]' $data);
However, they would be wasting execution time by using the slower ereg_replace() to do what the lightning fast strtoupper() function would do much better:
$data strtoupper $data
In general, you should always try to use simpler alternatives to regular expressions as it will speed up your code tremendously.
There are a few functions that are essential to saving script execution time when used in place of a regular expression. Below is a list of these 'essential' functions:
strtoupper() strtolower() ucfirst() strtr() str_replace() trim() explode() implode() substr() strcmp()
If you replace your regular expression with one of the above functions you should expect to see a great jump in performance, especially as the string size that you are dealing with begins to increase.
Many people get started with PHP after having become proficient in another language such as Perl, C, Java or (gasp) ASP. In doing so, they bring along programming paradigms which might not always be in line with the methodologies employed by PHP.
Unfortunately, some of these individuals fail to take the time to learn how to program PHP in a manner more suitable to PHP's way of doing things. Instead, they prefer to get PHP to work with as few new concepts being introduced as possible.
When you program PHP like its some other language, it often leads to slower and less maintainable code. You often see people making the mistake of programming PHP like it is another show up when you see:
Perl 'one liners'. PHP as a language is not really optimized for the 'one-liner' approach to writing a program. Instead, expand the complicated set of combined function calls and regular expressions into a more hierarchical format.
$fp fopen 'php://stdin' 'r');
while($line fgets $fp ))
foreach($quotesas$name=>$quote fclose $fp ?>
Not using built-in functions: Many PHP programmers who come from a C background, don't seem to realize that PHP provides many built-in functions which eliminate lengthy blocks of code. If you come to PHP from C, I suggest you make sure to have a look at the PHP manual before you write a block of code to see what functions PHP has to offer to make your life easier.
Renaming existing PHP functions: I see users rename PHP's existing functions just to make it easier for them to remember. Not only does this slow down the execution time of your program, but it also decreases the code's readability.
Overusing OO features: PHP is not an object oriented language, while it does provide object oriented features, you should always be conscious of the fact that using PHP's object oriented features will significantly slow down your code.
Luckily there is a lot of information out there on how to program PHP, some of the best are:
Zend.com: Obviously. You're reading this article, right??
Professional PHP: One of the best overall books on PHP, good for non-programmers and programmers alike.
Web Application Development with PHP: A great book teaching both the concepts in Web development as well as some of PHP's more advanced features. Contains the official Zend API documentation.
The PHP Developer's Cookbook: A solutions oriented book covering the common problems that PHP developers encounter (Coming out November 2000, written by myself with Andrei Zmievski).
Our users will not always work within our systems. It is our responsibility as programmers to design secure and forgiving systems that will account for, and work with user mistakes.
When designing systems you must put yourself in the mind of your user. See where they might commit errors and locate the potential security breaches. Then you can design your programs to account for those errors and eliminate the potential security breaches. It is also important to remember that while a user's errors and system attacks may be their fault, you're the one who is held responsible if you write a program with a security hole or miss a level of error checking that leaves you vulnerable to corrupt data.
For example, I've seen many scripts that do not utilize PHP's built-in mail() function which connects in a secure way. Instead, the script will pass a users e-mail to sendmail, through the popen() This can lead to many security holes (such as /etc/passwd being sent to the end user).
Some areas where security breaches are most common, or the potential for data corruption is greatest are:
When making system calls. I can't stress this point enough. Always make sure that any data a user gives you is safe before passing it to a system call. NEVER TRUST THE USER BLINDLY BY PLACING THEIR DATA IN A SYSTEM CALL WITHOUT CHECKING IT FIRST.
When registering users. If you expect accurate results, always check and make sure that the registration of the user has a few checks in place. First of all, there are many ways to validate an e-mail address. Ensure that the user has a valid e-mail address. Furthermore, you should check to make sure that the user's age is within a certain range. As generalization, you can be pretty sure there are no 200 year olds running around with the ability to operate a computer.
When accepting credit cards. Some programmers will only use simple algorithms which can easily be spoofed when doing checks with credit cards. Always gain an account with a major corporation to check the validity of a credit card number before actually accepting the user's credit card. DO NOT TRUST AN ALGORITHM.
Whenever you place user data in a system call you're going to want to sanity check that data. Make sure that nothing dangerous is contained in the data that can 'spoof' your system into executing unwanted commands. PHP offers a function that does just that: the EscapeShellCmd() function.
Whenever you are passing a command that contains sensitive data, always escape that data with the EscapeShellCmd() function:
Note: Escaping the data means places a backslash in front of characters that might be used to spoof a system (#&;´''|*?~<>^()$x0AxFF to be exact).
Note: While the EscapeShellCmd() is a worthy function for checking a command to make sure it is safe from spoofs, you should still try and make specific checks depending on the type of data that is being submitted. The EscapeShellCmd() will not check for the validity of the submitted data, it will just prevent the user from doing anything unauthorized.
As a rule, it is better to check for characters which are allowed, rather than for characters which are not.
For example, make sure that $name only contains alphanumeric characters. In this manner, new ways of exploiting your system are less likely to slip through your filter.
One of the most common forms of validation is checking an e-mail address to make sure that it is valid. Many novice programmers will just use a regular expression that they grabbed off one of the mailing lists or from a code repository. However, a regular expression is not sufficient if you want to secure accurate results. There are a couple methods you can use, instead, that are more secure:
One way of validating an e-mail address without directly involving the user is to open up a socket to the server they give you for their e-mail address and check to find their username.
No inconvenience to the user as everything is done transparently.
Weeds out many phony addresses that wouldn't be caught by a regular expression (such as email@example.com
Will not catch valid but mistaken addresses. For example, if John Doe submits my e-mail address, (firstname.lastname@example.org), the message will be processed, in spite of it being my address instead of his.
Slower than using a regular expression to validate an e-mail address.
User's mail server may be temporarily down, causing a valid address to not be recognized.
Another method of validating an e-mail address is by sending a special 'key' to the users e-mail box, and then requiring the user to enter in that special key in order to continue. This ensures that not only that the e-mail address will be valid, but that the user will also have legal access to an e-mail account.
It is the best way to ensure that a user has a valid e-mail address. (They must have access to the e-mail address they give you in order to register.)
Requires that a user take extra steps in order to submit their data. This will annoy users intended on fooling you.
Like every method, it is not fool proof. The user can create a temporary account with Hotmail or Netaddress and then use that account to register onto your site.
In this article we have discussed the second set of mistakes, namely the seven serious mistakes #14 to 8, that PHP programmers commit when applying PHP. These serious mistakes are:
Not following basic naming conventions: Following basic naming conventions will lead to clearer and more maintainable code.
Not thinking things through: Databases & SQL: Incorrect data sampling is a good example of coding with a lack of focus. Some coders do not take the time to think things through. True, there might not be a single 'correct' way of data sampling, but there are plenty of incorrect ways.
Lack of error checking: You should always plan the time to have ample error checking in your scripts. Be especially sure to check the results of function calls and system calls.
Overuse of OO: Since PHP is not a full blown object oriented language, you should not use its OO features as freely as you would with a language such as Java or C++ (or even Perl).
Misusing regular expressions: Regular expressions are slow. When considering using a regular expression, make sure beforehand that there isn't a simpler, faster function available which will achieve your desired results.
Programming PHP like it's some other language: You should not program PHP as if it is Perl or C. PHP is a separate language in and of itself, Therefore, you should learn the correct way of doing something in PHP, rather that in a manner that might be deemed correct in another language.
Not being security conscious: You should always design systems to account for human error. Never place user data in a system call without checking the data beforehand. Validate e-mail addresses. Do not trust algorithms when accepting credit cards.
Politica de confidentialitate|
Adauga cod HTML in site