Пишем свою авторизацию на PHP и MySQL

Сентябрь 21st, 2010 Рубрики: MySQL, PHP coubertin.cz www.colvillewoodworking.com

Ну что же, сегодня я вам расскажу о безопасной авторизации на PHP и Cookie. Ну о том что она абсолютна безопасна я не говорю, ибо взломать можно все, но для маленького сайта она вполне подходит. Так же я предвижу комментарии о том что сессии безопаснее. Не спорю куки уступают сессиям в безопасности но для реализации простенькой авторизации вполне подходят. Подробности ниже.

И так, в базе у нас будет 1 база из 4 полей: users_id, users_login, users_password и users_hash. SQL запрос:

1
2
3
4
5
6
7
CREATE TABLE IF NOT EXISTS `users` (
  `users_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `users_login` VARCHAR(30) NOT NULL,
  `users_password` VARCHAR(32) NOT NULL,
  `users_hash` VARCHAR(32) NOT NULL,
  PRIMARY KEY  (`users_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
    Сам скрипт авторизации будет тоже на 4 файлах. А именно:

  • conf.php — Файл конфигурации, в котором так же содержится подключение к бд;
  • register.php — Регистрация нового пользователя;
  • login.php — Авторизация пользователя;
  • check.php — Скрипт проверки авторизации;

Давайте разберем каждый файл.

conf.php

В константах содержится данные SQL подключения, а именно хост, логин, пароль и имя вашей базы. Тут же мы подключаемся к базе, устанавливаем кодировку в которой будут передаваться данные в бд и выбираем бд с которой будем работать. Так же тут содержится массив ошибок которые могут возникнуть при авторизации.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
# настройки
define ('DB_HOST', 'localhost');
define ('DB_LOGIN', 'example_user');
define ('DB_PASSWORD', 'example_password');
define ('DB_NAME', 'example_base');
mysql_connect(DB_HOST, DB_LOGIN, DB_PASSWORD) or die ("MySQL Error: " . mysql_error());
mysql_query("set names utf8") or die ("<br>Invalid query: " . mysql_error());
mysql_select_db(DB_NAME) or die ("<br>Invalid query: " . mysql_error());

# массив ошибок
$error[0] = 'Я вас не знаю';
$error[1] = 'Включи куки';
$error[2] = 'Тебе сюда нельзя';
?>

register.php

Файл регистрации, тут содержится простейшая форма и ее обработчик. Исходный код прокомментирован, но общий процесс я коротко опишу. Вначале проверяем наш логин, он может содержать только английские буквы и цифры. Далее мы проверяем длину логина, от 3 до 30 символов. Проверяем свободен ли логин. При успешных проверках добавляем нового пользователя в базу. Из введенного пароля мы вырезаем пробелы на случай если пользователь хранит свои пароли в каком ни будь текстовом файле (в windows текстовые редакторы любят «хватать» пробелы в начале или конце выделяемого текста). Шифруем пароль в двойном MD5 и добавляем в базу данные о новом пользователе. Перебрасываем пользователя на login.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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<?php
# Подключаем конфиг
include 'conf.php';

if(isset($_POST['submit']))
{

    $err = array();

    # проверям логин
   if(!preg_match("/^[a-zA-Z0-9]+$/",$_POST['login']))
    {
        $err[] = "Логин может состоять только из букв английского алфавита и цифр";
    }
     
    if(strlen($_POST['login']) < 3 or strlen($_POST['login']) > 30)
    {
        $err[] = "Логин должен быть не меньше 3-х символов и не больше 30";
    }
     
    # проверяем, не сущестует ли пользователя с таким именем
  $query = mysql_query("SELECT COUNT(users_id) FROM users WHERE users_login='".mysql_real_escape_string($_POST['login'])."'")or die ("<br>Invalid query: " . mysql_error());
    if(mysql_result($query, 0) > 0)
    {
        $err[] = "Пользователь с таким логином уже существует в базе данных";
    }
 
     
    # Если нет ошибок, то добавляем в БД нового пользователя
   if(count($err) == 0)
    {
         
        $login = $_POST['login'];
         
        # Убераем лишние пробелы и делаем двойное шифрование
       $password = md5(md5(trim($_POST['password'])));
         
        mysql_query("INSERT INTO users SET users_login='".$login."', users_password='".$password."'");
        header("Location: login.php"); exit();
    }
}
?>

  <form method="POST" action="">
  Логин <input type="text" name="login" id="reg_inp" /><br />
  Пароль <input type="password" name="password" id="reg_inp" /><br />
  <input name="submit" type="submit" value="Зарегистрироваться">
  </form>
  <?php
    if (isset($err)) {
      print "<b>При регистрации произошли следующие ошибки:</b><br>";
      foreach($err AS $error)
      {
        print $error."<br>";
      }  
    }
  ?>

login.php

Опять кратко расскажу о действиях совершаемых в данном скрипте. В самом начале у нас висит функция для генерации случайной строки, она служит для хеша пользователя (чуть позже более подробно). Далее мы проверяем наличие куков с ошибками (они ставятся в check.php). Подключаем файл конфигурации и проверяем пользователя. Вытаскиваем из бд логин и пароль, сравниваем с введенными и генерируем хеш. Записываем в бд новый хеш пользователя и ставим куки. В куках находится id и хеш пользователя. Пересылаем пользователя на check.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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?php
  # Функция для генерации случайной строки
  function generateCode($length=6) {
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPRQSTUVWXYZ0123456789";
    $code = "";
    $clen = strlen($chars) - 1;  
    while (strlen($code) < $length) {
        $code .= $chars[mt_rand(0,$clen)];  
    }
    return $code;
  }
 
  # Если есть куки с ошибкой то выводим их в переменную и удаляем куки
  if (isset($_COOKIE['errors'])){
      $errors = $_COOKIE['errors'];
      setcookie('errors', '', time() - 60*24*30*12, '/');
  }

  # Подключаем конфиг
  include 'conf.php';

  if(isset($_POST['submit']))
  {
   
    # Вытаскиваем из БД запись, у которой логин равняеться введенному
    $data = mysql_fetch_assoc(mysql_query("SELECT users_id, users_password FROM `users` WHERE `users_login`='".mysql_real_escape_string($_POST['login'])."' LIMIT 1"));
     
    # Соавниваем пароли
    if($data['users_password'] === md5(md5($_POST['password'])))
    {
      # Генерируем случайное число и шифруем его
      $hash = md5(generateCode(10));
           
      # Записываем в БД новый хеш авторизации и IP
      mysql_query("UPDATE users SET users_hash='".$hash."' WHERE users_id='".$data['users_id']."'") or die("MySQL Error: " . mysql_error());
       
      # Ставим куки
      setcookie("id", $data['users_id'], time()+60*60*24*30);
      setcookie("hash", $hash, time()+60*60*24*30);
       
      # Переадресовываем браузер на страницу проверки нашего скрипта
      header("Location: check.php"); exit();
    }
    else
    {
      print "Вы ввели неправильный логин/пароль<br>";
    }
  }
?>
  <form method="POST">
  Логин <input name="login" type="text"><br>
  Пароль <input name="password" type="password"><br>
  <input name="submit" type="submit" value="Войти">
  </form>
  <?php
  # Проверяем наличие в куках номера ошибки
  if (isset($errors)) {print '<h4>'.$error[$errors].'</h4>';}

  ?>

check.php

И последний файл, который содержит проверку авторизации пользователя. В начале подключаем конфиг и если существуют куки начинаем проверку, если их нет, то ставим куки с номером ошибки и отсылаем на login.php. И так проверка. Вытаскиваем из бд id и хеш. Если они не проходят проверку на соответствие с теми куками которые стоят у посетителя, то удаляем существующие куки посетителя и ставим куки с номером ошибки, пересылаем на login.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
<?php
# подключаем конфиг
include 'conf.php';  

# проверка авторизации
if (isset($_COOKIE['id']) and isset($_COOKIE['hash']))
{    
    $userdata = mysql_fetch_assoc(mysql_query("SELECT * FROM users WHERE users_id = '".intval($_COOKIE['id'])."' LIMIT 1"));

    if(($userdata['users_hash'] !== $_COOKIE['hash']) or ($userdata['users_id'] !== $_COOKIE['id']))
    {
        setcookie('id', '', time() - 60*24*30*12, '/');
        setcookie('hash', '', time() - 60*24*30*12, '/');
    setcookie('errors', '1', time() + 60*24*30*12, '/');
    header('Location: login.php'); exit();
    }
}
else
{
  setcookie('errors', '2', time() + 60*24*30*12, '/');
  header('Location: login.php'); exit();
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
  <title></title>
</head>
<body>
  hello!
</body>
</html>

Выход

Выход можно осуществить любым удобным для вас способом просто удалив куки, допустим так:

1
2
3
4
5
6
7
8
9
<form action="" method="post"><input type='submit' name='exit' value='Выйти'/></form>
<?php
if($_REQUEST['exit'])
  {
        setcookie('id', '', time() - 60*60*24*30, '/');
        setcookie('hash', '', time() - 60*60*24*30, '/');
        header('Location: login.php'); exit();
  }
?>

Сразу хочу предупредить о том что ваши файлы должны быть в кодировке UTF8 и БЕЗ BOM! Приятного пользования!

Теги: , , , ,

79 комментариев к “Пишем свою авторизацию на PHP и MySQL”

  1. Октябрь 11th, 2010 at 11:02
    1

    Подскажите, как сделать выход?

    [Ответить]

    ZekMan Reply:

    Добавил в статью…

    [Ответить]

  2. mustang
    Январь 6th, 2011 at 17:16
    2

    а зачем используется
    # массив ошибок
    ???

    [Ответить]

    ZekMan Reply:

    Если ты написал неверный логин/пароль, или зашел на защищенную страницу не залогинившись то тебя перебрасывает на страницу авторизации с и в куке передается номер ошибки, выдаем ошибку и просим авторизоваться…

    А массив использую потому что это проще чем несколько переменных…

    [Ответить]

  3. Январь 12th, 2011 at 15:36
    3

    Если собрать файлы, и попробовать зарегистрироваться, выдает
    Invalid query: Unknown column ‘users_id’ in ‘field list’

    [Ответить]

    ZekMan Reply:

    В примере примерные название таблиц и баз, вы можете менять их по своему желанию. Была небольшая ошибочка в названия таблиц в дампе бд. Поправил.

    [Ответить]

  4. DooMer
    Март 14th, 2011 at 21:25
    4

    По моему с DOCTYPE можно обойтись проще. Достаточно . Но это уже мелочи.

    [Ответить]

    ZekMan Reply:

    Это валидный DOCTYPE — по стандарту XHTML 1.0 =)

    [Ответить]

  5. DooMer
    Март 15th, 2011 at 09:24
    5

    Ну а DOCTYPE html это валидный для всех документов 😉 Просто писать меньше и удобней.

    [Ответить]

    ZekMan Reply:

    Писать надо по стандарту на котором пишешь, для проверки валидности есть validator.w3.org а для «писать меньше и удобней» есть ZenCoding про который я уже писал 😉

    [Ответить]

  6. Июнь 5th, 2011 at 14:34
    6

    Спасибо за статью. для своего самописного проекта приходилось писать и регистрацию, и авторизацию. Также на эту тему писал серию статей, во многом, кстати, схожих с этой)
    Если интересует, можем обменяться постовыми. У тебя на этой странице, а у меня — на такой же по тематике статье.

    Заинтересует — пишите)

    [Ответить]

    ZekMan Reply:

    Интересует — отписал на почту

    [Ответить]

  7. Сергей
    Июль 5th, 2011 at 14:00
    7

    «В самом начале у нас висит функция для генерации случайной строки, она служит для хеша пользователя (чуть позже более подробно).»

    А зачем нужна эта функция и зачем записывать в БД полученный хэш?

    [Ответить]

    ZekMan Reply:

    Сравнивая ID и хэш пользователя мы допускаем пользователя к странице или наоборот.

    ID и хэш в куках должен совпадать с id и хэшем пользователя в бд. Таким образом если у пользователя есть правильных хэш и куки ему не надо авторизовываться снова. Подбор хэша исключаем генерируя его каждый раз при авторизации.

    [Ответить]

  8. Сергей
    Июль 5th, 2011 at 14:26
    8

    Нашел много разных статей, где описывается авторизация на сессиях или куки отдельно. Но вот никак не могу воедино собрать — как сделать скрипт как в примере у вас (по-моему мнению у вас один из лучших примеров в сети), но с возможностью выбора пользователя — сохранять пароль в куки или же пользоваться только сессиями.
    Вы не планируете написать статью, в котором будет пример разработки скрипта авторизации именно с возможностью выбора (типа галочки «запомнить меня»)? Я был бы просто счастлив почитать такое.
    Но и за эту статью огромное спасибо!

    [Ответить]

    ZekMan Reply:

    Куки или сессии? Пользователю не надо выбирать алгоритм работы — это ни к чему.
    По поводу галочки «Запомнить меня»: Реализуется очень просто. В данном примере нужно добавить еще одно условие на проверку checkbox и если он активен увеличиваем время на которое будет поставлена кука с хешем и id.
    Чуть позже я добавлю пару статей в блог, очень давно хочу их дописать но все руки не доходят, среди них будет авторизация на сессиях ( учту и галочку как пожелание 🙂 ) и украшение checkbox и еще много чего. Если хотите — подпишитесь на RSS что бы следить за обновлениями.

    [Ответить]

  9. SANO
    Июль 7th, 2011 at 20:26
    9

    Один вопрос возник) Как сделать так:
    index.php
    проверяет есть ли куки если нет то login.php подгружается на страницу, после введения логина и пароля перенаправляет отбратно.
    а если куки есть то открывает инфу с сайта.

    Эээ… Постарался понятно обьяснить))

    [Ответить]

    ZekMan Reply:

    check.php переименуйте в index.php — дальше смотрим, первой идет проверка на авторизацию если не авторизован идет перенаправление на форму логина и ставится кука с ошибкой. Вместо перенаправления нужно выдать форму а если человек авторизован то выдать контент — данный пример не очень удобен для разбора такого подхода, нужно переделывать всю логику и переписывать на функции.

    Как я говорил выше чуть позже будет статья о авторизации на сессиях. Она будет на функциях сделана примерно так как вы хотите. Потерпите выхода новой статьи или переписывайте логику этой авторизации =)

    [Ответить]

  10. Март 17th, 2012 at 03:07
    10

    Perfecto!

    [Ответить]

  11. Март 25th, 2012 at 18:30
    11

    У меня проблема, почему то не авторизовывается на login.php Запись в базе данных есть с зашифрованным паролем, но при логине он мне говорит что неверно введен пароль или логин… Не могу понять где я накосячил. Спасибо.

    [Ответить]

  12. Март 25th, 2012 at 18:31
    12

    Сделал ) Спасибо

    [Ответить]

    ZekMan Reply:

    Ну вот и чудно, а я уже хотел что ни будь да ответить))

    [Ответить]

  13. Март 26th, 2012 at 18:59
    13

    Коли ваша статья сподвигла меня изучать PHP ) Нет ли у вас какого нибудь совета как можно интегрировать пользователей из Active Directory ?

    [Ответить]

    ZekMan Reply:

    Ну судя по поверхностному поиску следует копать в PHP:LDAP или adLDAP. Точнее можно пробежаться по гуглу уже.

    Вообще я предпочитаю не держать web сервер на windows — не подходящая платформа.

    [Ответить]

  14. Артем
    Май 19th, 2012 at 00:04
    14

    что означает атрибут id=»reg_inp» в форме?

    [Ответить]

    ZekMan Reply:

    Он предназначен для CSS стилизации, но тут скорее всего закралась ошибка, т.к. использование нескольких одинаковых id запрещено.

    [Ответить]

  15. Иван
    Август 2nd, 2012 at 15:35
    15

    В файле check.php у Вас ставятся куки в errors со значением 1, что говорит «включи куки». Получается если человек логинится из другого браузера либо когда время у куков кончилось, либо первый раз, то он видит эту ошибку. Если же куки на самом деле выключены, то пользователь вообще не увидит это сообщение, так как ошибка записывается тоже через куки (которые отключены 🙂 ). Так что куку errors = 1 можно просто не ставить и убрать $error[1] из массива ошибок.

    [Ответить]

    ZekMan Reply:

    Мда, надо переписывать))) Этот исходник уже очень стар, в блоге есть гораздо новее на сессиях

    [Ответить]

  16. serega
    Август 5th, 2012 at 17:22
    16

    А что если, злоумышленник сворует куки и поставит их себе? ведь у него и hash и id будет тот же самый, и он без проблем зайдет туда куда ему не положено

    [Ответить]

  17. Troy
    Август 27th, 2012 at 07:41
    17

    Форма выхода, setcookie не переписывает куки…. в чем может быть проблема?

    [Ответить]

    ZekMan Reply:

    Файл выхода лежит в той же директории что и файл входа? Попробуйте вывести все куки которые есть. т.е. в файле выхода напишите что то типа < ?php print_r($_COOKIE[]); ?> или так же но var_dump посмотрите доступны ли этому файлу куки вообще.

    [Ответить]

  18. Октябрь 3rd, 2012 at 19:21
    18

    Доброго времени суток!
    Я не совсем понял зачем мучатся с хешем, лишний код, нагрузка на сервер БД при постоянных авторизациях и тд.
    Не могли бы Вы кратенько пояснить что это нам даёт ?
    или чем опасно просто в куках хранить пароль и логин в md5 ?
    Заранее благодарен, Игорь!

    [Ответить]

    ZekMan Reply:

    Злоумышленник может своровать куки и получить пароль в открытом виде, двойное хеширование так же не безопасно, вообще это авторизация на куках уже довольно старая, как простой пример подойдет. В рабочие сайты с большой посещаемостью я бы не советовал ее ставить. Среди последних постов у меня есть авторизация на сессиях — она предпочтительнее. Хранить в открытом виде можно только логин, пароли надо хранить в хеше с солью, так что бы если злоумышленник и получил хеш пароля — он не мог им воспользоваться ( по крайней мере не так просто). В куки мы ставим id пользователя и личный хеш, куки своруют получат временный кеш но не пароль, и при следующей авторизации личный хеш поменяется.

    [Ответить]

  19. ololosh
    Март 21st, 2013 at 22:44
    19

    Качественно скрипт написан. Отлично

    [Ответить]

  20. Mihail
    Март 23rd, 2013 at 21:57
    20

    А можно обьяснить что дальше. Авторизировался. А как сделать дальше? Чтоб можнобыло работать на сайте пока ты авторизирован и запретить при разрыве сесий ? Что-то того?

    [Ответить]

    ZekMan Reply:

    Посмотрите на пример файла check.php
    Там осуществляется проверка авторизации, если пользователь не авторизован его с этой страницы перебросит на страницу авторизации login.php.
    Возьмите это за пример

    [Ответить]

  21. Макс
    Апрель 25th, 2013 at 21:01
    21

    Доброго времени суток.
    У меня вопрос — мы создаем таблицу с пользователями, но мы ведь это делаем от имени супер пользователя root (или другое установленное имя при установке mysql).
    При этом для того чтобы пользователь из созданной нами таблицы смог войти ему нужно для начала соедениться с бд.
    А для доступа к таблицам из бд у него прав нет… так как формально это просто таблица лежащая в бд.
    Таблица содержащая пользователей с доступом к бд лежит в MySql / user — правильно ли я понимаю, чтоб сделать полноценный доступ нужно дописывать пользователей в базу MySql / user с назначением прав, а в нашей таблице просто дублировать эти данные + дополнительные параметры (которые мы хотим присвоить) .
    Спасибо за ваш ответ.

    [Ответить]

    ZekMan Reply:

    возможно что бы избежать вопросов таких мне как ни будь стоит подробно описать процесс создания баз и работы с бд в целом.
    Обычно я поступаю просто, создаю нового пользователя (для каждого проекта/субдомена) и создаю базу с именем пользователя, предоставляя на нее все права. В том же самом phpmyadmin это выглядит так:
    http://storage6.static.itmages.ru/i/13/0513/h_1368414371_7347828_edadb61379.png

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

    [Ответить]

  22. Dima
    Апрель 30th, 2013 at 01:29
    22

    Спасибо за материал!
    В контрольной использую вашу авторизацию. В форму регистрации добавлено несколько полей. При регистрации в БД не записывает кириллицу.
    Подскажите как исправить.

    [Ответить]

    ZekMan Reply:

    на сколько я помню кирилица спокойно проходила, проверьте кодировки. Ну и если с кодировками все нормально то опишите ситуацию более подробно

    [Ответить]

  23. Руслан
    Май 28th, 2013 at 21:18
    23

    Ввожу вот это условие из Вашего примера:

    # проверям логин
    if(!preg_match(«/^[a-zA-Z0-9]+$/»,$_POST[‘login’]))
    {
    $err[] = «Логин может состоять только из букв английского алфавита и цифр»;
    }

    Вставляю себе в код:

    $login = $_POST[‘login’];
    if ($login != «»)
    {
    if(!preg_match(«/^[a-zA-Z0-9]+$/»,$_POST[‘login’]))
    {
    if ((strlen($login) >= 2) and (strlen($login) <= 25))
    {
    echo $login;
    }
    else
    {
    echo "Вы ввели не корректные данные в поле \"Имя\"";
    echo "»;
    }
    }
    else
    {
    echo «буквы не английские»;
    }
    }
    else
    {
    echo «Вы не ввели данные в поле login»;
    }

    Когда заполняю поле с логином английскими буквами, и нажимаю кнопку для отправки в файл обработки, мне выдает, что буквы не английские, русские буквы почему-то выводяться нормально?

    [Ответить]

  24. Руслан
    Май 29th, 2013 at 11:17
    24

    if (preg_match(‘#^[A-Za-z0-9]+$#’,$login)), а вот так ввел, работает!

    [Ответить]

    ZekMan Reply:

    Я рад что Вы самостоятельно разобрались с проблемой 🙂

    [Ответить]

  25. kkolorid
    Май 30th, 2013 at 10:15
    25

    Warning: Cannot modify header information — headers already sent by (output started at Z:\home\localhost\www\hyip\account\login.php:8) in Z:\home\localhost\www\hyip\account\login.php on line 45

    И так со всеми заголовками… Делаю на Денвере. Что делать? 🙁

    [Ответить]

    ZekMan Reply:

    у вас что то выводиться до старта сессии.
    session_start должно быть до вывода чего либо на экран. Так же проверьте что бы файл был сохранен как utf-8 без BOM.

    [Ответить]

    ZekMan Reply:

    у вас что то выводиться до старта сессии.
    session_start должно быть до вывода чего либо на экран. Так же проверьте что бы файл был сохранен как utf-8 без BOM.

    [Ответить]

  26. Sineq
    Июнь 3rd, 2013 at 15:44
    26

    Warning: Cannot modify header information
    что делать?

    [Ответить]

  27. Павел
    Сентябрь 7th, 2013 at 18:21
    27

    Код не понравился. Особенно не понравилась подключение к БД. Автор, вы, я надеюсь, знакомы с таким понятием, как — класс? Видимо нет. Я понимаю, если пишешь одну страничку с регистрацией, то такой код приемлем. В остальных случаях так можно просто базу «убить».

    [Ответить]

    ZekMan Reply:

    Код приведен в ознакомительных целях поэтому не нагружен ООП и прочими радостями жизни. Цель — показать логику максимально доходчиво. Отнюдь не каждый может сразу понять как функционируют функции и классы, их области видимости и т.д. когда начинает учиться программировать.
    Кто работает в веб разработке — даже не будет читать подобные статьи, он уже знаком с тем как правильно организовывать код, как построить свое приложение. Еще раз повторюсь что данная статья ориентирована на новичков.

    Если

    [Ответить]

  28. Макс
    Ноябрь 18th, 2013 at 16:12
    28

    Доброго времени суток. Куда обработку выхода писать (в какой файл)? Можно подробнее про него?

    [Ответить]

Страницы комментариев

Написать комментарий