пятница, 25 апреля 2008 г.

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

Сегодня нужно было купить пару железок для железного друга. Так как лень наше всё, решил сделать заказ через интернет. Нашёл, заказал, но плюх, оказывается доставки нет. Не стал отчаиваться и решил подышать свежим воздухом. 
Добрался, зашёл, осмотрелся.  Менеджер был занят заказчиком, пошёл посмотреть на витрины, пока смотрел пришло ещё два покупателя. Пока постоял и пока выдали заказ обратил внимание, что все пятеро уже заказали товар и пришли только оплатить и забрать. Сравнивая с другими местами, где терлось столько же народу, но в основном все приходили поглазеть, понял важность сайтов на шкуре заказчиков.
Разрабатывая сайты, не часто приходится пользоваться плодами своего творчества, а здесь всё как на ладони - посмотрел, оценил, буду другим рассказывать.

четверг, 10 апреля 2008 г.

Мысли о скобках

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



<?php
$template = new template;
// здесь присваивание переменных. вывод куска шаблона,
// а после
// я так понял, это автор хотел очистить переменные
$template->freshall;
?>

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

четверг, 3 апреля 2008 г.

Собственный обработчик сессий.

В предыдущей части был описан принцип работы сессий по умолчанию, сейчас постараемся его переопределить.
Для этого нам нужна следующая функция
bool session_set_save_handler ( callback open, callback close, callback read, callback write, callback destroy, callback gc )
Она вызывается перед использованием session_start().
Параметры – это кэлбак функции, которые вызываются при определённом вызове.
1) bool open(string path , string filename) – вызывается при вызове session_start(), на вход получает 2 значения – путь к директории с файлами сессий и имя файла. Возвращает true, если успешно.
2) bool close() – вызывается при завершении работы сценария. Возвращает true в случае успеха.
3) array read(string session_id) – вызывается при старте сессии, получает идентификатор сессии, заполняет $_SESSION;
4) bool write(string session_id, array data) – записывает изменения.
5) bool destroy(string session_id) – вызывается при session_destroy()
6) bool gc(int time) – уборщик мусора, на вход получает время жизни сессии.
Сейчас сделаем обёртку для хранения данных в базе данных.

<?php
class Session {
private $dbh; // хендл на соединение с базой данных
private $sessionLife = 3600; // время жизни сессии
// в конструкторе устанавливаем обработчик, устанавливаем время жизни сессионной куки и стартуем сессию
public function __construct() {
session_set_save_handler(
array($this, '_open'),
array($this, '_close'),
array($this, '_read'),
array($this, '_write'),
array($this, '_destroy'),
array($this, '_gc')
);
session_set_cookie_params($this->sessionLife);
session_start();
}
// при старте сессии открываем соединение с базой данных
private function _open($dir, $name) {
$this->dbh = mysql_connect('localhost', 'root', '');
if (!$this->dbh) die('Bad database connect');
if (!mysql_select_db('test')) die('Bad db table name');
return true;
}
// при окончании работы закрываем соединение
public function _close() {
mysql_close($this->dbh);
}
// считываем данные из базы данных и десериализируем их
private function _read($id) {
$sql = 'SELECT `data`
FROM `session`
WHERE `session_id`=\''.mysql_real_escape_string($id).'\'
LIMIT 1
';
$data = mysql_query($sql, $this->dbh);
if (!$data) die(mysql_errno() . ": " . mysql_error() . "\n");
$data = mysql_fetch_assoc($data);
if (isset($data['data'])) {
return unserialize( $data['data'] );
} else {
return array();
}
}
// при записи сериализируем данные и засовываем их в базу данных
public function _write($id, $data) {
$sql = 'REPLACE INTO `session`(`session_id`, `data`, `date_updated`)
VALUES (\''.mysql_real_escape_string($id).'\',
\''.mysql_real_escape_string(serialize($data)).'\',
UNIX_TIMESTAMP() )
';
if (mysql_query($sql, $this->dbh)) {
return true;
} else {
die(mysql_errno() . ": " . mysql_error() . "\n");
}
}
// при убийстве очищаем массив с данными, убиваем куку и чистим базу
public function _destroy($id) {
$_SESSION = array();
unset($_COOKIE[session_name()]);
setcookie(session_name(), '', time()-42000, '/');
$sql = 'DELETE FROM `session`
WHERE `session_id`=\''.mysql_real_escape_string($id).'\'
LIMIT 1
';
if (mysql_query($sql, $this->dbh)) {
return true;
} else {
die(mysql_errno() . ": " . mysql_error() . "\n");
}
}
// убираем старые сессии
public function _gc($time) {
$sql = "DELETE FROM `session`
WHERE `date_updated` < UNIX_TIMESTAMP() - {$this->sessionLife}
";
if (mysql_query($sql, $this->dbh)) {
return true;
} else {
die(mysql_errno() . ": " . mysql_error() . "\n");
}
}

}
// тестируем
$session = new Session();
$_SESSION['test'] = 1;
var_dump($_SESSION);
?>

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