Черствый category php. Пример создания интернет-магазина в dreamweaver8. Вывод категорий кастомных записей

07.03.2024 Обзоры 

За работой которого я слежу. При описании создания магазина я не буду подробно описывать те операции, которые изложены в пункте "Пример создания интернет-аптеки в Dreamweaver" .В пункте меню "file" выберем подпункт "new". Сделаем страницу динамической, т.к будем использовать РНР. Сохраним под именем index.php в папке MAGAZIN. В свойствах страницы (page properties) выберем размер и цвет шрифта, фон. В пункте меню "site" выберем "newsite". Назовем сайт MAGAZIN. Как заполнить предложенную форму можно прочитать в пункте " Создание интернет-аптеки". Вместо Apteka1 вставить magazin

Создание базы данных и таблиц

Создадим базу данных magazin . А в базе таблицу categories с категориями товаров и таблицу tovari с описанием товара с помощью администратора баз данных. В таблице categories будут два поля- ID(счетчик,для него атрибут UNSIGNET , дополнительно- auto_increment (автоматически увеличивается на 1) и выберем флажок под рисунком ключа), и CATEGORY -тип поля VARCHAR и длина 20. Если очистить таблицу с помощью администратора, то поле id будет продолжать увеличиваьтся. Если вы хотите начать значение поля ID с нуля, то придется уничтожить таблицу.

Таблица с товарами будет иметь поля-id-счетчик(с теми же характеристиками, как и в таблице categories ), nom(INT )-для поиска записей,name - наименование товара (VARCHAR30), datapost -DATE поступления(DATE), Cena -цена(FLOAT(8,2), kolvo -количество товара(SMALLINT), razmer - Размер(VARCHAR30), cvet -цвет(VARCHAR60), sostav -состав ткани(VARCHAR50), opisanie - описание товара(TEXT), postav -поставщик(VARCHAR40), foto -путь к папке, где фото товара(VARCHAR20). При вводе цены обязательно должна стоять запятая, а не точка. Если при создании будет ошибка ERROR 1005: Can"t create table (errno: 121) и вы никак не сможете от нее избавиться, то попробуйте создать таблицу под другим именем.

Регистрация базы данных

Зарегистрируем базу данных в DR(dramweaver). Для этого в правой части DR в разделе application и закладке databases нажмем "+ ". Далее нажмем на MySQL Connection . Заполним форму. Connection name -magazin, MySQLserve r-localhost , Username -root ,password -пароль при установке MySQL, database -magazin. В папке Files/Site/connection появится файл, описывающий соединение с базой данных-magazin.php.

Создание скриптов для занесения информации в таблицы

Создадим папку Admin и в ней скрипт categ_add.php для занесения информации о категориях товаров.На вкладкеВ нем поместим форму для ввода информации(insert/form/form).Поместим курсор в форму и в нее будем заносить информацию о полях. Поле ID не будем заносить, т.к. значение его будет автоматически увеличиваться на 1-цу при создании новой записи (это мы указали при создании таблицы). Вставим курсор в форму, выберем insert/form/TextField для создания окна для поля . Введем в окно для Label слово "Категория" , "OK" . В окно TextField(в нижней части экрана)введем название этого поля- category. В Charwith длину поля для заполнения-20 и максимальную длину для поля-30. Для занесения информации в таблицу нужна кнопка- insert/Form/Button . Для появления на кнопке слова "Добавить" введем его в окне Value . Чтобы кнопка сработала на вставку записи с информацией о товаре, на вкладке ServerBehaviors нажмем на "+" и выберем оператор insert Record (вставка записи). Заполним предложенную оператором форму(рис.1). В ней в окне connection ввести имя нашего соединения-magizin. Особое внимание обратите на поле ID . При создании таблицы обязательно нажать на знак ключа напротив этого поля и сделать его автоматическим и по возрастанию(auto_increment,unsignet )-иначе появится ошибка о дубле значений. В нижнем окошке указывается путь к файлу, к которому после ввода данных перейти программа(если в тот же скрипт, то ввести categ_add.php .После нажатия на "ОК" под кнопкой появится особый знак. Если будут сбои при вызове скрипта добавления записи, то лучше замените вызов файла magazin.php:


на: И файл magazin.php из папки Connections скопируйте в папку, где находится скрипт categ_add.php , т.е. папку admin .

Создадим скрипт для занесения информации о товарах tovar_add.php . В application/Database Создадим соединение magazin. А в Server Behaviorsдва набора данных- category и tovari. На рис.2 создание набора tovari с таблицей tovari.

Рис. 3. Создание записи Category для занесения кода и названия ктегории

Введем форму, поле для ввода наименования товара(Textfield -name). Категории будем выбирать из таблицы categories (рис. 5) . Для этого вставим поле list/menu (insert/form/list/menu) . Type-menu. Нажмем на dinamic со знаком молнии и заполним форму (рис.4)

Рис.4 Форма для для определения для поля выбора категорий.

В select value eqal to Можно не вводить информацию, главное определить value. В таблицу бдет заноситься информация о названии категории. А нам надо также ввести код категории в поле KOD таблицы tovari. для этого выведем рядом с наименованием и код категории. Для этого подкорректируем сами оператор select d коде скрипта:

Значение кода будет вводится отдельно в окне рядом(рис.5). Далее вставим поле textfield для даты поступления товара. Назовем его datapost. Нажмем на окно ввода и в нижней части экрана в окно init val введем вывод даты на РНР- . Далее введем текстовые поля цены, количества, размера и цвета. Остановимся подробнее на поле opisanie . Для него введем тип поля формы- Textarea для ввода большого текста. В окне Num Lines можно задать количество строк.Введем тексовые поля для поставщика и фото.После описания всех полей вставим кнопку (insert/form/Button). В окне Value введем добавить .

Рис.5. Форма занесения информации о товаре.

Рис.6. Описание полей таблицы tovari в Insert Record.

include("magazin.php");
function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "")
{
$theValue = (!get_magic_quotes_gpc()) ? addslashes($theValue) : $theValue;

switch ($theType) {
case "text":

break;
case "long":
case "int":
$theValue = ($theValue != "") ? intval($theValue) : "NULL";
break;
case "double":
$theValue = ($theValue != "") ? """ . doubleval($theValue) . """ : "NULL";
break;
case "date":
$theValue = ($theValue != "") ? """ . $theValue . """ : "NULL";
break;
case "defined":
$theValue = ($theValue != "") ? $theDefinedValue: $theNotDefinedValue;
break;
}
return $theValue;
}

$editFormAction = $_SERVER["PHP_SELF"];

$editFormAction .= "?" . htmlentities($_SERVER["QUERY_STRING"]);
}

