Данная тема предназначена для новичков, здесь будут описаны «нежелательные» примеры программирования, настроек, нарушений безопасности приложения, и правильные пути решения их. Модерируется строго! Оставляйте свои вопросы, так же сюда будут переноситься часть обсуждений из других тем.
PHP: <?php if(@$_GET['id']=='1') setcookie("tarif",'test1',time()+3600); if(@$_GET['id']=='2') setcookie("phone",'test2',time()+3600); if(@$_GET['id']=='3') setcookie("nomer",'test3',time()+3600); ?> <a href="index.php?id=1">1</a><br /> <a href="index.php?id=2">2</a><br /> <a href="index.php?id=3">3</a><br /> <?php echo '<pre>'; @print_r($_COOKIE); echo '</pre>'; ?> В приведенном примере плохой практикой является использование GET параметров без их проверки на допустимость, а так же подавление ошибок вывода.
PHP: <?php if(isset($_GET['page']) && !empty($_GET['page'])) include(trim($_GET['page'])); ?> Если в конфиге php разрешено инклудить файл с других серверов, то данный подход позволяет подключить скрипт с другого сервера (например http://mysite.com/?page=http://anothers ... script.php) Решение от Vladson'a PHP: <?php $mode = 'default'; if ( isset($_GET['mode']) ) { if ( !empty($_GET['mode']) ) { if ( !preg_match("#[^a-z]#s", $_GET['mode']) ) { $mode = $_GET['mode']; } } } $filename = 'modules/module_' . $mode . '.php'; if ( file_exists($filename) ) { include $filename; } else { include 'includes/error.php'; } ?>
PHP: <? $mode = isset($_GET['mode']) ? trim($_GET['mode']) : FALSE; if ($mode) { switch $mode; { case "1" : include "1.php"; break; ... } } else { include "default.php"; } ?>
Можно и без условия: PHP: <?php switch ($mode) { case '1': include '1.php'; break; // ... case 'n': include 'n.php'; break; default: include 'default.php'; break; } Тогда за загрузку модуля по умолчанию будет отвечать default:
PHP: <?php // Дано // mysql.table_categories = 100 items; таблица категорий товаров = 100 записей // mysql.table_products = 1000 items; таблица товаров = 1000 записей // Нужно вывести 1000 товаров с наименованием категорий. $time = array (getmicrotime()); //======================== // Метод 1. //======================== $result = mysql_query("SELECT category_id, name FROM table_products LIMIT 0, 1000"); while ($row = mysql_fetch_assoc($result)) { $result2 = mysql_query("SELECT name FROM table_categories WHERE id='{$row['category_id']}' LIMIT 1"); if (list($category) = mysql_fetch_row($result2)) { //... //print "category = {$category}, product = {$row['name']}<br />\n"; } } $time['1: query of while of query'] = getmicrotime(); //======================== // Метод 2. //======================== $categories = array (); $result = mysql_query("SELECT id, name FROM table_categories"); while ($row = mysql_fetch_assoc($result)) { $categories [$row['id']] = $row['name']; } $result = mysql_query("SELECT category_id, name FROM table_products LIMIT 0, 1000"); while ($row = mysql_fetch_assoc($result)) { //... //print "category = {$categories[$row['category_id']]}, product = {$row['name']}<br />\n"; } $time['2: two query and one array'] = getmicrotime(); //======================== // Метод 3. //======================== $result = mysql_query("SELECT p.name, c.name as category FROM table_products as p, table_categories as c WHERE c.id=p.category_id GROUP BY p.id LIMIT 0, 1000"); while ($row = mysql_fetch_assoc($result)) { //... //print "category = {$row['category']}, product = {$row['name']}<br />\n"; } $time['3: one query with two table'] = getmicrotime(); //======================== // Метод 4. //======================== $result = mysql_query("SELECT p.name, c.name as category FROM table_products as p LEFT JOIN table_categories as c ON c.id=p.category_id GROUP BY p.id LIMIT 0, 1000"); while ($row = mysql_fetch_assoc($result)) { //... //print "category = {$row['category']}, product = {$row['name']}<br />\n"; } $time['4: one query with LEFT JOIN'] = getmicrotime(); //======================== $last_time = null; foreach ($time as $label=>$value) { if (empty($last_time)) $last_time = $value; else { print "{$label} == ".($value - $last_time)." s. <br />\n"; $last_time = $value; } } function getmicrotime() { list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec); } ?> Результат: Код (Text): 1: query of while of query == 0,096814155578613 s. 2: two query and one array == 0,010401964187622 s. 3: one query with two table == 0,0089080333709717 s. 4: one query with LEFT JOIN == 0,0088870525360107 s. Для недоверчивых тестовые данные: [sql] CREATE TABLE `table_categories` ( `id` int(11) NOT NULL auto_increment, `name` varchar(255) default NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; CREATE TABLE `table_products` ( `id` int(11) NOT NULL auto_increment, `category_id` int(11) NOT NULL default '0', `name` varchar(255) default NULL, PRIMARY KEY (`id`), KEY `category_id` (`category_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; [/sql] Заполнение таблиц: PHP: <?php for ($i = 1; $i <= 100; $i++) { mysql_query('INSERT table_categories VALUES(null, '.$i.')'); for ($j = 1; $j < 10; $j++) { mysql_query('INSERT table_products VALUES(null, '.$i.', '.($i*100+$j).')'); } } ?>
Как не стоит делать: PHP: <?php mysql_connect("localhost", "root", ""); mysql_select_db("mydb"); $var = mysql_query("SELECT * FROM my_table WHERE status='On' AND selected='y'"); $var1 = mysql_fetch_array($var); for($i=0; $i<mysql_num_rows($var); $i++) { echo $var1['id']; // и т.д. } ?> или PHP: <?php mysql_connect("localhost", "root", ""); mysql_select_db("mydb"); $name = array("Вася", "Дима", "Саша", "Сережа", "Олег"); for($i=0; $i<5;$i++) { $var = mysql_query("SELECT * FROM my_table WHERE name=\"{$name[$i]}\""); $var1 = mysql_fetch_array($var); echo $var1['phone']; } ?>
на правах оффтопа котрый всё равно удалит Горбунов Олег. host, перепутал переменные в первом примере и просчитался с количеством проходов по массиву. Сам придумал? А то таких извратов имхо и в блондинках не пишут уже
// offtop Уставший за сегодня полностью. Да и вечер уже. Так что извиняйте. PS Исправлено. PPS Такие примеры я действительно видел, поэтому и написал
host, это наверно очень важно, но совершенно бесполезно! т.к. я не понял что именно делать не стоит: соединятся таким образом с базой? Выводить так массив? Кодить без отступов? использовать "*" когда нужен только id? Требуются пояснения, или, что еще лучше, пример как это делать НАДО! И конечно же хочется понять почему? т.е. чем это чревато. Заранее спасибо. ЗЫ я делаю именно так (только использую функцию для обработки запроса и foreach вместо for)
PHP: <?php //Скрипту передается через $_GET или $_POST параметр по которому нужно сделать выборку в базе. $result = mysql_query ("SELECT * FROM table_name WHERE id='{$_GET['id']}'"); //например $_GET['id'] == "' UNION /*...на что фантазии хватит...*/ '" //получется запрос: //SELECT * FROM table_name WHERE id='' UNION /*...на что фантазии хватит...*/ '' //'' - это два апострофа а не кавычка //как надо было: //если известно, что id - целое число $id = (int) $_GET['id']; //если известно что это набор букв и/или цифр $id = mysql_escape_string($_GET['id']); //ну и сам запрос $result = mysql_query ("SELECT * FROM table_name WHERE id='{$id}'"); /* * Если в вышем запросе используется LIKE, * например, SELECT * FROM table_name WHERE login LIKE '$login' * этот запрос выполнит поиск логина без учета регистра * помимо вышеописанных обработок нужно сделать дополнительную * LIKE воспринимает "_" как любой символ, а "%" как любые символы * соответственно надо их экранировать */ $login = str_replace (array ('%', '_'), array ('\%', '\_'), $login); ?>
Я бы предложил для подготовки запросов юзать sprintf() Т.е PHP: <?php // Подготовка запроса $sql = sprintf("SELECT * FROM `table_name` WHERE `id`=%d AND `name`='%s'", intval($_GET['id']), // вот тут в принципе intval не нужен, просто привычка mysql_escape_string($_GET['name']) ); // сам запрос $result = mysql_query ($sql); ?>
S.t.A.M., Битник В первом случае не стоит использовать mysql_num_rows в цикле, т.е. лучше PHP: <?php $rows = mysql_num_rows($var); for($i=0; $i<$rows; $i++) ?> а еще лучше PHP: <?php while($var1 = mysql_fetch_array($var)) { echo $var1['id']; } ?> Во втором: Лучше не использовать цикл for с запросом к БД. Лучше использование foreach и не стоит злоупотреблять запросами в циклах. В обоих вариантах: Использование логина root и без пароля.
host на самом деле все зависит от характеристик массива. если там идет последовательность нумерованных значений, и нумерация непрерывна, и число элементов массива от 100, то while, по моим наблюдениям, работает быстрее for, не говоря о foreach. имхо, удел foreach - это ассоциированные массивы.
Я новичок в PHP. Хотел бы больше услышать в ветке о безопасности, а не о скорости. Насколько я понял с безопасностью связано проверка переданных параметров. Параметры могут интерпретироватся как "команды" если мы используем их в SQL-запросе или если мы будем использовать значения этих параметров при выдаче браузеру. Можете толково разжувать в кратце все основные моменты? Ниже то что я для себя понял ) PHP: <?php // Проверка того что параметр передан и не пуст if (isset($_GET['param']) && !empty($_GET['param'])) { }; // Проверка с помощью регулярного выражения // Очень мощьное средство! if ( !preg_match("#[^a-z]#s", $_GET['param']) ) { } // Если известен тип, то делать явное приведение типов. (пример для int) $param = (int) $_GET['param']; // Преобразовывать "опасные" символы, перед использованием строки в sql-запросе // Смотреть также htmlentities и htmlspecialchars $param = mysql_escape_string($_GET['param']); // Потому как LIKE воспринимает "_" как любой символ, // а "%" как любые символы, при использовании LIKE в sql-запросе // например SELECT * FROM table_name WHERE login LIKE '$login' // следует: $param = str_replace (array ('%', '_'), array ('\%', '\_'), $param); // Использование следующей конструкции позволит // Отсеят "нежелательные" значения параметра $mode = $_GET['mode']; switch ($mode) { case '1': /* Что-то делаем */ ; break; // ... case 'n': /* Что-то делаем */ ; break; default: /* Что-то делаем */ ; break; } ?> Есть какое-то упоминание об intval($_GET['id']). Что это я не знаю ( Еще слышал об использовании substr($x,0,...); ? Это как? Типа брать не больше n символов? Дополните позжлста!
Лучше ни то ни другое, просто делать preg_match на наличие в строке чего либо кроме цифр, и в зависимости от этого выдавать ошибку или работать дальше (тормознутее, но за то не вмешиваясь в типы)