Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Базы Данных > Хранение заголовка и т.д. о странице, и настроек


Автор: Гриша 31.8.2006, 03:39
Здраствуйте.

Немогу определиться с хранением информации о страницах (заголовок, описание, ключевые слова), и некоторых опций страницы.
Например есть раздел сайта  (модуль) "Каталог" /catalog/, и информацию о разделе я буду хранить в БД:
- В заголовке страницы (title), должно быть название сайта (т.е. мне необходимо извлеч из БД название), -> затем заголовок каталога:
<meta name="title" content="localhost - Каталог" />
- В описание сайта должно храниться либо описание для "Каталога", если его нет, то общее описание сайта
- В ключевых словах сайта должны храниться либо ключевые слова для "Каталога", если их нет, то общие ключевые слова для сайта  
- Дальше например в БД нужно хранить общие настройки сайта, + настройки для каталога: количество выводимых товаров на страницах каталога, ну и например количество выводимых номеров страниц на странице каталога.

Если к примеру я сделаю БД следующим образом:
Код

PAGES #страницы 
page_id | page_url        
   1    | /index.php         
   2    | /catalog/index.php 

METAS #типы мета-данных 
meta_id | meta_name    | meta_name_info     
   1    | title        | Заголовок      
   2    | description  | Описание 
   3    | keywords     | Ключевые слова     

PAGE_META #значения мета-данных для страницы 
page_id | meta_id | page_meta_value 
   1    |    1    | localhost - интернет-магазин
   1    |    2    | localhost - интернет-магазин 
   1    |    3    | localhost, интернет-магазин 
   2    |    1    | Каталог  
   2    |    2    | Каталог товаров интернет-магазина 
   2    |    3    | Каталог, товары, интернет-магазин 


Вывожу эти данные на странице, при помощи запроса:
+ К этому запросу добавить еще извлечени данных из таблицы настроек (стркутура такая же как и для таблиц содержащих заголовок, описание, ключевые слова)
Код

$result = mysql_query(" 
    select 
        meta_name, 
        page_meta_value 
    from 
        pages, 
        metas, 
        page_meta 
    where 
        ...
        page_url = '/catalog/index.php' 
    ");
$fetch_assoc = mysql_fetch_assoc($result);


Название сайта храню в какой-то таблице общих настроек сайта (Это дополнительный запрос к БД).


А если вот например для каталога, нет описания и ключевых слов, то нужно сделать запрос к БД, и извлеч эти данные для предыдущей директории, в данном случае для корневой страницы (Получается еще запрос к БД).

В ИТОГЕ я запутался, и кажется мне что делаю я как-то некорректно, несколько пугает такое количество дополнительных запросов к БД (3), поэтому прошу вас,  подскозать мне решение данной задачи или написать совет или дополнение.




Автор: IZ@TOP 31.8.2006, 10:56
Я все понимаю, но зачем три таблицы???
Одна pages, другая meta. И вообще, мне кажется можно и в одной все хранить. Все зависит от задачи.
Хотя, если тебе нужно для страниц указывать кучу разных мета-тегов, тогда твой вариант с переменным набором данных подходит вполне. Но нужен ли такой излишек?

Автор: ZlojEzh 31.8.2006, 16:22
если в адресе каждого дочернего раздела содержится адрес родителя, то можно запрашивать информация таким вот образом:
Код

    select 
        meta_name, 
        page_meta_value,
        length page_url as page_url_length
    from 
        pages, 
        metas, 
        page_meta 
    where 
        ...
        locate(page_url,'/catalog/index.php')
    having legth(page_url)=max(page_url_length)


если чесно, то не уверен, что это заработает
если нет - проверку максимальности длины надо реализовать вложенным запросом:
выйдет все равно неслабо быстрее, чем двумя отдельными

вообщем идея сырая, но авось чем-то поможет ))

Автор: Гриша 31.8.2006, 17:13
IZ@TOP, спасибо за ответ. 
Вообще наверное я действительно все сделаю в одну таблицу, а уж если будет необходимость доп. параметров, то сделаю доп таблицу.
PAGES(page_id, page_url, page_title, page_description, page_keywords).

ZlojEzh, спасибо за ответ  и пример.

Вчера пришла идея, и до 6 утра сидел программировал, вот такой вариант получился, помоему совсем неплохой:
(с учетом того что в БД, url не будет содеражть 'index.php', для главной страницы url = '/')

Код

// Берем url, разбираем его на массив, и делаем реверсию этого массива
$url = '/catalog/firms/index.php';
$full_path = preg_replace('/index.php/', '', $url);
$full_path = explode('/', $full_path);
$full_path = array_reverse($full_path);

// Дальше делаем списог всех родительских url, включая текущий
$path = '';
$list_path = '/';
foreach($full_path as $row)
{
    if(!empty($row))
    {
        if(stristr($row, '.php'))
            $path .= (!$path) ? ', /'.$row : $row; 
        else
            $path .= (!$path) ? ', /'.$row.'/' : $row.'/';

        $list_path .= $path;
    }
}