if ((isset($_POST["MM_insert"])) && ($_POST["MM_insert"] == "form1")) {
$insertSQL = sprintf("INSERT INTO tovari (kod, category, name, datapost, cena, kolvo, razmer, cvet, sostav, opisanie, postav, foto) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)",
GetSQLValueString($_POST["kod"], "int"),
GetSQLValueString($_POST["select"], "text"),
GetSQLValueString($_POST["name"], "text"),
GetSQLValueString($_POST["datapost"], "date"),
GetSQLValueString($_POST["cena"], "double"),
GetSQLValueString($_POST["kolvo"], "int"),
GetSQLValueString($_POST["razmer"], "text"),
GetSQLValueString($_POST["cvet"], "text"),
GetSQLValueString($_POST["sostav"], "text"),
GetSQLValueString($_POST["opisanie"], "text"),
GetSQLValueString($_POST["postav"], "text"),
GetSQLValueString($_POST["foto"], "text"));


$Result1 = mysql_query($insertSQL, $magazin) or die(mysql_error());

$insertGoTo = "tovar_add.php";
if (isset($_SERVER["QUERY_STRING"])) {
$insertGoTo .= (strpos($insertGoTo, "?")) ? "&" : "?";
$insertGoTo .= $_SERVER["QUERY_STRING"];
}
header(sprintf("Location: %s", $insertGoTo));
}

mysql_select_db($database_magazin, $magazin);
$query_category = "SELECT * FROM categories";

$row_category = mysql_fetch_assoc($category);

mysql_select_db($database_magazin, $magazin);
$query_tovari = "SELECT * FROM tovari";



?>




ввод данных о товаре









Цена

Количество


Размер


Цвет


Состав




Поставщик








