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
))) {
"Error: no rows are found "
;
exit;
}
do {"$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
) {
" Error: no rows are found "
;
exit;
}
while ($row
=
sql_fetch_row
(
$result
)){
"$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
){
"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
);
$row
[
1
];
// Second column
$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
) {
"Error: no rows are found "
;
exit;
}
while ($row
=
sql_fetch_array
(
$result
)) {
"$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
++){
"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
] &
amp
;
5
) {
"Name: $row[name]\n<br>\n"
;
"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
);
"Name: $row[name]\n<br>\n"
;
"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
[
],
$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
);
functiondo_math
(
$a
,
$b
) {
return (($a
-
$b
) *
2
) /
mt_rand
();
}
for ($i
=
5
,
$j
= -
5
;
$i
> -
5
;
$i
--,
$j
++){
$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
);
functiondo_math
(
$a
,
$b
) {
return (($a
-
$b
) *
2
) /
mt_rand
();
}
for ($i
=
5
,
$j
= -
5
;
$i
> -
5
;
$i
--,
$j
++){
$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
) {
"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 paymentfunction
_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 intervalfunction
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 forminclude_once
'MortgageRate.php'
;
$price
=
calculate_mortgage_rate
(
$money
,
$time
,
$period
);
"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
(
$fp
,
1024
)){
$data
.=
$line
;
}
@fclose
(
$fp
) or
warn
(
"Fail by closing descriptor $URL"
);
$data
=
ereg_replace
(
"[a-z]"
,
"[A-Z]"
,
$data
);
$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 formPerl
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
(
$fp
,
1024
)){
list($name
,
$quote
) =
explode
(
':'
,
$line
);
$quotes
[
$name
] =
$quote
;
}
foreach ($quotes
as
$name
=>
$quote
){
print"$name: "
;
printimplode
(
" "
,
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"
));
"<br>\n\n"
;
}?>
<form action="<?php
$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.