Пользователь
0,0
рейтинг
10 июля 2007 в 02:07

Разработка → Основы безопасности PHP

PHP*
Данный материал для начинающих программистов.

Содержание





Демонстрация ошибок


Почему так часто я вижу, зайдя на какой-нибудь сайт что-то подобное этому:
Warning: Use of undefined constant LOCAL_SERVER — assumed 'LOCAL_SERVER' in /web/includes/page-definitions.php on line 13


Это одна из стандартных PHP ошибок, которая а) некрасива для пользователя; б) потенциально опасна.
Поэтому их необходимо перехватывать и упорядочивать.

Во первых, функция error_reporting позволяет нам решить, какие ошибки мы хотим видеть.
В принципе, достаточно просто выключить показ всех ошибок (error_reporting(0)), но нам нужно не это, потому что об ошибках мы хотим знать.
Константа всех ошибок — E_ALL.
В пятой версии появилась константа E_STRICT, показывающая строгие замечания по поводу кода.
Разумеется, их желательно видеть, но они не входят в E_ALL, потому будем использовать числовое значение error_reporting(8191), которое вбирает всё, вплоть до новых ошибок шестой версии.

Примечание для любознательных: error_reporting(E_ALL | E_STRICT) не подходит, ибо тогда PHP 4 будет ругаться, не зная, что такое E_STRICT. С численным значением никаких проблем не будет.


Добавляем проверку на DEBUG — константу, выставленной в конфиге, и, с помощью set_error_handler, будем отлавливать ошибки в уже запущеном сервисе. Кстати, свой репортер ошибок должен возвращать true, иначе PHP выбросит стандартную ошибку.

Результат:
(Насчёт сравнения переменной с пятью параметрами я не уверен в выборе метода: in_array красивее, и гораздо медленее, а switch case case быстрее, но совсем некрасиво. Красота — субъективное дело...)
	<?php

		error_reporting(8191);
		if (!DEBUG)
		{
			function errorHandler ($errno, $errstr, $errfile, $errline)
			{
				// Запись в БД или отсылка по почте вебмастеру.

				if	($errno == E_ERROR ||
					$errno == E_PARSE ||
					$errno == E_CORE_ERROR ||
					$errno == E_COMPILE_ERROR ||
					$errno == E_USER_ERROR)
				{	
					// Сообщение пользователю. Мол, «простите, облажались маленько»...

				}
				return true;
			}
			set_error_handler('errorHandler');
		}
	?>
	



register_globals


До версии 4.2.0 директива register_globals была в PHP включена по умолчанию.
Привело это к тому, что многие привыкли, что если в форме есть , то в PHP коде можно проверять if ($username == 'admin')…

Однако это потенциальная дыра, которая привела ко множеству взломов.
Поэтому к POST, GET, COOKIE переменным надо обращаться через superglobals $_POST, $_GET, $_COOKIE.
Многим это показалось слишком трудно и стала очень популярной команда import_request_variables, возвращающая всё на круги своя.
Так вот.
Не делайте этого.

Другая проблема с register_globals:
	<?php
		...
		if (check_admin($..., $...))
		{
			...
			$user_level = 169;
		}
		...
		if ($user_level > 150)
		{
			echo 'Boom!';
		}
	?>
	

Если пользователь — не администратор, а переменная $user_level не инициализирована
(ей не придано значение 0 в начале скрипта, в надежде, что оно 0 автоматически),
то нехороший человек может дописать в адресной строке foo.php?user_level=999 и получить доступ.


SQL injection и magic_quotes


Так популярна среди начинающих конструкция
	<?php
		$user = mysql_fetch_assoc(mysql_query("SELECT * FROM `users` WHERE `username` = '{$_POST['username'}' AND `password` = '{$_POST['password']}'"));
	?>

	

опасна. Если пользователь введёт вместо пароля ' OR `username` = 'admin, то система впустит его как админа.

Приведённый пример, разумеется, элементарен.
Но если не решить проблему глобально, всегда можно пропустить какой-нибудь запрос, подверженный SQL injection.
Для борьбы с этим разработчики PHP решили сделать так, чтобы вся информация, поступающая от пользователя, подвергалась обработке и все кавычки escapeились (перед ними ставится слэш, что делает команда addslashes).
Что случилось? Вся информация от пользователя приходит со слэшами. Даже та, что вроде слэши получить не должна. Например, комментарии к статье.
Мало того, это не 100-процентный способ защиты от SQL injection.

Решение. а) со всей входящей информации снимаеи слэши, если они есть. б) Всю информацию, поступающую в SQL запрос фильтруем специально для этого созданной функцией mysql_real_escape_string (или аналогом для другой базы данных).

Снимаем слэши:
	<?php
		{
		if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
		{
			function stripslashes_deep($value)
			{
				if(is_array($value))
				{
					$value = array_map('stripslashes_deep', $value);
				}
				elseif (!empty($value) && is_string($value))
				{
					$value = stripslashes($value);
				}
				return $value;
			}
	
			$_POST = stripslashes_deep($_POST);
			$_GET = stripslashes_deep($_GET);
			$_COOKIE = stripslashes_deep($_COOKIE);
		}
	}
	?>

	


Создаём функцию для фильтрации (mysql_real_escape_string — длинно, да и привязанно к формату проверки. А если понадобиться поменять фильтр?)
	<?php
		function quote($value) {
			if (!is_numeric($value)) {
				$value = "'".mysql_real_escape_string($value)."'";
			}
			return $value;
		}
	?>

	

И используем её везде. Как только какие-то динамические данных отсылаются SQLу, сразу используем quote:
	<?php
		$user = mysql_fetch_assoc(mysql_query('SELECT * FROM `users` WHERE `username` = '.quote($_POST['username']).' AND `password` = '.quote($_POST['password'])));	
	?>

	



Проверка данных


Проверяйте всё, что вводит пользователь.
По умолчанию он злоумышленник.

Старайтесь не фильтровать, старайтесь валидировать.
Другими словами, не создавайте чёрного списка, создавайте белый.
Вместо
	<?php
		if (are_bad_symbols($data)) boo();
	?>
	

используйте
	<?php
		if (!all_good_symbols($data)) boo();
		// Например:
		is_numeric($data);
		preg_match('/[a-z0-9_-]*/i', $data)
		...
	?>

	

Так вы будете уверены, что информация чиста и никаких неожиданностей не будет.
Если вы составляете список запрещённых символов, всегда можете просмотреть какой-нибудь нехороший %00 и подобные, о которых, скорее всего, не догадываетесь.

