|
|
|
| Я хочу сохранять в базе информацию о посещении каждым из пользователей каждой из страниц. Но страниц в перспективе намечается сделать довольно много (200). Получается большой объём. Как минимизировать? У меня идея такая:
У каждой страницы есть порядковый номер, а в таблице зарегистрированных пользователей есть бинарная колонка, где для каждого есть ряд из 200 нуликов и единичек: 0001001000010001, где нулик обозначает непосещённые страницы, а единица - посещённые.
При посещении страницы это бинарное число соответствующим образом маскируется преобразуется в интеджер и заново сохраняется в ячейку.
Но не знаю как даже подступиться к этому потому что
1) Нигде не найду как PHP работает с бинарными числами
2)Лон интеджер всё же маловат для моих запросов. Тогда какое поле отводить в базе?
Есть идеи? | |
|
|
|
|
|
|
|
для: Eugene77
(26.05.2007 в 16:47)
| | - | |
|
|
|
|
|
|
|
для: Eugene77
(26.05.2007 в 16:47)
| | предложил бы для каждого пользователя завести массив с ключами - адресами или кодами страниц и значениями - количеством посещения
и занести пользователю в колонку в сериализованном виде | |
|
|
|
|
|
|
|
для: bronenos
(26.05.2007 в 17:30)
| | Спасибо, действительно, удобней будет работать с массивом .
Только вот
занести в сериализованном виде - тут у меня какой-то пробел в знаниях.
Можно кусочек кода написать для ясности? | |
|
|
|
|
|
|
|
для: Eugene77
(26.05.2007 в 20:40)
| | Я думал Вы хотите числа хранить - память эконимите или еще чего извращенное.. А тут на массив согласились.
Почему бы эти нули и единички не сохранить строкой?
// это то, что получится с массивом
<?php
for ($i = 0; $i < 200; $i++, $arr[$i] = 1);
echo serialize($arr);
?>
|
| |
|
|
|
|
|
|
|
для: kasmanaft
(26.05.2007 в 20:55)
| | Спасибо, что пролили свет на мою тёмную голову. Теперь я понял что bronenous имеет ввиду, но согласиться не могу. Огромная таблица получится. Не реально это лучше даже не начинать!
Подскажите лучше как грамотно и аккуратно сделать, минимум места заняв.
Некое подобие бинарного поля надо изобрести в таблице. Это будет реальный предел экономии места. Он не раздует мне таблицу больше разумных пределов. | |
|
|
|
|
|
|
|
для: Eugene77
(26.05.2007 в 16:47)
| | Наверняка SET либо (если SET маловат ) BLOB.
Если BLOB - в php будете работать с ним, как с обычной строкой. Каждый символ - восемь элементов множества. | |
|
|
|
|
|
|
|
для: Trianon
(26.05.2007 в 22:16)
| | serialize ($massiv)
вот то что вернет эта функция запишите в таблице
когда будете читать массив получите так
unserialize ($zapis) | |
|
|
|
|
|
|
|
для: bronenos
(26.05.2007 в 22:20)
| | Не надо мне на вопрос отвечать - тем более - неправильно. Я умею с битовыми картами работать. | |
|
|
|
|
|
|
|
для: Trianon
(26.05.2007 в 22:22)
| | Да при чем тут..... | |
|
|
|
|
|
|
|
для: Trianon
(26.05.2007 в 22:16)
| | Это мне каждый символ отдельно маскировать придётся?
Э-хе-хе - трудна работа програмиста!
Хотя, может так даже удобнее - масок всего восемь.
Только я не хочу BLOB использовать. Я хотел сделать всего два столбца, фиксированной ширины к тому же, чтобы максимально быстро работало.
Или что, у меня выбора нет? | |
|
|
|
|
|
|
|
для: Eugene77
(27.05.2007 в 20:18)
| | никто не мешает зафиксировать ширину у этого столбца.
Если не хотите понапрасну расходовать память и усложнять скрипт лишними перекодировками - альтернативы нету.
Вот алгоритмическая конструкция, проверяющая, поднят ли флаг в множестве:
function check_element($str, $elem, $on)
{
$idx = $elem >>3; $mask = 1<<($elem&7);
return (ord($str[$idx]) & $mask) != 0;
}
Конструкция, присваивающая элемент, пишется аналогично. | |
|
|
|
|
|
|
|
для: Trianon
(28.05.2007 в 00:10)
| | Спасибо!
Как же всё-таки написать обратную функцию?
Так?
function set_element($str, $elem)
{
$idx = $elem >>3; $mask = 1<<($elem%7);
return substr($str,0,$idx-1).chr(ord($str[$idx]) | $mask).substr($str,$idx+1);
}
Если так, то мне надо начинать нумерацию страниц сайта с 1.
Это возможно? Или autoincriment с нуля начнёт? | |
|
|
|
|
|
|
|
для: Eugene77
(28.05.2007 в 22:07)
| | autoincrement начинает с единицы.
Да. примерно так.Только почему $idx-1 ? | |
|
|
|
|
|
|
|
для: Trianon
(28.05.2007 в 23:45)
| | Только почему $idx-1 ?
Ничего умного тут сказать не могу. У меня вообще понятия о PHP пока довольно туманные.
Я не знаю включительно функция возвращает подстроку или исключительно.
Да и оператор >> меня в шок поверг - его в справочнике нет. Что, на самом деле он есть? Может у меня справочник устаревший? Потом сдвиги вообще-то разные бывают, циклические, например. Как я могу быть уверен, что это тот, что надо? В смысле, я доверяю, конечно, но твёрдой почвы под ногами пока почувствовать не могу. То есть сама ситуация подразумевает отсутствие этой почвы у меня.
Потом, строковые функции будут ли работать с несимвольными величинами?
Скажите да!
А то у меня слишком много сомнений для такого маленького отрывка кода, который сам по-себе ещё и не испытаешь. Придётся довольно большой фрагмент сразу сочинять. А я пока легко спотыкаюсь на самом элементарном. | |
|
|
|
|
|
|
|
для: Eugene77
(29.05.2007 в 19:42)
| | >Ничего умного тут сказать не могу. У меня вообще понятия о PHP пока довольно туманные.
>Я не знаю включительно функция возвращает подстроку или исключительно.
второй параметр функции substr - не конечный индекс, который может включаться или исключаться, а длина вырезаемой подстроки - то есть сущность абсолютно детерминированная. Попробуйте сказать в свете этого.
>Да и оператор >> меня в шок поверг - его в справочнике нет.
В мануале есть.
>Потом сдвиги вообще-то разные бывают, циклические, например
Циклические сдвиги не реализованы встроенными в язык операциями ни на одном из диалектов C, насколько мне известно, и в других языках тоже. Хотя со сдвигами и без того неоднозначностей хватает.
>Как я могу быть уверен, что это тот, что надо?
Вот этот раздел руководства прояснит Вам картину:
http://ru2.php.net/manual/ru/language.operators.bitwise.php
>Потом, строковые функции будут ли работать с несимвольными величинами?
>Скажите да!
С байтовыми цепочками произвольного вида? Безусловно. | |
|
|
|
|
|
|
|
для: Trianon
(29.05.2007 в 20:05)
| | второй параметр функции substr - не конечный индекс, который может включаться или исключаться, а длина вырезаемой подстроки - то есть сущность абсолютно детерминированная. Попробуйте сказать в свете этого.
При таком хорошем освещении, сразу заметно, что единицу я зря отнимаю.
Так у меня при каждом обращении один байт будет теряться. Исправлю. Спасибо!
Остальное тоже полезно.
Теперь вот не знаю как поле blob инициализировать.
Вот отрывок из файла:
<?
$qwiery[] = "CREATE TABLE visitors(
id int(6) NOT NULL auto_increment,
pages blob NOT NULL default '??????????',
PRIMARY KEY (id)
)TIPE = MyISAM";
$create_table = true;
foreach($qwiery as $value){
if(!mysql_query($value)) $create_table = false;
}
?>
|
Кстати, жаль, что циклические сдвиги недоступны, я бы на них щифрование сделал - проще не придумаешь! | |
|
|
|
|
|
|
|
для: Eugene77
(29.05.2007 в 21:51)
| | запишите там сразу нужное количество нулевых байт:
<?
$query[] = "CREATE TABLE visitors(
id int(6) NOT NULL auto_increment,
pages blob NOT NULL default '". '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0' ."',
PRIMARY KEY (id)
)";
|
Циклические сдвиги можно вычислить, как комбинацию логических, соединенных по побитовому ИЛИ.
А шифрование лучше самому не писать, а применять уже готовое. Уж больно скользкая область. Тем более что симметричных шифров в php реализовано вагон, а для асимметричных никакие циклические сдвиги не нужны. | |
|
|
|
|
|
|
|
для: Trianon
(29.05.2007 в 22:29)
| | TYPE = MyISAM | |
|
|
|
|
|
|
|
для: Unkind
(29.05.2007 в 22:31)
| | Угу. Поправил :) | |
|
|
|
|
|
|
|
для: Trianon
(29.05.2007 в 22:29)
| | Спасибо!
А есть симметричное шифрование, которое длину строки не меняет? | |
|
|
|
|
|
|
|
для: Eugene77
(30.05.2007 в 10:58)
| | если правильно применять шифрующий движок, то есть использовать не simple permutations а хотя бы в cipher feedback режиме, до длина строки не меняется. | |
|
|
|
|
|
|
|
для: Trianon
(29.05.2007 в 22:29)
| | Если соединить всё это вместе, то у меня получается вот такой код на три файла.
Я его привожу весь, потому что, как мне кажется, выходит довольно полезная утилита, позволяющая любому посетителю в любой момент времени узнать какие странички он ещё не видел. Я бы не отказался от такой возможности даже на этом сайте «софттайма», не говоря уже о некоторых других, в которых явно не хватает этой утилиты.
Конечно сейчас в тексте программы море ошибок, но иначе и не может быть – это ведь моя первая программа на PHP, которую я собираюсь реально использовать.
Заранее благодарю всех, кто укажет на ошибки и подскажет возможные усовершенствования. Особое спасибо Трианону! Без него я не сумел бы даже подступиться к этой задаче!
Файл вывода на экран списка посещённых страниц пока не рассматривается.
Извините за комментарии на английском языке. Мой Dreamweaver с русским вытворяет что попало. Может мне на другой редактор пересесть?
В начале создаются две таблицы каждая из двух колонок. Одна содержит названия файлов, вторая id посетителей и специальное поле типа blob, в котором каждый бит отвечает за посещение страницы с соответствующим номером. Id посетителей хранятся в cookies.
<?php
// This file create tables to count visits of eatch visitor of eatch page
$qwiery[] = "CREATE TABLE visitors(
id int(6) NOT NULL auto_increment,
pages blob NOT NULL default '". '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0' ."',
PRIMARY KEY (id)
)TYPE = MyISAM";
$qwiery[] = "CREATE TABLE pages(
id int(6) NOT NULL auto_increment,
page tinytext NOT NULL default '',
PRIMARY KEY (id)
)TYPE = MyISAM";
require_once("connect_db.inc");
$create_table = true;
foreach($qwiery as $value){
if(!mysql_query($value)) $create_table = false;
}
if ($create_table) echo "??????? ??????? ???????";
else echo "?????? ??? ???????? ??????";
?>
|
Эта та часть кода, которая включается на каждую учитываемую страницу. Он извлекает из cookies id посетителя, из серверной переменной берёт имя файла, запрошенного клиентом, и устанавливает в bit отвечающий за номер этой страницы единицу в строке с id посетителя. По крайней мере, должна это делать.
<?php
// This part of code must be included in every file
require_once("connect_db.inc");
$query="SELECT count(*) FROM visitors"; // Count number of visitors
$vstrs = mysql_query($query);
$v = mysql_fetch_array($vstrs, MYSQL_NUM);
if(!isset($COOKIE['id'] || $COOKIE['id']>$v) { // Id of visitor supposed to be in cookies
$id = $v+1;
setcookie("id", $id, time()+60*24*60*60); // Set cookie on two monthes period
header("Location: cookies_on.php?id=$id"); // Check if cookie really set
}
else $id = $COOKIE['id'];
if(isset($PHP_SELF) $name_page=$PHP_SELF; // Take name of current page
else $name_page='no_page';
$query="SELECT id FROM pages WHERE $page = $name_page"; // Find out id number of page
$id_page = mysql_query($query);
if(!$id_page || mysql_num_rows($id_page)<1)) { // If page not registered in the table, we are to add record into the table pages
$query="INSERT INTO pages page=$name_page"; // Insert new line into table pages
if(!mysql_query($query)) echo "New page $name_page not inserted";
$query="SELECT id FROM pages WHERE page = $name_page"; // Find out id number of page
if(!($id_page = mysql_query($query))) echo "New line is not created";
}
$pg = mysql_fetch_array($id_page, MYSQL_NUM);
$query="SELECT pages FROM visitors WHERE id = $id"; // Extract list of visited pages
$p = mysql_query($query); //
$pages = mysql_result($p, 1);
$p=set_element($pages, $pg); // Add current page to list of visited pages
$query="UPDATE visitors pages=$pages WHERE id = $id";
mysql_query($query); //
function set_element($str, $elem){
for($i=$elem-strlen($str); $i<0; $i++) $str ='/0'.$str; // In case if number of pages exeed initialy reserved place in colomn pages, we make the col. wider
$idx = $elem >>3; $mask = 1<<($elem%7);
return substr($str,0,$idx).chr(ord($str[$idx]) | $mask).substr($str,$idx+1);
}
function check_element($str, $elem){
$idx = $elem >>3; $mask = 1<<($elem%7);
return (ord($str[$idx]) & $mask) != 0;
}
?>
|
Этот маленький файл проверяет, действительно ли cookie установлен.
<?php
// file: cookies_on.php
if(!isset($_GET['id']) die("Name of cookie not set");
if(!isset($_COOKIE['id']) die("Please, let us to set cookie!");
if($_GET['id'] != $_COOKIE['id']) die("Wrong cookie value");
header("Location: $_SERVER['HTTP_REFERER']");
?>
|
| |
|
|
|
|
|
|
|
для: Trianon
(29.05.2007 в 22:29)
| | ---- | |
|
|
|