if ($Submit=="Добавить")
{ ?>



mysql_free_result($tovari);
?>

Для проведения операций добавления, удаления и корректировки создадим скрипт по аналогии для препаратов сайта "АПТЕКА" (см. меню страницы):

Описание вывода информации о товарах

Вставим таблицу(insert/table) из одной строки и одного столбца для названия магазина и под ней вставим таблицу из одной строки и 2-х столбцов. В первом столбце будет меню, во втором операции с таблицами.Вставим курсор в 1-ый столбец и выберем для вертикали режим тор . Вставим таблицу из одной строки и одного столбца для заголовка- "Категории". Закрасим зеленым цветом (bgcolor) и шрифт - белый.Поместим список категорий товаров из таблицы categories для выбора из таблицы tovari для посетителя магазина. Для этого вставим под заголовком таблицу из одного столбца и одной строки. Вставим курсор в созданную таблицу, создадим на вкладке bindings набор записей под именем category, с таблицей category и отсортируем по алфавиту (рис.3). Мы должны вывести названия категорий в цикле. Для этого выделим последнюю таблицу и на вкладке Server Behaviors ,нажав на +, выберем Repeat Regoin и заполним форму:

Заполнение формы означает, что для набора записей создаем цикл. Ниже привожу фрагмент кода создания цикла:





gМы сделали вывод списка категорий одежды. Нам далее необходимо, чтобы при выборе категории произошел выбор из таблицы с товарами по коду категории (параметр kod ). Этот параметр будет описан при создании набора записей для вывода информации о товаре (см. рис.9.).Мы самостоятельно сделаем ссылку. Ниже привожу тот же фрагмент, но уже подкорректированный:


//
начало цикла

// вывод списка категорий

//
окончание цикла

?> // передача значения параметра id как кода категории kod

" class="style10">

Для вывода информации о товарах вставим таблицу из одной строки и двух столбцов. В первом столбце выводится фото изделия, а в правом столбце характеристики: размеры, цвет, описание. Эта информация будет выбираться из таблицы tavari при выборе категории товара.

На вкладке Bindings создадим набор записей tovari:

Рис.9 Быбор из таблицы tovari по категории

Выделим последнюю таблицу и выберем на вкладке Server Behaviors Repeat region для того, чтобы таблица выводилась в цикле (по количеству товаров одной категории). Зайдем в код скрипта и внутри цикла сделаем операции:

занесение в переменную $image
$r=$row_tovari["razmer"];$cv=$row_tovari["cvet"];//
выбор размера и цвета из полей таблицы

$rm=explode(";",$r); $ke=sizeof($rm); //
создание массива размеров по точке с запятой и $ke- колво элементов (размеров)

$name=$row_tovari["name"];

Выведем фото изделия:

<img src="" alt= width="67" height="150">

Выведем наименование и цену товара:

цена- ";
print ($row_tovari["cena"]);print " руб"; ?>

Сделаем вывод списка размеров и цветов с помощью оператора select .В режиме Design после обозначения PHP вставим курсор и добавим форму, а в ней -List/menu .

Зайдем в код скрипта и подкорректируем оператор select, который создал DR:

Рядом вставим еще оператор list/menu для цвета и подкорректируем его:

Далее сделаем ссылку на скрипт prosm.php (его сделаем позже), в котором можно будет посмотреть товар поближе). Для этого в форме напишем- "посмотреть" и в окне link набьем prosm.php. Выбранную информацию о товаре необходимо внести с помощью кнопки с названием "в корзину" . Также нам нужно передать и уникальный номер записи данного товара (idtov ). Для этого введем в форме элемент Hidden field - невидимый для передаваемого номера записи. С помощью Dinamic Dat a (его получим, нажав на молнию) определим для невидимого элемента поле idtov:

