Рейтинг@Mail.ru
 





Приступим
Последнее время ко мне стали очень часто обращаться люди с просьбой помочь переделать сайт, в котором те или иные проблемы. Вернее обращались и раньше, но в последнее время проблемы стали повторяться с завидным постоянством. Виной тому (как бы помягче сказать) не совсем корректный код, который распространяется в видеокурсах.

Чесслово, это изрядно поднадоело, и я решился исправить эти ошибки один раз и на всегда. Чтобы не повторяться.
А по сему сейчас по косточкам разберу этот самый код и покажу тонкие места. На правах рецензии.

Я не буду касаться компановки и структуры, не мое дело. Каждый пишет, как он хочет. Но грубые логические и семантические ошибки исправим.

Начнем, как водится, с самого начала.
index.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php
include ("blocks/bd.php"); /*Соединяемся с базой*/
$result mysql_query("SELECT title,meta_d,meta_k,text FROM settings WHERE page='index'",$db);
$myrow mysql_fetch_array($result); 
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta name="description" content="<?php echo $myrow['meta_d']; ?> ">
<meta name="keywords" content="<?php echo $myrow['meta_k']; ?> ">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title><?php echo $myrow['title']; ?></title>
<link href="style.css" rel="stylesheet" type="text/css">
</head>
<body>
<table width="690" border="0" align="center" cellpadding="0" cellspacing="0" bgcolor="#FFFFFF" class="main_border">
<!--Подключаем шапку сайта-->
<? include("blocks/header.php");   ?> 
  <tr>
    <td><table width="690" border="0" cellspacing="0" cellpadding="0">
      <tr>
<!--Подключаем левый блок сайта-->
<? include ("blocks/lefttd.php");  ?>      
        <td valign="top">
        <?php echo $myrow['text']; ?>       
        </td>
      </tr>
    </table></td>
  </tr>
<!--Подключаем нижний графический элемент-->  
<?  include ("blocks/footer.php");        ?>  
</table>
</body>
</html>

Итак.
1
2
3
4

<?php 
include ("blocks/bd.php"); /*Соединяемся с базой*/

Первое, не плохо бы знать, что по английски "база данных" звучит как "database", а значит подключаемый файл должен называться db.php, а не bd.php.
Оно на работоспособность вроде как не влияет, но звучит глупо. И говорит о уровне исполнителя. Если придется писать сайт за деньги, это непростительно.

Второе. Путь нужно указывать явно. Если считаем от корня сайта, то так: './path/file.php'; И хотя демократичный PHP прощает такие неточности, злоупотреблять не по-христиански.

Третье. Конструкция include не требует скобок. Они создают избыточность кода.

Четвертое. Литеральные константы (в миру - строки) лучше обрамлять апострофами, а не кавычками. Ибо они быстрее и читабельнее.

В итоге корректно эта строка должна выглядеть так:
1
2
3
4
5
<?php

    
include './blocks/db.php'/*Соединяемся с базой*/

Но это грех не смертный, с опытом приходит умение писать красиво.
А вот дальше уже серьёзнее. Откроем этот файл со смешным названием:
bd.php
1
2
3
4
5
6
7
<?
$db 
mysql_connect ("localhost","php","12345");
mysql_select_db("phpsite",$db);
?>

Не нужно лениться. Не нужно пользоваться short-тегами. Их вообще скоро выведут из употребления, так как они пересекаются с XML. Писать нужно только так: <?php
Ну и коль скоро зашла речь о них, то закрывающий значек в конце файла PHP ?> нельзя ставить ни в коем случае. Это не просто вредно, но и опасно.
Объясню, чтоб не быть голословным.
1. После него может оказаться пробел или перенос строки. А так, как файл подключен выше доктайпа, значит и пробел вылезет туда. А это гарантированно угробит верстку в IE.
2. Всё, что написано после него, интерпретируется как HTML. А это значит, что (не дай Бог) в конец файла попадет вирус, то он сработает.
А тупые боты именно туда норовят прописать всякую гадость. Так вот, ежели его (закрывающего значка) не будет, то вирь попадет в тело php и вызовет ошибку. Плохо конечно, но лучше, чем бы он сработал у клиента.

Продолжаем разговор.
Тут мы вроде спохватились, и пишем правильно - $db. Ура. Однако на радостях почему то упускаем такой важный момент, как кодировка соединения. И это часто вызывает панику среди мирного населения - мол почему у меня из базы лезут кракозяблы???