// Дальше извлекаем данные из таблицы для всех url списка
/* $result = mysql_query(" 
    select 
        page_url as url, 
        page_title as title, 
        page_description as description,
        page_keywords as keywords
    from 
        pages
    where 
        page_url IN ($list_path) #  '/catalog/firms/, /catalog/, /'
    ");
*/

$path = array();
// Вывожу данные в массив, где ключом является url страницы
// Получается например такой массив
$path['/catalog/firms/']['description'] = 'Описание каталога фирм';
$path['/catalog/']['description'] = 'Описание каталога';
$path['/']['description'] = 'Описание';

// Дальше прохожу циклом по массиву, 
// В случае если, url имеет описание, завершаю цикл
foreach($path as $value)
{
    if($value['description'])
    {
        $description = $value['description'];
        break;
    }

}

echo $description;


Помоему очень хороший вариант. Если url не имеет олписание, то описание берется из предыдущего Url.
Даже не ожидал что сам придумаю такое. Что вы думаете об этом варианте?

Автор: -=Ustas=- 31.8.2006, 22:36
Гриша, у тебя  в подписи все сказано ;) А вообще я бы так не делал, твой подход - это излишки информации. Я бы генерил эти данные, т.е. всякие description и кейвордсы из основного контента страницы.

Автор: Гриша 1.9.2006, 04:12
;)
-=Ustas=-, спасибо за ответ. 
Вы имеете в  виду, что вы например бы на странице /catalog/index.php, сделали бы переменные содержащие заголовок, описание и ключевые слова, - в таком случае это может делать только программист, а мне как раз необходимо, чтобы это можно было настраивать через веб форму.
Либо вы имеете в виду, что вы бы просто не стали делать принцип наследования, т.е. либо мы ввели информацию о странице и она есть, либо мы ее не ввели и ее нет?
Но мне вот думается что твариант с наследованием данных от родителя, в данном случае удобен, я например это увидел у Битрикс (http://www.bitrixsoft.ru/sitemanager/demo.php).

Автор: -=Ustas=- 1.9.2006, 08:21
Гриша, я за насаследование ничего не говорил. Пожалуйста, наследуй сколько душе угодно, но просто избавься от излишек данных.
Цитата(Гриша @  1.9.2006,  04:12 Найти цитируемый пост)
случае это может делать только программист, а мне как раз необходимо, чтобы это можно было настраивать через веб форму.

Зачем же программист, прогораммист должен один раз написать этот код и все.
Цитата(Гриша @  1.9.2006,  04:12 Найти цитируемый пост)
т.е. либо мы ввели информацию о странице и она есть, либо мы ее не ввели и ее нет?

Ты малость не понял.

Смотри, пишем функцию, которой передаем ID страницы, это я так, к слову. Затем в этой функции выбираем описание, выбираем уникальные слова или выражения или предложения (смотря что генерить будем - описание или ключевые слова). И все, и возвращаем. По-поводу наследования, на котором ты помешан, то в этом подходе такого быть не может, потому что если не будет текста основного контента, тогда нет и самой страницы, правильно же...
Но и в этом случае можно добавить твое наследование, в этой же функции, при каких-либо неудовлетворенных условиях для генерации описанных выше элементов, берем id родителя этого элемента, и пукаем в функции рекрсию.
Все получается просто. Тебе надо будет только одну функцию эту юзать и всё! smile

Автор: Гриша 2.9.2006, 16:10
-=Ustas=-, спасибо за ответ.

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

И у страницы например /catalog/index.php - в данном случае нет ИД, это просто url И мне приходится извлекать данные по url.
А уже в каталоге есть разделы, в БД хранятся в виде дерева, /catalog/?catid=1, вот тогда я могу еще родителя подстовлять.

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

И почему вы пишите что я помешан на наследованиии мне не ясно, я же написал, что увидел такой подход и он мне понравился.

Автор: -=Ustas=- 2.9.2006, 23:14
Цитата(Гриша @  2.9.2006,  16:10 Найти цитируемый пост)
Я склоняюсь к варинату при котором ключевые слова и описание будут вводиться вручную.

Глупо, и нерационально!

Цитата(Гриша @  2.9.2006,  16:10 Найти цитируемый пост)
И у страницы например /catalog/index.php - в данном случае нет ИД, это просто url И мне приходится извлекать данные по url.

Переделывай структуру БД.



Цитата(Гриша @  2.9.2006,  16:10 Найти цитируемый пост)
И почему вы пишите что я помешан на наследованиии мне не ясно, я же написал, что увидел такой подход и он мне понравился. 

Понравился, значит помешался smile

Автор: Гриша 3.9.2006, 19:48
PAGES(page_id, page_url, page_title, page_description, page_keywords)
page_id | page_url  | page_title | page_description | page_keywords
   1    | /catalog/ | Каталог    | Описание         | Ключевые слова

Столбец page_id установлено как auto increment, PRIMARY KEY.
Я решил что при добавлении нового раздела сайта, я создаю sql запрос,
в соответвии с данными выше описанной таблицы БД, не заботясь о 'page_id' (делаю поле пустым), 
и при извлечение данных страницы, я использую ее url (в таком случае нет необходимости помнить page_id).

Что в данном случае вы предлагаете переделывать.

И чем вы можете обосновать, то что вводить описание и ключевые слова, при создании нового раздела сайта, это глупо и не рационально?   

Автор: ewolf 3.9.2006, 23:37
Если страницы зависят друг от друга, то лучше использовать структуру дерева, где у каждой записи будет parent_id, обозначающий id родительского элемента. Тогда очень легко ораганизовывать, например, навигацию по сайту. В любом случае, id - полезная вещь.

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

Лучше организовать поиск текущей страницы, а также ее родителей (по parent_id) в случае пустого описания. Тут можно просто делать несколько запросов, но если дерево большое, то может быть эффективнее хранить страницы в виде так называемых вложенных множеств
http://doc.woweb.ru/index.htm/id/1077327290

Автор: Гриша 4.9.2006, 01:08
ewolf, спасибо за ответ.

Предположим, что есть несколько разделов сайта:
каталог - /catalog/index.php
помощь - /help/index.php
админ - /admin/index.php

В таблице PAGES(page_id, page_url, page_title, page_description, page_keywords), хранятся данные о страницах (/catalog/, /help/, /admin/)

Раздел "каталог" состоит из множества подразделов, которые хранятся в БД в виде дерева (СПИСКИ СМЕЖНОСТИ: category_id, parent_id).
/catalog/?catid=1


Вот если бы все разделы сайта хранились бы в видее одного дерева, то например для обращения к каталогу, ссылки на различные разделы сайта имели бы вид:
каталог - /?catid=10
помощь - /?catid=11
админ - /?catid=12
В таком случае, я могу бы извлекать данные для страницы по ИД.

Но у меня например главная страница каталога представлена так /catalog/index.php
Поэтому я извлекаю данные страницы по url.
И какой может дать сбой структура таблицы PAGES,
где явно указано что page_url = '/catalog/', я не понимаю.

Автор: ewolf 4.9.2006, 18:20
Ты выбираешь записи по оператору IN он вернет все записи, которые соответствуют заданному в нем наборе параметров. Далее ты проходишь циклом по массиву и, найдя первый элемент с описанием, завершаешь цикл. Где гарантия, что первым будет имено элемент с page_url = '/catalog/' ?

Автор: Гриша 5.9.2006, 03:44
ewolf, спасибо за ответ.

Я считал, что извлечение данных из БД соответсвует порядку указанному в функции IN(), но после ваше сообщения засомневался в этом и решил переделать функцию, теперь массив извлеченных url, обрабатывается в  соответсвии со строгим порядком.


Код

// Функция загрузки даных страницы (заголовок, описание, ключевые слова)
function page_load_data($script_name)
{
    // Берем url, разбираем его на массив, и делаем реверсию этого массива
    $script_name = preg_replace('/index.php/', '', $script_name);
    $script_name = explode('/', $script_name);


    // Дальше делаем список и массив всех родительских url, включая текущий
    $path = '';
    $list_path = "'/'";
    foreach($script_name as $row)
    {
        if(!empty($row))
        {
            if(stristr($row, '.php'))
                $path .= (!$path) ? ",'/".$row : "'".$row."'"; 
            else
                $path .= (!$path) ? ",'/".$row."/'" : "'".$row."/'";

            $list_path .= $path;
        }
    }
    $list_path = preg_replace("/''/", '', $list_path);
    $array_path = explode(',', preg_replace("/'/", '', $list_path));
    $array_path = array_reverse($array_path);

    // Дальше извлекаем данные из таблицы для всех url списка
    $conn = db_connect();
    $result = mysql_query(" 
         select 
            page_url, 
            page_title, 
             page_description,
             page_keywords
         from 
                pages
         where 
             page_url IN($list_path)
        ");

    $pages_array = array();
    for($count=0; $row = mysql_fetch_assoc($result); $count++)
        $pages_array[$row['page_url']] = $row;


    // Дальше прохожу циклом по массиву $array_path,
    // используя его значения в качестве ключа,
    // для массива $pages_array, содержащего данные страницы
    // В случае если, url имеет описание, завершаю цикл
    $page_array = array();
    foreach($array_path as $row)
    {
        if(!empty($pages_array[$row]))
        {
            if(empty($page_array['title']))
                $page_array['title'] = $pages_array[$row]['page_title'];

            if(empty($page_array['description']))
                $page_array['description'] = $pages_array[$row]['page_description'];

            if(empty($page_array['keywords']))
                $page_array['keywords'] = $pages_array[$row]['page_keywords'];

            if(!empty($page_array['title']) && !empty($page_array['description']) && !empty($page_array['keywords']))
                break;
        }
    }

    return $page_array;
}


Добавлено @ 03:52 
Единственное что мне еще не нравится, это то, что у меня получается так:
Есть отдельные меню для разных разделов сайта, например:
1) Одно меню состоит из разделов.
Каталог - /catalog/ 
Помощь - /help/
2) Другие меню, состоят из подразделов (в виде дерева) для разделов /catalog/, /help/, ...
Либо это нормальный случай?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)