Выбранные товары необходимо поместить в корзину. Создадим таблицу с полями- kodtov(smallint),name (varchar(50), razmer (varchar(3)) , cvet(varchar(20)), postav(varchar(60), cena (float(9,2) , kolzak(smallint(3) . А в таблице под списком категорий разместим таблицу с выбранными товарами. Напишем- "Ваша корзина:" .Под этим выражением разместим таблицу из двух срок и двух столбцов- для наименования и цены. Введем заголовки таблицы. На вкладке Bindings нажмем на + для создания набора данных и назовем его korzina и отсортируем по наименованию. Нажмем на + напротив этого набора и курсором перенесем соответствующие поля в таблицу. Выделим строку с полями и сделаем цикл с помощью .При этом обратите внимание на тэг , чтобы записи находились одна под другой.Но нам нужно, чтобы содержание корзины появлялось при ее заполнении. Выделим заголовок и таблицу, на вкладке Server Behaviors нажмем на + и в разделе выберем show if recordset is not empty и в нем выберем таблицу korzina (рис. 12).

Рис.13.Результат нашей проделанной работы.

После нажатия на кнопку "в корзину" в таблицу korzina должна занестись информация о выбранном товаре. Для этого мы соpдадим скрипт korzina.php. На вкладке Bindings создадим набор записей tovari для таблицы tovari с фильтрацией по коду товара idtov (рис. 14):

В этой форме на рис.14 мы указываем, что этот параметр передается методом POST , через форму (FORM Variable). мы его передаем как невидимый параметр (см. рис. 11). В скрипте korzina.php создадим набор записей korzina. Ниже привожу код скрипта korzina.php, т.к. вставку выбранных параметров товара в таблицу korzina сделаем самостоятельно:

include("magazin.php");
$colname_tovari = "-1";
if (isset($_POST["idtov"])) {
$colname_tovari = (get_magic_quotes_gpc()) ? $_POST["idtov"] : addslashes($_POST["idtov"]);
}

$query_tovari = sprintf("SELECT * FROM tovari WHERE idtov = %s", $colname_tovari);//выбор записи по коду
$tovari = mysql_query($query_tovari, $magazin) or die(mysql_error());
$row_tovari = mysql_fetch_assoc($tovari);
$totalRows_tovari = mysql_num_rows($tovari);

$name=$row_tovari["name"]; $postav=$row_tovari["postav"]; //запоминание из таблицы параметров товара
$cena = $row_tovari["cena"];
mysql_select_db($database_magazin, $magazin);



$sql = "INSERT INTO korzina (idtov,name,razmer,cvet,postav,cena,kolzak) //оператор вставки
VALUES ("$idtov","$name","$razmer","$cvet","$postav","$cena","1")";


// Проверка исполнения операции
if(!$result) {
echo "Запись не создана!"; }
mysql_free_result($tovari);

?>

После того, как покупатель поместил выбранные товары в корзину, необходимо посчитать общую сумму с возможностью коррекировки. Напишем под содержанием корзины выражение "оформить заказ" и сделаем ссылку на скрипт raskorz.php. Создадим этот скрипт и в нем в цетре напишем "Ваша корзина". Создадим форму и вставим в нее таблицу из 4 столбцов и двух строк. В первой строке запишем-код, наименование, поставщик,размер, цвет,цена,количество.Создадим набор записей (record set) korzina и перенесем соответствующие поля (Рис.15). Сделаем вторую строку в цикле (repeat region). Там, где указывется количество мы сделаем самостоятельно, т.к. необходимо дать покупателю возможность указать количество товара. Для этого создадим массив $kolm , в него занесем количество товара и сделаем корректировку массива в последнем столбце- ";?> . Подсчитаем сумму товара, для этого используем переменную $s . Напишем "Общая сумма" под таблицей, а в коде поставим рядом оператор- . При изменении количества необходимо пересчитать сумму. для этого мы в форму вставим кнопку (form/Button) с надписью "пересчитать" слева от "Общей суммы". Имя кнопки-Subper . Справа поместим кнопку subobnul для обнуления содержания корзины. Эти операции мы проведем в новом скрипте pereskor.php. К нему мы обратимся из формы. В pereskor.php создадим набор записей korzina . Ниже я привожу фрагмент кода скрипта pereskor.php:

$i=0
if (isset ($Subper)) { // если нажата кнопка пересчета, важен регистр
do {
$i=$i+1;$kol=$kolm[$i]; $idtovz=$row_korzina["idtov"];print"i= $i кол-во= $kol idtov= $idtovz ";
$sql = "UPDATE korzina set kolzak="$kol" where idtov=$idtovz"; //изменение количества
/* Исполнение SQL запроса */
$result = mysql_query($sql);
} while ($row_korzina = mysql_fetch_assoc($korzina)); //конец цикла
} // конец по пересчету
if (isset ($Subobnul)) { // если нажата кнопка обнуления, важен регистр
$sql = " DELETE FROM korzina"; //удаление записей
$result1 = mysql_query($sql);}/* Исполнение SQL запроса */
?>

Для отправки заказа необходимы данные о покупателе. Для этого создадим новую форму(Рис.15).

Ниже привожу текст скрипта raskorz.php:

include("magazin.php");
mysql_select_db($database_magazin, $magazin);

$korzina = mysql_query($query_korzina, $magazin) or die(mysql_error());
$row_korzina = mysql_fetch_assoc($korzina);
$totalRows_korzina = mysql_num_rows($korzina);
?>



Расчет корзины для магазина


Ваша корзина:
























Код товара Наименование Поставщик Размер Цвет Цена Количество
";?>


Общая сумма-


Заполните, пожалуйста, форму:








Ф.И.О.

Адрес


Телефон


email


Комментарий







mysql_free_result($korzina);
?>

После заполнения формы и нажатии на кнопку "Отправить" мы должны сформировать сообщение. Для этого создадим скрипт otpzak.php. В нем создадим набор записей korzina с таблицей korzina . Ниже привожу текст скрипта:

include("magazin.php");
mysql_select_db($database_magazin, $magazin);
$query_korzina = "SELECT * FROM korzina";
$korzina = mysql_query($query_korzina, $magazin) or die(mysql_error());
$row_korzina = mysql_fetch_assoc($korzina);
$totalRows_korzina = mysql_num_rows($korzina);
?>



отправка заказа из магазина


$i=0;$s="";
do { // начало цикла по корзине
$i=$i+1;
$stkod=(string)$row_korzina["idtov"];
$stkol=(string)$row_korzina["kolzak"]; //перевод в строку с помощью приставки string
$stcena=(string)$row_korzina["cena"]; //
$sum=(string)$row_korzina["cena"]*$row_korzina["kolzak"]; //сумма товара
$z[$i]="код-".$stkod." наименование- ".$row_korzina["name"]." производитель- ".$row_korzina["postav"]." в количестве- ".$stkol." цена-".$stcena." сумма- ". $sum;
$s=$s.$z[$i]."\n"; //сложение информации о товаре в одну переменную s
$obsum=$obsum+$sum;
}
while ($row_korzina = mysql_fetch_assoc($korzina)); //конец цикла по корзине
$obsum="Общая сумма-".(string)$obsum;
$message=" От ".$fio." прожив. по адресу-".$adres." email-".$email." "." Телефон-".$tel." получен заказ: \n".$s.$obsum." рублей";// n должно быть в двойных кавычках
include("smtpmail.php"); //подключение почты, см. "отправка сообщений на РНР" на странице в содержании
smtpmail("", "", $message, $headers=""); // вызов функции

include "index.php";?>

include("magazin.php");
mysql_select_db($database_magazin, $magazin);
$query_category = "SELECT * FROM categories ORDER BY category ASC";
$category = mysql_query($query_category, $magazin) or die(mysql_error());
$row_category = mysql_fetch_assoc($category);
$totalRows_category = mysql_num_rows($category);

$colname_tovari = "-1";
if (isset($_GET["kod"])) {
$colname_tovari = (get_magic_quotes_gpc()) ? $_GET["kod"] : addslashes($_GET["kod"]);
}
mysql_select_db($database_magazin, $magazin);
$query_tovari = sprintf("SELECT * FROM tovari WHERE kod = %s", $colname_tovari);
$tovari = mysql_query($query_tovari, $magazin) or die(mysql_error());
$row_tovari = mysql_fetch_assoc($tovari);
$totalRows_tovari = mysql_num_rows($tovari);

mysql_select_db($database_magazin, $magazin);
$query_korzina = "SELECT * FROM korzina ORDER BY name ASC";
$korzina = mysql_query($query_korzina, $magazin) or die(mysql_error());
$row_korzina = mysql_fetch_assoc($korzina);
$totalRows_korzina = mysql_num_rows($korzina);
?>
?>




интернет-магазин






ИНТЕРНЕТ-МАГАЗИН для шикарных женщин









Категории







" class="style10">


0) { // Show if recordset not empty ?>

Ваша корзина:














Наименование Цена

Оформить заказ










$r=$row_tovari["razmer"];$cv=$row_tovari["cvet"];//выбор размера и цвета
$sos=$row_tovari["sostav"];//состав ткани
$rm=explode(";",$r); $ke=sizeof($rm); //колво элементов (размеров)
$cvm=explode(";",$cv); $kecv=sizeof($cvm); //колво элементов (цветов)
$sosm=explode(";",$sos); $kesos=sizeof($sosm); //колво элементов состава ткани
$name=$row_tovari["name"];
?>
" alt= width="67" height="150">

цена- ";
print ($row_tovari["cena"]);print " руб"; ?>



посмотреть


">





mysql_free_result($category);

mysql_free_result($tovari);

mysql_free_result($korzina);
?>

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

Иногда простое кажется сложным, именно по этому выложу несколько фрагментов кода, которые я надеюсь вам пригодятся для реализации php категорий в виде дерева.

Итак, структура должна состоять из id категории (id), из названия категории (name) и конечно id родительской категории (parent_id). В MySQL это выглядит так:

CREATE TABLE IF NOT EXISTS `category` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `parent_id` int(11) NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=0 ;

Минимальная и понятная структура таблицы для хранения категорий.

INSERT INTO `category` (`id`, `name`, `parent_id`) VALUES (1, "Телефоны и планшеты", "0"), (2, "Автомобили", "0"), (3, "Samsung", "1"), (4, "Apple", "1"), (5, "LG", "1"), (6, "Ford", "2"), (7, "Lexus", "2"), (8, "BMW", "2"), (9, "Galaxy Tab 4", "3"), (10, "Galaxy S6", "3");

Там где значение parent_id=0, у данной категории нет родительской категории.

Тут все понятно и просто. Теперь присутпим к выводу списка категорий. Но для правильного вывода списка, нам нужно сначала получить весь список php категорий, а уже потом с помощью рекурсии сформировать наше дерево. Следующая функция предназначена для получения этого списка:

Function get_cat() { //запрос к базе данных $sql = "SELECT * FROM category"; $result = mysql_query($sql); if(!$result) { return NULL; } $arr_cat = array(); if(mysql_num_rows($result) != 0) { //В цикле формируем массив for($i = 0; $i < mysql_num_rows($result);$i++) { $row = mysql_fetch_array($result,MYSQL_ASSOC); //Формируем массив, где ключами являются адишники на родительские категории if(empty($arr_cat[$row["parent_id"]])) { $arr_cat[$row["parent_id"]] = array(); } $arr_cat[$row["parent_id"]] = $row; } //возвращаем массив return $arr_cat; } }

//получаем массив каталога $result = get_cat();

Теперь нужна функция с рекурсией

Function view_cat($arr,$parent_id = 0) { //Условия выхода из рекурсии if(empty($arr[$parent_id])) { return; } echo "

    "; //перебираем в цикле массив и выводим на экран for($i = 0; $i < count($arr[$parent_id]);$i++) { echo "
  • " .$arr[$parent_id][$i]["name"].""; //рекурсия - проверяем нет ли дочерних категорий view_cat($arr,$arr[$parent_id][$i]["id"]); echo "
  • "; } echo "
"; }

Теперь осталось только вывести каталог на экран с помощью рекурсивной функции

View_cat($result);

И в общем то и всё. Таким образом мы можем получить полное дерево категорий с бесконечными подкатегориями.

Category subcategory tree view provides a user-friendly way to list the parent and child categories. The category and their subcategory are easily separated by a tree structure. The categories tree view is always recommended to display an infinite level of categories and subcategories.

In this tutorial, we will show you how to create dynamic category subcategory tree using PHP and MySQL. The recursive category tree is very useful to list n level categories in a dropdown. The example code helps you to build n level category subcategory dropdown in PHP. The dynamic categories data will be retrieved from the MySQL database and listed in a parent-child category tree format.

Create Database Table

To store categories and subcategories, a table needs to be created in the database. The following SQL creates a categories table in the MySQL database.

CREATE TABLE `categories ` (`id` int (11 ) NOT NULL AUTO_INCREMENT, `parent_id` int (11 ) NOT NULL DEFAULT "0" , `name` varchar (100 ) COLLATE utf8_unicode_ci NOT NULL , `created` datetime NOT NULL , `modified` datetime NOT NULL , `status` enum("1" ,"0" ) COLLATE utf8_unicode_ci NOT NULL DEFAULT "1" COMMENT "1:Active, 0:Inactive" , PRIMARY KEY (`id` )) ENGINE= InnoDB DEFAULT CHARSET= utf8 COLLATE= utf8_unicode_ci;

The parent_id column specifies whether the category is parent or child. If parent_id is 0, it will be a parent category. Otherwise, it will be a child category and the ID is the parent of this category.

Database Configuration (dbConfig.php)

The dbConfig.php file is used to connect and select the database. Specify the database host ($dbHost), username ($dbUsername), password ($dbPassword), and name ($dbName) as per your MySQL credentials.

// Database configuration
$dbHost = "localhost" ;
$dbUsername = "root" ;
$dbPassword = "root" ;
$dbName = "codexworld" ;// Create database connection
$db = new mysqli ($dbHost , $dbUsername , $dbPassword , $dbName );// Check connection
if ($db -> connect_error ) {
die("Connection failed: " . $db -> connect_error );
}
?>

PHP Recursive Function to Generate Parent/Child Tree

The categoryTree() function generates an n level category subcategory tree using PHP. It will create the dropdown options for categories tree.

  • $parent_id – Optional. Specify the parent ID to get the child categories of this parent category.
  • $sub_mark – Optional. Mark that will append at the beginning of the child category name.
// Include the database configuration file
require "dbConfig.php" ;categoryTree ($parent_id = 0 , $sub_mark = "" ){
global $db ;
$query = $db -> query ("SELECT * FROM categories WHERE parent_id = $parent_id ORDER BY name ASC" );$query -> num_rows > 0 ){
while($row = $query -> fetch_assoc ()){
echo "" ;
categoryTree ($row [ "id" ], $sub_mark . "---" );
}
}
}

Category Subcategory Dropdown in PHP

Use categoryTree() function to build dynamic categories tree dropdown in PHP with MySQL.

Are you want to get implementation help, or modify or extend the functionality of this script?

Решил написать эту заметку, потому как надоело отвечать 100500 раз одно и то же на ВиО.

Многие начинающие веб-программисты рано или поздно сталкиваются с задачей внедрения в свой сайт человеко-понятных линков (ЧПУ). До внедрения ЧПУ все ссылки имеют вид /myscript.php или даже /myfolder/myfolder2/myscript3.php, что тяжело для запоминания и ещё хуже для SEO. После внедрения ЧПУ линки принимают вид /statiya-o-php или даже на кириллице /статья-о-пхп.

Кстати о SEO. Человекопонятные линки на САМОМ деле придумали не для удобного запоминания, а в основном для повышения индексируемости сайта, потому что совпадение поискового запроса и части URL даёт хорошее преимущество в рейтинге поиска.

Эволюция начинающего PHP-программиста может быть выражена следующей последовательностью шагов:

  1. Размещение plain-PHP кода в отдельных файлах и доступ к этим файлам через линки вида /myfolder/myscript.php
  2. Понимание, что все скрипты имеют значительную часть общего (например, создание подключения к БД, чтение конфигурации, запуск сессии и проч.) и как следствие создание общей начальной точки «входа», некоторого скрипта, который принимает ВСЕ запросы, а потом выбирает — какой внутренний скрипт подключить. Обычно этот скрипт имеет имя index.php и лежит в корне, вследствие чего все запросы (они же URLы) выглядят так: /index.php?com=myaction&com2=mysubaction
  3. Необходимость внедрения роутера и переход к человекопонятным линкам.

Замечу, что между пунктами 2 и 3 большинство программистов делают очевидную ошибку. Я не ошибусь, если назову это значением около 95% программистов. Даже большинство известных фреймворков содержат эту ошибку. И заключается она в следующем.

Вместо того, чтобы реализовывать принципиально новый способ обработки линков, ошибочно делается концепция «заплаток и редиректов» на базе.htaccess, которая заключается в том, чтобы с помощью mod_rewrite создавать множество правил редиректа. Эти строки сравнивают URL с каким-либо регулярным выражением и при совпадении расталкивают выуженные из URL значения по GET-переменным, в дальнейшем вызывая всё тот же index.php.

#Неправильный метод ЧПУ RewriteEngine On RewriteRule ^\/users\/(.+)$ index.php?module=users&id=$1 #....Ещё куча подобных правил...

У данной концепции множество недостатков. Один из них — трудность создания правил, большой процент человеческих ошибок при добавлении правил, которые сложно выявить, но они приводят к ошибке сервера 500.

Другой недостаток в том, что часто правится по сути конфига сервера, что само по себе нонсенс. И если в Apache конфиг можно «пропатчить» с помощью.htaccess, то в популярном nginx такой возможности нет, там всё находится в общем файле конфигурации в системной зоне.

И ещё один недостаток, вероятно, наиболее важный, что при таком подходе невозможно динамически конфигурировать роутер, то есть «на лету», алгоритмически менять и расширять правила выбора нужного скрипта.

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

Суть заключается в том, что начальный запрос всегда хранится в переменной $_SERVER[‘REQUEST_URI’], то есть его можно считать внутри index.php и разобрать как строку средствами PHP со всеми обработками ошибок, динамическими редиректами и проч и проч.

При этом в файле конфигурации можно создать только одно статичное правило, которое будет все запросы к несуществующим файлам или папкам редиректить на index.php.

RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f #Если файл не существует RewriteCond %{REQUEST_FILENAME} !-d #И если папка не существует RewriteRule ^.*$ index.php

Причём это правило можно разместить как в.htaccess, так и в основном файле конфигурации Apache.

Для nginx соответствующее правило будет выглядеть вот так:

Location / { if (!-e $request_filename) { rewrite ^/(.*)$ /index.php last; } }

Всё просто.

Теперь рассмотрим кусок кода PHP в index.php, который анализирует ссылки и принимает решение — какой скрипт запускать.

/часть1/часть2/часть3

Первое, что приходит в голову — разбить её с помощью explode(‘/’, $uri) и сделать сложный роутер на основе switch/case, анализирующий каждый кусок запроса. Не делайте этого! Это сложно и в итоге приводит код в ужасный непонимабельный и неконфигурабельный вид!

Я предлагаю более лаконичный способ. Лучше не описывать словами, а сразу показать код.

"page404.php", // Страница 404 "/" => "mainpage.php", // Главная страница "/news" => "newspage.php", // Новости - страница без параметров "/stories(/+)?" => "storypage.php", // С числовым параметром // Больше правил); // Код роутера class uSitemap { public $title = ""; public $params = null; public $classname = ""; public $data = null; public $request_uri = ""; public $url_info = array(); public $found = false; function __construct() { $this->mapClassName(); } function mapClassName() { $this->classname = ""; $this->title = ""; $this->params = null; $map = &$GLOBALS["sitemap"]; $this->request_uri = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH); $this->url_info = parse_url($this->request_uri); $uri = urldecode($this->url_info["path"]); $data = false; foreach ($map as $term => $dd) { $match = array(); $i = preg_match("@^".$term."$@Uu", $uri, $match); if ($i > 0) { // Get class name and main title part $m = explode(",", $dd); $data = array("classname" => isset($m)?strtolower(trim($m)):"", "title" => isset($m)?trim($m):"", "params" => $match,); break; } } if ($data === false) { // 404 if (isset($map["_404"])) { // Default 404 page $dd = $map["_404"]; $m = explode(",", $dd); $this->classname = strtolower(trim($m)); $this->title = trim($m); $this->params = array(); } $this->found = false; } else { // Found! $this->classname = $data["classname"]; $this->title = $data["title"]; $this->params = $data["params"]; $this->found = true; } return $this->classname; } } $sm = new uSitemap(); $routed_file = $sm->classname; // Получаем имя файла для подключения через require() require("app/".$routed_file); // Подключаем файл // P.S. Внутри подключённого файла Вы можете использовать параметры запроса, // которые хранятся в свойстве $sm->params

Несмотря на то, что код довольно длинный, он прост логически. Мне не хочется его объяснять, я считаю любой код на PHP самообъясняющим, если он правильно написан. Учитесь читать код.

Хорошо, в моей голове это несколько сложно, и я надеюсь, что смогу это объяснить. Если что-то неясно, прокомментируйте, поэтому я могу уточнить вопрос.

Я хочу обрабатывать загрузки файлов пользователей на 3-й сервер.

Итак, мы имеем

  • Пользователь
  • веб-сайт (сервер, на котором работает веб-сайт)
  • сервер хранения (который получает файл)

Поток должен быть следующим:

    Сайт запрашивает URL загрузки из шлюза облака хранения, который указывает непосредственно к конечному серверу хранения (что-то вроде http://serverXY.mystorage.com/upload.phpа >). Наряду с запросом отправляется "целевой путь" (уникальный веб-сайт и глобально уникальный) и URL-адрес перенаправления.

    Веб-сайт создает форму загрузки с сервером загрузки серверов хранения в качестве целевого объекта, пользователь выбирает файл и нажимает кнопку отправки. Сервер хранилища обрабатывает почтовый запрос, сохраняет файл во временное местоположение (т.е. "/tmp-directory/".sha1(target-path-fromabove)) и перенаправляет обратно на URL-адрес перенаправления, указанный веб-сайтом. Также передается "целевой путь".

    Я не хочу, чтобы какие-либо "призрачные файлы" оставались, если пользователь отменяет процесс или соединение прерывается или что-то в этом роде! Также следует избегать записей в базе данных веб-сайтов, которые не были правильно обработаны в облаке хранения, а затем сломаны. вот почему и следующий шаг

    это критические шаги

    • Теперь веб-сайт записывает запись в свою собственную базу данных и выдает спокойный запрос на хранение api (подпись, веб-сайт должен аутентифицироваться с помощью секретного токена), который
    • копирует файл из своего временного местоположения на сервере хранения в его конечное местоположение (это должно быть быстрым, потому что его только переименование)
    • тот же запрос на отдых также вставляет строку базы данных в базу данных сетей хранения вместе с идентификатором веб-сайта как владельца
  • Все файлы в каталоге tmp на сервере хранения, которые старше 24 часов, автоматически удаляются.

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

Могу ли я каким-либо образом сделать эту часть кода "критичной", чтобы сервер, если он когда-то попадал в эту часть кода, выполняет его до конца, независимо от того, отменяет ли пользователь загрузку страницы или нет?

(Конечно, я знаю, что авария сервера или ошибка могут прерываться в любой момент, но мои проблемы касаются регулярного потока)

Один из меня должен был иметь флаг и временную метку в базе данных сайтов, которые помечают файл как "завершены" и проверить в cronjob для старых незавершенных файлов и удалить их из облака хранения, а затем из базы данных сайтов, но Я действительно хотел бы избежать этого дополнительного поля и процедуры.

Я хочу, чтобы хранилище api было очень общим и использовало его во многих других будущих проектах.

Я посмотрел на хранилище Google для разработчиков и Amazon s3.

У них такая же проблема и еще хуже. В amazon S3 вы можете "подписать" свой почтовый запрос. Таким образом, файл загружается пользователем под вашими полномочиями и непосредственно сохраняется и сохраняется, и вы должны его оплатить. Если соединение прерывается, и пользователь никогда не возвращается на ваш сайт, вы даже не знаете. Таким образом, вы должны хранить все загружаемые URL-адреса, которые вы подписываете, и проверять их в cronjob и удалять все, что "не достигло цели".