Поправим и переименуем файл:
db.php
1
2
3
4
5
6
7
8
9
<?php

    $db 
mysql_connect ('localhost','php','12345');
    
mysql_select_db('phpsite',$db);
    
mysql_query('SET NAMES cp1251',$db);          
    
mysql_query('SET CHARACTER SET cp1251',$db);  
    
mysql_query('SET COLLATION_CONNECTION="cp1251_general_ci"',$db);
И хотя мне чужды и противны по религиозным соображениям местечковые кодировки, из песни слов не выкинуть.

Поехали обратно в индекс.
1
2
3
4
5
6


$result 
mysql_query("SELECT title,meta_d,meta_k,text FROM settings WHERE page='index'",$db);
$myrow mysql_fetch_array($result); 

Начали красиво, пусть даже без обратных кавычек и в одну строку - вполне допустимо. Но вот продолжение обескураживает.
Прежде чем использовать функцию, стоит заглянуть в мануал, а не копипастить из первого попавшего источника. Дело в том, что функция mysql_fetch_array() возвращает два массива. Нумерованный и ассоциативный. А используется только один.
Для чего брать в одну руку ложку, а в другую вилку, если мы собираемся есть суп?
Если уж использовать её, то с подобающим флагом (MYSQL_ASSOC). А вообще тут уместнее mysql_fetch_assoc()
1
2
3
4
5
6
<?php

    $result 
mysql_query("SELECT title,meta_d,meta_k,text FROM settings WHERE page='index'",$db);
    
$myrow mysql_fetch_assoc($result);

А дальше просто страшно. Такие дыры совсем непростительны:
1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta name="description" content="<?php echo $myrow['meta_d']; ?> ">
<meta name="keywords" content="<?php echo $myrow['meta_k']; ?> ">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title><?php echo $myrow['title']; ?></title>
<link href="style.css" rel="stylesheet" type="text/css">
</head>
<body>

На первый взгляд ничего особенного, однако попробуйте через PhpMyAdmin выполнить такой запрос
1
2
3
UPDATE `settings` SET `meta_d` = '"><script>location.href="http://sex.ru";</script>' WHERE `id` = 1
и зайти на главную страницу сайта. Обещаю незабываемые впечатления )).

Как это может попасть в базу, я не покажу по известным причинам. Но поверьте, это не так уж сложно на таком сайте. Называется сие - XSS или межсайтовый скриптинг.

Так вот, чтобы такого никогда не было, нужно всегда обрабатывать данные перед выводом в поток функцией htmlspecialchars()
1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta name="description" content="<?php echo htmlspecialchars($myrow['meta_d']); ?> ">
<meta name="keywords" content="<?php echo htmlspecialchars($myrow['meta_k']); ?> ">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title><?php echo htmlspecialchars($myrow['title']); ?></title>
<link href="style.css" rel="stylesheet" type="text/css">
</head>
<body>

Дальше уже по известному сценарию. Вот так с натяжечкой пойдет:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php
 
    
include './blocks/db.php'/*Соединяемся с базой*/
    
    
$result mysql_query("SELECT `title`, `meta_d`, `meta_k`, `text` 
                           FROM `settings` 
                           WHERE `page` = 'index'"
$db);
                           
    
$myrow mysql_fetch_assoc($result);
     
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta name="description" content="<?php echo htmlspecialchars($myrow['meta_d']); ?> ">
<meta name="keywords" content="<?php echo htmlspecialchars($myrow['meta_k']); ?> ">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title><?php echo htmlspecialchars($myrow['title']); ?></title>
<link href="style.css" rel="stylesheet" type="text/css">
</head>
<body>
<table width="690" border="0" align="center" cellpadding="0" cellspacing="0" bgcolor="#FFFFFF" class="main_border">
<!--Подключаем шапку сайта-->
<?php include './blocks/header.php';   ?> 
  <tr>
    <td><table width="690" border="0" cellspacing="0" cellpadding="0">
      <tr>
<!--Подключаем левый блок сайта-->
<?php include './blocks/lefttd.php';  ?>      
        <td valign="top">
        <?php echo htmlspecialchars($myrow['text']); ?>       
        </td>
      </tr>
    </table></td>
  </tr>
<!--Подключаем нижний графический элемент-->  
<?php  include './blocks/footer.php'; ?>  
</table>
</body>
</html>

Отличия ищите сами.

С первым покончили... Дальше - больше. Как говорится, чем дальше в лес, тем толшэ партизаны.