Разумеется, есть ситуации, когда нужна фильтрация, например, когда пользователь пишет комментарий.
Тогда надо отсекать плохие символы.
Но в принципе стараться надо валидировать.

Есть несколько команд, с которыми надо обращаться очень осторожно.
Это include, require, readfile, eval, ``, system, exec, create_function, dir, fopen и подобные.
Всегда посмотрите трижды, когда используете их, если в них используются данные, которые могут прийти от пользователя, будьте уверены — кто-то обязательно этим воспользуется.
	<?php
		include($_GET['module'] . '.php');
	?>
	

Этот кусок опасен. Если злоумышленник введёт '../../../../../etc/passwd%00', будет рад, а вы — вряд-ли.

Аутентификация


Не забывайте, что cookies редактируются ни чуть не сложнее, чем то, что видно в адресной строке.
Поэтому всё, что приходит как печенье, потенциально — атака.
Так что не надо хранить в cookies уровень доступа пользователя или его ID.
Лучше всего дать PHP самому разбираться с этим, используя сессии.
	<?php
		session_start();
		$_SESSION['userid'] = 168;
		session_write_close();
	?>
	


Кстати, в cookies вообще хранить что-либо надо очень скромно и три раза подумать, а надо ли?


Вывод


Всё время думайте о данных в переменных $_GET, $_POST, $_COOKIE, как об атаке злоумышленника.
Trust no one! :)
akral @akral
карма
50,5
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (185)

  • 0
    Спасибо за статью! Побольше таких=)
  • 0
    Отличная статья! Мне очень понравился стиль изложения: что написал программист — как это можно сломать — как защититься.

    Но мне всё-таки кажется, что таким важным вещам лучше учить сразу. Если человек уже год пишет рабочие сайты и ещё не разу не слышал об этих мерах безопасности, у него есть хороший повод пересмотреть свой код :)

    Подсказка авторам книг и другой учебной литературы: если рассказываете про MySQL, то одним из пунктов обязательно нужно рассказать про SQL injection.
    • 0
      > Но мне всё-таки кажется, что таким важным вещам лучше учить сразу.
      Это я про то, что программиста с 12-18 месяцев стажа уже нельзя назвать начинающим.
      • 0
        С утра посмотрел и тоже немножко усомнился в своей адекватности. %)
        Исправил.
  • +3
    Явно преувеличен стаж, безопасность — это следующий урок любого программиста, который выучил как сделать "Hello World!" тремя и более способам. Приведенные проблемы относятся к начальному уровню, то есть для новичков.

    Для валидации данных полезно использовать такие функции как intval, ctype_*. Если набор возможных значений заведомо известен, то in_array тоже сойдет. В куки вообще лучше хранить только хэш сессии, а всё остальное на сервере или в БД. Динамически подключаемые файлы должны проверяться на местонахождение, ограничивать папку для возможных файлов, например. А лучше, конечно, иметь список допустимых файлов.
    • 0
      По поводу стажа согласен. Да и вообще, таких статей в интернете куча. И во всех написано тоже самое. Надоели эти статьи для новичков, даёшь что-нибудь интересно для Pro.
      > куки вообще лучше хранить только хэш сессии
      не согласен, сессии тоже не самый лучший вариант, так как при нетрудной атаки, можно создать такое количество сессий, что сервак не выдержит... Подробнее в гугле.

      А куки я считаю нормальным местом для хранения данных. А то, что у юзера могут вытащить куки трояном, то это его вина, а не программиста.
      • 0
        Троян — не единственный вариант. Ещё есть XSS. А есть вообще такие данные (например, сумма заказа, или уровень прав доступа) — которые нельзя хранить в кукисах по соображениям безопасности.
        • 0
          XSS может быть только по вине программиста, если программист внимательный, то он избежит данной ошибки.
      • +1
        А мне бы хотелось прочитать статейку (ну в идеале книжечку, а лучше 2) с названием типа этого: как построить систему из 1000 серверов за 21 день :)
        • 0
          Простите, не силён. :)
      • 0
        А куки я считаю нормальным местом для хранения данных. А то, что у юзера могут вытащить куки трояном, то это его вина, а не программиста.

        Sniffing, XSS, дополнительный траффик, отключенные куки.

        И о юзерах надо заботиться, если они — ваши клиенты. Ваше заявление из разряда «плевал я на поддержку IE, нефиг пользоваться левым браузером».
        • 0
          то есть вы хотите сказать, что в сессиях лучше и безопаснее хранить к примеру логин и пароль, чем в куках?
          • 0
            Зачем хранить логин и пароль? Храните ID пользователя.
            На крайняк - храните в зашифрованном виде.
            • 0
              > Зачем хранить логин и пароль?
              затем, чтобы человек после авторизации мог не вводить свой пароль пару дней. К примеру вот прям тут(на етом сайте) в куках хранится hha - это ID юзера, и hhb - пароль в зашифрованом(md5) виде. Если я не ошибаюсь конечно.

              > На крайняк - храните в зашифрованном виде.
              А если так, то какую вы здесь видеть дырку?
              <?
              // Для наглядности
              $login = "12345"; // Логин
              $pass = "mypass"; // Пароль
              $ip = $_SERVER['REMOTE_ADDR']; // IP
              $hash = md5($pass.$ip); // Получаем зашифрованный пароль и айпи в одну строку. То есть теперь у нас пароль привязан к IP. И если его украдут у пользователя, то на другой машине он будет безполезен.

              // Сохраняем инфу в куки
              setcookie("login", $login, ...
              setcookie("pass", $hash,...
              ?>

              На странице проверки авторизации:

              if(isset($_COOKIE['login']) and isset($_COOKIE['pass']))
              {
              // Запрос, который вытащит пароль юзeра с ID $_COOKIE['login']
              mysql_query....


              // Представим, что в переменной $user['pass'] лежит пароль вытащенный сейчас из БД
              if(md5($user['pass'].$_SERVER['REMOTE_ADDR']) === $_COOKIE['pass'])
              {
              // юзер авторизован
              }
              else
              {
              // не авторизован
              }
              ?>
              • 0
                В вашем примере есть дыра.
                Во первых, могут (и наиболее вероятно) украсть из локальной подсетки с тем же IP.

                Во вторых выдавая хеш пользователю, вы раскрываете алгоритм шифровки, что не хорошо.


                А зачем вам хранить пароль?
                if (isset($_SESSION['userid'])) $db->get('... WHERE `id` = '.$_SESSION['userid']));

                Зачем проверка на пароль вообще?
                • 0
                  Эмм, как зачем. :D Вы когда где-нибудь авторизируетесь, вы что только логин вводите?

                  > Во вторых выдавая хеш пользователю, вы раскрываете алгоритм шифровки, что не хорошо.
                  Я не спорю, можно создавать рандомный хеш при авторизации, сохранять его в БД и ложить в куке и потом просто сверять два хеша.
                  • 0
                    Я не спорю, можно создавать рандомный хеш при авторизации, сохранять его в БД и ложить в куке и потом просто сверять два хеша.

                    Так это и есть сессии!
                    session_register это и делает без лишних телодвижений.

                    Идентификатор сессии и есть авторизация.
                    • 0
                      ну у сессии ограниченное время жизни. как я понимаю, потому куки и нужны
              • 0
                У меня отключены куки. Что мне делать? =)
                • 0
                  у меня нет интернета, что мне делать?
                  /* люди до сих пор размышляют, что делать с теми у кого отключены куки, но таких уже не осталось */
                  • 0
                    ну как же не осталось - у нас портал 4.2К пользователей, так я как-то системку для опросов и тестов написал, с использованием куки, так потом выяснилось, что у многих они отключены, пришлось потом исправлять.
                • +1
                  вернутся в 90е ;-)
            • 0
              Даже не ID пользователя можно хранить в куках и зашифрованный пароль, а ID авторизации (не сессии) и md5 какой-то случайной строки.
              • 0
                Накой вообще что-то хранить в куках, если есть сессии?
                Максимум что я храню в куках - дату последнего визита или на других проектах - уникальный ID посетителя (чтобы статистику обсчитывать более точно).
                • 0
                  В куках хранить инфу только для автоматического захода через N-ное количество времени. У вас же сессии 2 недели не живут? ;)
                  • 0
                    Этого ещё не хватало, чтоб они жили по 2 недели ))
              • 0
                Т.н. сеансовый ключ. Чем вам не нравится PHPSESSID, при условии VDS или приватного сервера, конечно?
                • 0
                  Не понял, при чём здесь выделенные и приватные сервера? Сессиями пользуюсь во всю. Куками гораздо реже. Но именно для автоматического захода спустя большой промежуток времени, предпочитаю хранение инфы в куках.
                  • 0
                    На шаред-хостинге легко украсть содержимое сессии, украв куку.

                    Как вы передаете сессионный ключ между страницами?
                    • 0
                      В куках. Ограничиваю время жизни сессии. Да и у меня собственный сервер.
                  • 0
                    папка tmp имеет права доступа 0777 и её легко может прочитать любой скрипт, находящийся на том же хостинге. Дальше рассказывать?
                    • 0
                      Всё, дальше не надо. :)
                • 0
                  Много ли народу берёт под свои проекты VDS?
                  • 0
                    "20 долларов то не лишние..." :)
                    Мне проще отдать $20, зная, что это будет мой (почти) сервер, в котором я сам буду ставить Apache(Nginx), PHP, MySQL(SQLite,PostgreSQL) и никакой супер-админ не поставит какую-нибудь хрень.

                    За всех, конечно, сказать не могу.
                    • 0
                      Во-во. Мне тоже проще, но другим - нет )
          • 0
            Да.

            Но пароль-то зачем хранить в любом случае?

            Если очень нужно (зачем?), то храните хеш. По сути данные в сессии хранятся в файловой системе так же, как БД, так что никакой опастности, если только не будет перехвачен session ID, но для этого можно добавить привязку к IP, User-Agent, ...
            • 0
              А вам не кажется, что чтобы перехватить session ID нужно одинаково столько же времени, сколько и на кражу кук? Ну разве что, вы будете передавать сессион ид в УРЛ... но это сейчас не в моде + юзер может сам случайно передать свой ID сессии злоумышлинику...
              • 0
                Да, но украв session ID, злоумышленник будет иметь просто тупой хеш, а украв пароль из куков, или даже его хеш, злоумшленник будеть иметь более важную информацию :)
              • 0
                Если плюшки-печенюшки выключены, то session id всегда передаётся по url.
                Разберитесь с механизмом работы сессий.
                • 0
                  Кто вам сказал, что я не знаю об этом?
                  • 0
                    > Ну разве что, вы будете передавать сессион ид в УРЛ... но это сейчас не в моде

                    Вот тут написано, что Вы этого не знаете. Модно/немодно - это размышления не программиста, а блондинки в супермаркете.
                    • 0
                      А я не программист. Я кодер.
                      • 0
                        Тогда всё ясно
                        • 0
                          где можно почитать про это =) ?
                          • 0
                            Про что?
                            • 0
                              про программистов и кодеров
                              • 0
                                Поищите в Гугле. Не помню просто на каком сайте это пробегало.
                    • 0
                      + по урл передовать не безопасно
                      + разве тока блондинки носят модный шмот? а да точно, я забыл, программисты строго классику:D
                      • 0
                        1. Согласен.
                        2. Ошибаетесь =) Не поверите, иногда программисты занимаются не только программированием. Я вот например ещё резидент в одном крупном клубе )

                        Короче, мы уже начали с Вами придираться к образным фразам. Давайте оставим это занятие для других...
                        • 0
                          =) ок
            • 0
              В итоге мы получаем, что хранение пароля и логина в сессиях и куках одинаково опасно, только сессии ещё могут и положить сервак, если грамотно DDOSнуть и тогда их кол-во перерастет за несколько сотен тысяч..
              • 0
                В итоге чего? О_о

                Говорю же, нельзя давать даже хеш пароля! Взламывается даже md5!
                • 0
                  Здесь я согласен, возможен вариант как я описал выше "10 июля 2007 15:29 "
                  • 0
                    А чем он отличается от мною с самого начала предлагаемых сессий?
                    • 0
                      тем что сессиями можно уложить сервер, читайте ниже "10 июля 2007 15:37"
                • 0
                  Есть ли взлом md5 без банального брутфорса?
                  Гуглил-гуглил, не нашел ничего интересного :(
              • 0
                1 000 000 сессий по 200 байт это 200 Mb. Согласен, никакой сервак не выдержит. :))
                • 0
                  Проконсультируйтесь у сис.админов по этому поводу.
                • 0
                  Сессии создаются в ТМП. Время жизни 30 минут.

                  Каждый раз при создании сессии проверяется уникальность сгенерированного кода. 5000 файлов практически уводят сервер в даун
                  Уникальность проверяется чтением папки ТМП, сосбственно чтение и убивает сервер
                  • 0
                    Похоже на страшную сказку по запугиванию юнцов-кодеров. Это абсолютная чушь. Да и кстати вы можете сами указывать session_name.
                    • 0
                      Нет не сказка, об этом мне рассказывал человек Tibor - который когда-то создал самый быстрый и безопасный клон нюки - xNuke. Также он давно занимается создание и поддержкой проектов, с очень большой посещаемостью.
                      > Это абсолютная чушь
                      Аргументы?
  • 0
    Мне как раз очень нужно это все, спасибо. Только вот появилась надежда на продолжение. =)
  • 0
    есть очень хорошее правило - никогда не доверять тому, что отправил пользователь через браузер. Абсолютно всё нуждается в проверке.

    Есть два относительно надёжных места хранения инфромации - это сессии и БД
  • +1
    Слишком сумбурно и непоследовательно.
    Пишется "не делайте так", "потенциальная опастность", а объяснений "почему" нет.
    В пятой версии появилась константа E_STRICT, показывающая строгие замечания по поводу кода. Разумеется, их желательно видеть, но они не входят в E_ALL, потому будем использовать числовое значение error_reporting(8191)

    Только что константы были, теперь какое-то непонятное число. Почему не
    error_reporting(E_ALL | E_STRICT)?
    • 0
      И правда, непонятно. Я редактировал после, потому получилось бессвязно.

      PHP 4 не знает E_STRICT и будет ругаться. А используя числовое значение, мы уверены в корректной работе.
      • 0
        а кто мешает проверить на наличие E_STRICT и при его отсутствии создать его с нужным значением?
  • 0
    поправьте ошибку в заголовке.
    "Безопасности", а не "Безопастности".
    • 0
      лучше не нужно, это сразу очень сильно характеризует адекватность статьи...
    • 0
      Спасибо ;)
      • 0
        не за что :)
  • +1
    "Поэтому их необходимо перехватывать и упорядычивать."
    ошибки не надо перехватывать, их надо исправлять

    "Создаём функцию для фильтрации (mysql_real_escape_string - длинно)"
    переименование функций - зло, пользуйся редакторами с автокомплитом

    "Не проверяйте на наличие плохих символов. Проверяйте на отсутствие нехороших. Вместо"
    разницы абсолютно никакой, всё зависит от ситуации

    "Данный материал для начинающих программистов (ИМО, до 12-18 месяцев стажа)."
    добрая половина материала вообще не рекомендуется к прочтению, как растлевающая умы молодым и неокрепшим в профессиональном смысле разработчикам
    • 0
      > добрая половина материала вообще не рекомендуется к прочтению, как растлевающая умы молодым и неокрепшим в профессиональном смысле разработчикам
      Согласен.
    • 0
      добрая половина материала вообще не рекомендуется к прочтению, как растлевающая умы молодым и неокрепшим в профессиональном смысле разработчикам

      /me морг-морг глазами
      В смысле?
      • 0
        в смысле - статью новичкам лучше не читать, им будет только хуже...
        ты это поймёшь, чуть попозже...
        • 0
          Простите, о Великий Гуру!
          • 0
            и не надо язвить, к критике надо относиться с пониманием
            • +4
              К критике в стиле «подрастёшь — поймешь» и обращению на «ты», думаю, можно относиться и с иронией. ;)
              • 0
                эм... тебя так задевает обращение на вы?
                хм...
                ну если ты действительно не принял (не понял) 3 моих замечания, разве это не повод рассуждать о том - что ты поймёшь их позже (см. дорастёшь) не?
                • 0
                  *на ты
                • 0
                  Просто, как я видел раньше, на хабре принято обращаться на «вы». Кроме того, в контексте «подрастёшь — поймёшь», переход на ты имеет дополнительный эмоциональный окрас. А в принципе мне до лампочки, так что можете общаться и на ты :)

                  Конструктивно рассмотрим ваши замечания:
                  "Поэтому их необходимо перехватывать и упорядычивать."
                  ошибки не надо перехватывать, их надо исправлять

                  То-есть ваш код такой идеальный и 100-процентно хороший, что никогда и нету таких ситуаций, когда он вывалится с ошибкой? Например перегруз БД, когда она плюётся «Невозможно выполнить»?
                  "Создаём функцию для фильтрации (mysql_real_escape_string - длинно)"
                  переименование функций - зло, пользуйся редакторами с автокомплитом

                  Согласен, но я имел ввиду немного другое, и сейчас дополнил статью.
                  Фильтрация данных может измениться, может произойти переход на другую БД, а менять «myqsl_» на «foosql_» во всём коде даже с автозаменой нехорошо.
                  "Не проверяйте на наличие плохих символов. Проверяйте на отсутствие нехороших. Вместо"
                  разницы абсолютно никакой, всё зависит от ситуации

                  Разница есть. Разрешая только a-z0-9_, мы уверены, что эти символы ничего плохого не сделают. Запрещая '"`\, мы можем забыть запретить нулл-байт или другие контрольные символы.
                  "Данный материал для начинающих программистов (ИМО, до 12-18 месяцев стажа)."
                  добрая половина материала вообще не рекомендуется к прочтению, как растлевающая умы молодым и неокрепшим в профессиональном смысле разработчикам

                  Это неконструктивное замечание. =)
                  • 0
                    "То-есть ваш код такой идеальный и 100-процентно хороший, что никогда и нету таких ситуаций, когда он вывалится с ошибкой? Например перегруз БД, когда она плюётся «Невозможно выполнить»?"
                    я не говорил про Ваш код, я не говорил про свой код. Я лишь откомментировал Ваш совет новичкам
                    "Поэтому их необходимо перехватывать и упорядочивать."
                    После этой фразы начинающие программисты будут считать, что перехват и умалчивание ошибок - нормальная практика, вместо того, что бы писать хороший код

                    "Фильтрация данных может измениться, может произойти переход на другую БД, а менять «myqsl_» на «foosql_» во всём коде даже с автозаменой нехорошо."
                    экранирование переменных - меньшее что Вас будет заботить при переходе на другую СУБД. Даже при использовании DBAL, так или иначе диалект sql будет иным

                    "Разница есть. Разрешая только a-z0-9_, мы уверены, что эти символы ничего плохого не сделают."
                    проверяя preg_match('/^[a-z]+$/', $var); или preg_match('/[^a-z]/', $var); мы в варианте 1 проверяем на вхождение в дозволенный интервал, в варианте 2 - на вхождение в недозволенный. Оперируя вашей фразой - вариант 1: проверка на отсутствие плохих символов, 2: проверка на наличие плохих
                    т.е. как раз тот вариант - когда разницы никакой

                    "Это неконструктивное замечание. =)"
                    хм.. как бы то ни было - я бы не посоветовал её читать никому из начинающих. в этом плане гораздо полезнее тот же phpfaq.ru
                    • 0
                      >>"Поэтому их необходимо перехватывать и упорядочивать."
                      >После этой фразы начинающие программисты будут считать, что перехват и умалчивание ошибок - нормальная >практика, вместо того, что бы писать хороший код
                      До появления исключений, многие эмулировали их через trigger_error, и это нормально. Излишние проверки часто замусоривают систему, особенно работе на разных слоях, приходится дублировать проверки везде. Перехват ошибок нормальная практика и как-то странно с этим спорить. Идеального кода не бывает.

                      Насчет проверки данных. Различают два понятия: валидация и фильтрация. То, что описано в статье именно валидация, т.е. проверка по белому списку. С другой стороны фильтрацию тоже никто не отменял. У них логически разные предназначения
                      Пример: пользователь пишет комментарий (e-mail и текст). E-mail нужно проверять по
                      • 0
                        Обрезалося! Добавьте, пожалуйста!

                        Предпологаю, что вы хотели сказать, что email надо вылидировать, а текст фильтровать, и будете правы.
                        • 0
                          Да именно это и хотел. Не дополните ли статью на тему фильтрации? А еще бы хорошо заменить все таки авторизацию, на аутентификацию, тоже разные вещи все таки.
                          • 0
                            Поправил.
                            И разницу между авторизацией и аутентификацией подметил. :)
                  • 0
                    Например перегруз БД, когда она плюётся «Невозможно выполнить»?
                    ОМГ... Это исключительная ситуация.
    • 0
      "переименование функций - зло, пользуйся редакторами с автокомплитом"
      а повышать читаемость кода тоже зло? или делать обвертки с возможностью дополнить их в будущем?
      • +1
        стороннему программисту, который будет читать код - проще понять нативные функции, чем никому не нужные врапперы. так что читабельность тут только страдает.
        • 0
          К примеру, if (is_email($data)) гораздо читабельнее, чем if (preg_match('/QLNqufQPPIDHQWODn,amnDWALjdnqdQLOWHFQLO/',$data)) =)
          • +2
            не юлите
            я говорил о конкретном частном создании алиаса на функцию, а не об инкапсуляции сложной логики
  • 0
    Да, очень полезно. Спасибо.
  • 0
    Не проверяйте на наличие плохих символов. Проверяйте на отсутствие
    нехороших.

    - явно имелось ввиду:
    Не проверяйте на наличие плохих символов. Проверяйте на отсутствие
    хороших.
  • 0
    Тоже внесу несколько своих замечаний:
    1. E_STRICT - вещь замечательная хотябы потому, что выдает замечания по depricated (устаревшим) функциям (начинающему программисту пригодится).
    2. Можно ловить ошибки и errorHandler, однако куда красивее display_error в нет, а писать в логи, естественно после запуска. Иначе пользователь у вас будет видеть всегда "Мол, «простите, облажались маленько»...", а вы будуте часами искать ошибки.
    3. Про register_globals, ну не знаю кто ее еще применяет...
    4. По поводу слешей: отключайте меджик слеши вполучаемых переменых и используйте mysql_real_escape_string, зачем огород городить и придумывать велосипед...
    5. И инклудах используйте define, так советует PHP.
    6. Прор куки согласен, храните в сессии.
    • 0
      1. Согласен. Я так и написал. :)
      2. На мой взгляд, позволять пользователю видеть пустую страницу вместо извинения — очень плохо. Он будет неудомевать, пробовать заново. А в логи моя функция так и так пишет. Вы бы в начале прочитали её ещё раз. ;)
      4. Начинающие программисты вряд ли имеют доступ к глобальному конфигу и знания, как выключить magic_quotes. Очень часто вы находитесь на shared сервере, а set_ini тут не работает, поскольку к моменту выполнения set_ini magic_quotes уже поработали.
      5. Не могли бы вы перефразировать? Никак не пойму. :(
      • 0
        2. Естественно выводить что-то, я разве против. Где у вас там запись в логи?
        4. Сложно найти хостинг где не работает .htaccess и в нем нельзя прописать magic_quotes в оф.
        5. Попробую объяснить:

        <?php
        $x = '/usr/local/php/includes';
        include($x.'include.php');
        ?>

        Unsafe use of variable in call include()/require() (line 4)
        • 0
          2. "// Запись в БД или отсылка по почте вебмастеру."
          4. Мммм... Согласен.
          5. А что делать, если я динамически выбираю модуль? Грубо говоря из $_GET?
          • +1
            2. log_errors проще, а еще представьте ту ситуацию когда у вас отсылка по почте или запись в БД тоже будет выдавать ошибку, что тогда:)
            5. Проверяйте, конечно, хорошенько что там инклудите:)
            • 0
              2. Хорошая шутка. :))
            • 0
              В стиле «давай сделаем два ящика — на рамблере и на mail.ru, сделаем переадресацию с одного на другой и обратно и отправим одно письмо!» :)
          • 0
            4. А пишите либо switch($_GET['module']), либо из БД вытаскивайте.
            • 0
              Кстати я из БД вытаскиваю.
              • 0
                Я тоже. ._.
      • 0
        4. Начинающие программисты вряд ли имеют доступ к глобальному конфигу и знания, как выключить magic_quotes. Очень часто вы находитесь на shared сервере, а set_ini тут не работает, поскольку к моменту выполнения set_ini magic_quotes уже поработали.

        В крайнем случае можно использовать старый как мир способ

        set_magic_quotes_runtime(0);

        function strips(&$el)
        {
        if (is_array($el))
        foreach($el as $k=>$v) strips($el[$k]);
        else
        $el = stripslashes($el);
        }
        if (get_magic_quotes_gpc())
        {
        sk_ga_strips($_GET);
        sk_ga_strips($_POST);
        sk_ga_strips($_COOKIE);
        sk_ga_strips($_REQUEST);
        if (isset($_SERVER['PHP_AUTH_USER'])) sk_ga_strips($_SERVER['PHP_AUTH_USER']);
        if (isset($_SERVER['PHP_AUTH_PW'])) sk_ga_strips($_SERVER['PHP_AUTH_PW']);
        }


        Вставить перед исполнением каждого php-скрипта. Лучше, в отдельный файл это запихнуть и каждый раз подключать.

        Недостатки, конечно, налицо, но если сайт не такой и посещаемый, то вполне приемлимое решение.
        • 0
          Ну да... Вот он в статье и приведён. :)

          array_map > foreach
  • 0
    Что до SQL-инъекций... от них очень помогают Prepared statements. И вот на ЭТО как раз следовало бы обратить внимание.
    А вообще топик - страшный баян. Если бы Вы здесь написали, что нить вроде
    mysql_* (namespace типа) лучше не пользовать, т.к. тяжело поддерживать сложные запросы и чревато ошибками, а лучше пользуйте вот хотя бы PDO или DbSimple на пару с prepared statements
    - плюсадин в карму однозначно. Просто за то что так НИКТО не пишет. А так... Ничего нового.
    • 0
      Я согласен, что такой информации много. Но её должно быть много. Потому начинающие как раз и не знают, что искать. И надо, чтобы они попадали на такую информацию.

      И мне достаточно одного единственного "спасибо" в топике, чтобы понять, что не зря я это написал, что бы там профи не рассказывали. :)
      Карма, в отличие от этого, мне до лампочки. ;)
      • +1
        Если они не знают, что искать, значит им следует точнее формулировать свои вопросы/запросы/желания. И ни Вы сами, ни данный топик этой проблемы не решите. Это ИХ ЛИЧНАЯ ПРОБЛЕМА.

        Но согласитесь, что было бы замечательно приучать начинающих к безопасному программированию, не изобретая собственный четырехколесный велосипед каждый раз. Вы на PHPClasses.org видели, сколько там MySQL врапперов? 933 штуки. Каждый второй обязательно напишет и выложит СВОЙ. СОБСТВЕННЫЙ. ВРАППЕР MYSQL. Каждый третий - враппер курла. И все это чуть ли не под копирку. Даже дескрипшны не слишком разнятся.
        Кто это пишет? Разработчики symfony/creole/propel/doctrine/smarty? Вы прекрасно понимаете, что нет. Ваяют это как раз такие вот начинающие-"хачу-сибе-сцайт-на-РНР". Которые и алгоритм-то работы не слишком уверенно представляют и являются постоянными гостями http://worsethanfailure.com/.
        Карма, в отличие от этого, мне до лампочки.

        Я же не могу Вас угостить пивом, к примеру. Вот и приходиться искать суррогаты :)
        • 0
          ого, нехило! и оно растет! уже 946, прям как в гугле
        • 0
          Хорошо говорите, респект.

          Кстати, за линк спасибо. :)
  • 0
    > Во первых, функция error_reporting позволяет нам решить, какие ошибки мы хотим видеть.
    Я хочу видеть все, но что бы пользователь не видел никаких, поэтому использую:
    http://ru2.php.net/manual/ru/ref.errorfu…
  • 0
    Статья неплохая, однако: было б лучше, если Вы обосновывали некоторые положения простыми примерами, так сказать "на слониках". Например, касательно register_globals: то что это плохо Вы сказали, а _реального примера_ того, как это могут использовать для взлома нет.
  • 0
    упорядычивать → упорядочивать
    • 0
      Спасибо.

      /me стыдно.
  • 0
    Отличная статья. Я даже не начинающий, так, любитель-самоучка, мне было интересено. :)
  • 0
    Хорошая статья. Рекомендовал бы начинающим.)
  • 0
    Классная статья. Сейчас мне нужно приступать к разработке и я хорошо освежил безопасность в голове. Спасибо.
    • 0
      эту информацию надо знать, а не помнить ;)
  • 0
    автору большое спасибо!
  • +1
    Автору - респект. Когда я начинал заниматься PHP, то таких мануалов не было и приходилось всему учиться на своих ошибках.

    Кстати, новичкам ещё будет полезен вот этот сайт: http://www.omsk777.ru/all.php?act=web
    • 0
      Новичкам больше будет полезен ман и phpclub
      • 0
        Я тоже люблю сказать RTFM. Только я так отвечаю на вопросы. В ман можно лезть, когда знаешь, за чем лезешь. Просто так перечитывают ман никак не начинающие.
        • 0
          1. Изучая предмет не системно, а по принципу how-to, больших результатов не достигнешь.
          2. RTFM это одно, а профессиональное комьюнити - несколько иное.
          3. Есть поиск по этому комьюнити, выдающий решения по большинству вопросов, в том числе и по безопасности.
          4. По PHP очень удобный ман.
          5. Приведеный в пример сайт - потуги таких же "профессионалов", которые, не научившись языку, раздают советы направо и налево.
          6. "Просто так" ман никто не перечитывает.
          • 0
            Я просто так перечитываю ман. ._.
          • 0
            Если у меня кто-то из работников отвечает клиенту RTFM, то получает наряд вне очереди :))
            • 0
              Мы сейчас о клиентах или о программистах говорим? Я программист и смело посылаю всех, включая директора, к RTFM. Но дело не в этом! Я никого не посылал читать ман, если человек является ах***ным программистом, тогда конечно... зачем ему читать ман, он же и так все знает.
              А если серьезно... Меня бесят эти ах***но профессиональные сайты, на которых опубликованы статьи, раскрывающие тему "2*2=4", преподносящие предмет обсуждения как бином Ньютона или решение теоремы Ферма, блин, пиз*ец, сенсация, оказывается magic_quotes_gpc надо вырубать.... А кто-нибудь здесь знает вообще, что такое GPC, и как это расшифровывается?
              Нет, разумеется, давайте каждому (здесь есть тег, чтоп слова зачоркивать? Хотел вписать "лизать жопу") объяснять вещи, которые должны срабатывать на автомате... Наряд вне очереди... Хе-хе, Вы пойдите хорошего спеца по PHP найдите, потом будете раз 88 (восемьдесят восемь) думать насчет нарядов. Кстати, это ведь Вы написали статейку про Code Style (мол, надо то комментировать, это комментировать, отступы скобочки и т.д.). Вероятно, чуваки прозябающие в "нарядах", не знают, что такое "стиль кодирования", и мне от этого вас откровенно жаль.
              • 0
                Да верю, верю, что Вы круты и смелы :-) Много видел таких крутых и смелых.

                У нас пишут не на PHP, и я не отвлекаю своих людей от клиентских проектов на лично мои интересы и хобби ;-)

                Тег, чтоб слова зачеркивать? RTFM('HTML') :-)
                • 0
                  тогда уж по CSS
  • 0
    Статья понравилась, спасибо за неё. Тут, по крайней мере, собраны все основные источники небезопасности приложений: читать о каждом подробнее можно уже в других публикациях.

    Немного расстроил стиль большинства критиков: вместо исправления ошибок, лишь указывают на них (а ведь люди квалифицированные, могли бы предложить свои конкретные добавочки). Хотя, безусловно, имеются и содержательные комментарии. За них тоже большое спасибо.
  • 0
    Господа, не буду оригинален, но пора на свалку языки, допускающие подобное.
    Пока все нормальные языки двигались в сторону контроля типов и строгих конструкций, скриптовые языки всегда пытались услужить программистам, убирая "ненужную" декларативную писанину. Использовать в веб среде язык, не делающий существенного различия между кодом и данными и допускающий динамический code-injection просто безумие. Поэтому любой php скрипт по дефолту остается дырявым, пока не доказано обратное. Я призываю всех обратить внимание в сторону Java EE: JSP/JSTL и фреймворков типа JSF.
    • 0
      Очередной холивар? Давайте.
      Откуда это нормальные языки двигались к строгим типам? От нетипизированных ассемблеров?
      Вам не кажется, что изначально строгие типы, это ограничение компилирующих языков?
      Что значит "не делающий существенного различия между кодом и данными"? Вы знакомы с функциональным программированием и т.п? PHP по "неделанью различий" очень далеко до многих языков. Хотя вы можете считать их всех ненормальными.
      Поэтому любой php скрипт по дефолту остается дырявым, пока не доказано обратное

      Хватит выдвигать безумные лозунги, их тьма. Мотивируйте.
      Кстати, что вы подразумеваете под "скриптовыми" языками?
      • 0
        Вероятно интерпритируемые языки =)
        • –1
          А PHP не просто интерпретатор, а транслирующий. Java и C#, кстати, в некотором смысле тоже. Однако, различие интерпретатор/компилятор влияет только на скорость исполнения, но никак не на дырявость, типизированность и тому подобное.
          Скрипт, же переводится, как сценарий. Скрипты выполняются в других системах, манипулируя уже существующими объектами. Браузерный Javascript - скриптовый язык, а PHP никакой не скриптовый.
          • 0
            Я-то это понимаю...
            Но PHP всё-таки скриптовый язык... У него даже это по-моему в документации написано.
            • 0
              Документация нагло вводит в заблуждение =)
              • 0
                Всё может быть, но я склонен верить ей - не зря же её писали +)
                • 0
                  Про данный случай ничего не говорю, но вообще в РНР документации порой проскальзывают косяки, особенно в переводной.
          • 0
            PHP скриптовый и даже то, что парсенный код может повторно запускаться при установки некоторого софта никак на это не влияет.
    • 0
      Эх... vi против emacs, кто-нибудь? :)

      Я не знаю JSP, JSF, но я думаю, что человек умеющий может написать дырявый и опасный код и там, не правда ли? :)
      • 0
        Угу, было, да - недавно дырки закрывал в одном проекте на C# & ASP.NET. Его девелоперы о prepared statements явно даже не слышали. Или не хотели. ;)
    • 0
      Я призываю Вас идти нафиг с вашими советами.
      А лучше сюда - http://www.habrahabr.ru/blog/i_am_clever…
    • 0
      а никакой вступительной статьи только для "Java EE: JSP/JSTL и фреймворков типа JSF" нет? что-то я ничего толкового найти не смог.
      • 0
        Еще бы :)
        В J2EE Tutorial-е про JSP/JSTL/JSF первые 500 страниц.
        Вот мощь Enterprise-технологий :)
  • 0
    в контексте о magick quotes:
    Для борьбы с неправильными разработчиками, разработчики PHP решили все эскейпить. Теперь разработчики защищаются от разработчиков PHP выключением magick quotes )))
    • 0
      Разработчики 300 раз уже извинились за magick quotes и register_globals, и safe_mode. Ну хватит их уже пинать. Все эти опции включаются обычно недалёкими админами.
  • 0
    Спасибо, я как раз начинающий в php, статья понравилась.

    Насчет error_reporting(8191), так конечно нельзя, а что если код будет читать кто-то не читавший с вашу статью :) и попробуй догадайся, что-это.

    Стойт написать, что-то вроде:

    if(!defined(E_STRICT)) define(E_STRICT, 2048);

    хотя вам видней, я же начинающий
    • 0
      if (!defined("E_STRICT")) define("E_STRICT", 2048);
      кавычки не забываем :)
      • 0
        конечно, просто непривычно брать в кавычки имена переменных и констант
        • 0
          Это еще не имя константы :)
    • –1
      Хм... Начинающие так не пишут =) Новички бы понаставили кучу {} скобок и писали бы без пробелов после запятых =)
      • 0
        я начинающий в php
        • 0
          Да. я это понял уже после своего комментария ) Просто у меня php был первым языком.
      • 0
        Вы говорите об оформлении кода. Это приходит со временем. На алгоритм же не влияет никак.
        • 0
          Осознал уже после нажатия кнопки "добавить" )
    • 0
      Не поверите, в первой редакции этой статьи было так и написано.
      Но я подумал, что это излишество. Что такое 8191, можно узнать там же, где и что такое E_STRICT.
      А так две дополнительных комманды.
      • 0
        использование magic numbers в коде - плохой стиль программирования, как ни крути. почитайте книгу Макконнелла - там это рассмотрено очень подробно.
  • 0
    Хорошая статья, напомнила мне мой период паранои в первые месяцы программирования на PHP.

    Пожелания к статье: больше примеров "на слониках".
    Например, сказано что register_globals - зло, а примеры взлома с их использованием не приведены.
    Фраза "валидируйте все, что вводит пользователь" пугает своей сложностью =) Я бы сказал "Проверяйте" и "Trust no one" =)
  • 0
    Кстати, о SQL-инъекциях. Я часто использую функцию для выполнения запросов, увиденную мною в книге Котерова. Изначально расчитана на MySQL, но легко меняется и для другой СУБД.

    Выглядит так:
    mysql_qw('INSERT INTO users (name) VALUES (?)', $u_name);

    Работает аналогично sprintf: заменяет символы ? в строке запроса (1й параметр функции) на соответствующие ему значения и выполняет запрос. Перед заменой значения обрабатываются mysql_escape_string() и заключаются в кавычки.


    Код функции:

    $v) {
    if (!$i) continue; // это шаблон
    if (is_int($v)) continue; // целые числа не нужно экранировать
    $args[$i] = "'".mysql_escape_string($v)."'";
    }
    // На всякий случай запорняем 20 последних аргументов недопустимыми
    // значениями, чтобы в случае, если число "?" превышает количество
    // параметров, выдавалась ошибка SQL-запроса (поможет при отладке).
    for ($i=$c=count($args)-1; $i<$c+20; $i++)
    $args[$i+1] = "UNKNOWN_PLACEHOLDER_$i";

    // Формируем SQL-запрос.
    return call_user_func_array("sprintf", $args);
    • 0
    • 0
      тогда уж лучше использовать класс DB simple все от того же Дмитрия Котерова http://dklab.ru
      • 0
        Ну классы - это уже для продвинутых, мы говорим о начинающих
        • +1
          Начинающим нужно начинать с классов.
          • 0
            Не согласен.
            • 0
              Нет, нужно. По крайней мере, писать хоть мало-мальски сложные приложения нужно именно с применением ООП. В данном случае я имею в виду тех начинающих, к-рые решили наваять собственный, скажем, движок сайта. Даже самый примитивный.

              Процедурный подход must die. С его использованием можно писАть только примитивные гостевухи. И то, если поддержка этого творения не предполагается вообще. Иначе будет много секса в нехорошем смысле этого слова. То, что дофигища приложений на РНР созданы с его применением - ни о чем не говорит.

              З.Ы. Опыт поддержки веб-приложений созданных с применением процедурно-ориентированного подхода и вкраплениями ООП в стиле PHP4 имеется. Динамическая генерация членов класса прилагается. ~70000 LOC. Бррр. Методы по 300-400 строк, копипаст сплошь и рядом, многочисленные вложенные if'ы. Жуть, в общем.
              • 0
                Если более точно - с использованием процедурного подхода гораздо легче создавать неподдерживаемые приложения. Вот. :)
              • 0
                Абсолютно согласен, при грамотном использовании ООП самые большие методы (функции) не более 20 строк получаются, при том с предельно ясной логикой. К тому же, на число строк в большей степени может влиять желание вписать код в 80тисимвольный предел по ширине для удобочитаемости и вот примерно такие sql запросы:

                SELECT COUNT(*) AS `before`
                FROM `some_table`
                WHERE
                `some_id` = '{$this->somvar}' AND (
                `someoneelsevar` > '{$this->someproperty}' OR
                (
                `voices_number` = '{$this->onemoreproperty}' AND
                `id` user_id}'
                ))

                Уже не говоря о перевязке двух и более таблиц с различными JOIN'ами, группировками и т.д.
                • 0
                  Ой, из-за маленького окошечка с синтаксисом напутал :(
                • 0
                  рекорд - 10 JOIN'ов :) Запрос не помещался в монитор. Плюс куча if'ов, определяющих группировку и условие в where.
                  тысячу раз успел пожалеть, что DbSimple с ее условными Placeholder'ами не пользовали.
                  • 0
                    Ну из-за одного запроса, имхо, менять привычный БД-Струмент не стоит. К тому же некоторые фичи DbSimple, заявленные как преимущества, мне кажутся сомнительными.
                  • 0
                    и как на мускуле эти джойны работали? они сервак не ложили?
            • 0
              У начинающего должно точно в голову засесть объектно-ориентированное программирование, чтобы он не видел смысла писать что-то без использования классов. Сам же потом благодарить будет.
              • 0
                Хабразаряды закончились, поэтому +1 уходит в комменты :)
    • 0
      Речь идет о технологии Placeholder'ов, которая поддерживается, например такой штукой, как PEAR::DB и последователями (точно не помню ADODB кажется тоже держит плейсхолдеры), а также некоторыми БД на уровне их API для PHP, кроме того, смотрим про PDO Functions в мане
      • 0
        Да, забыл упомянуть названия, спасибо.
  • 0
    Может быть стоило просто дать ссылку на http://ru.php.net/manual/ru/security.php?
    • 0
      Может просто было написать RTF PHPM и не писать ни статьи ни камментов? =)
  • 0
    Хочу сказать спасибо за статью. Хотя для себя в ней ничего не прочел. Но знаю как это сложно собраться с духом и систематизировать свой опыт. Так как лишен хабара-потенции, то немогу добавить плюс. %)
  • 0
    Статья неплохая, как памятка, если случилась внезапная амнезия. Или тем, кто вообще только начинает, пожалуй.

    Вообще, чем больше я читаю статей по PHP, тем больше убеждаюсь в том, что заинтересованные делятся на две большие группы: те, кто хотят учится программированию и те, кто хотят учится программированию на PHP. Одна аббревиатура и один предлог решают вообще все, как не удивительно. Взять хотя бы ту прелестную радость, с которой php-шники открывают уже привычные вещи. Например, статьи в духе "что такое private в классах и где это использовать". Или "зачем нужны абстрактные классы". Круто.

    Автору респект, что грамотно оформляет материалы. Приятно смотреть.
    • 0
      Чтож вы нас (PHP-программистов) совсем за варваров чумазых держите? Разве идеология ООП и его принципы как-то принципиально отличаются в PHP, или, если чувак начал писать вызовы со "стрелочками", то он типа ОО программист на PHP?
      • 0
        Сюрприз: вы ушли в крайность и утрируете. Я не говорю, какие возможности предоставляет тот или иной язык. Я говорю про образ мышления и подход к разработке среднестатистического программиста.

        Кстати, я сам достаточно много пишу на PHP. Потому что альтернатив, которые "стоят вообще везде" у него нет. Разве что Perl.
        • 0
          Да, наверное, вы правы, я погорячился. Подход среднего представителя PHP фауны сообщества обусловлен жывучестью PHP приложений, содержащих ошибки, "собачкой", выключаемыми display_errors и настраиваемым error_reporting. Отсюда лень, невнимательность исполнителя и его же пофигизм.
    • 0
      те, кто хотят учится программированию и те, кто хотят учится программированию на PHP
      Кстати да, очень верно подмечено :) Желание учиться у вторых заметно ниже, чем у первых. А вот поиметь успех (читай бабло) нахаляву т.е. без труда - наоборот :)
      Например, статьи в духе "что такое private в классах и где это использовать". Или "зачем нужны абстрактные классы".
      Как это умиляет... непередаваемо :)

      Вообще же такого количества радостных ламеров "Йа нопесал гостевушко. Ergo йа - мегакодер!" я не встречал еще нигде. Вообще нигде. Даже на Delphi-сцене. Вероятно, потому что Delphi хоть как-то дисциплинирует. РНР же развязывает руки. Не навязывает ООП-подход. Не заставляет структурировать программу, выделять бизнес-объекты и работать уже с ними, разделять реализацию и представление, и т.д., и т.п.

      Кто-то скажет "мне это не надо, я и так неплохо работаю" - идите лесом и дальше пишите гостевухи и неподдерживаемые сайты/приложения, которые дешевле переписать с нуля, чем доработать. Доказывать очевидное считаю ненужным.

      З.Ы. Как обычно, все вышсказанное есть мое ИМХО.
      • 0
        Видимо стоит разделять такие понятия как "php-шник" и "PHP-программист", как линуксоидов и Пользователей Linux ;)
  • НЛО прилетело и опубликовало эту надпись здесь

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.