Osfonder's blog Just another wd weblog

1Май/100

Has been acquired by Google

В последнее время эта надпись очень часто наблюдается на главной того или иного стартапа.
И вот очередной omnisio.com
Вперед.

Метки записи: , Нет комментариев
27Апр/100

Касперский и баннеры

Не формат, но злободневно и основываясь на опыте.

Если ваши партнеры жалуются, что их баннеры не показываются на вашем сайте, первым делом проверьте, что в именах файлов и путях к ним не присутствуют слова banners, ad, ads.
Такие файлы (но наверняка ими не ограничиваясь) блокирует Антивирус Касперского, удаляя их из трафика пользователей.

Чтобы исправить это нужно просто переименовать директории содержащие файлы баннеров, в что-то отдаленное например images_b, images_a.
Успехов.

Метки записи: , , Нет комментариев
25Апр/100

Обзор Doctrine 2.0

Презентация, находящейся пока в разработке версии, Doctrine ORM PHP Framework от разработчиков.
Подробно, вплоть до используемых ими инструментов. Очень хорошо раскрыли перспективы развития.

Метки записи: , Нет комментариев
24Апр/100

Что такое ORM и когда её использовать

Обоснование ORM модели. Что к чему

В первом, формальном приближении, понимание ORM модели в том, что все записи представляются в виде объектов, поля — в виде свойств. Но не стоит на этом определении заострять особое внимание. Суть модели чуть ниже.

Дело в том, что очень часто(в средних и больших проектах), мы не имеем заранее представления о том, какие и сколько свойств будет у объекта.

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

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

Классическая модель

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

Суть ORM

Но технологии идут вперед и скорость работы серверов, куда быстрее чем раньше. Что позволяет, сильно модель базы данных упростить, и ускорить процесс разработки. В наипростейшем случае сократить до двух таблиц: одна всех объектов, вторая — их свойств.
В этом и есть истинное понимание и суть ORM модели базы данных.

Это сказывается на производительности, но в разы уменьшает время разработки.
К счастью, и разработчики языков программирования и серверов баз данных — умные люди, и делаю всё возможное, чтобы ускорить работу такой модели, так что камнем преткновения этот показатель считать не будем.

Когда отказываться от ORM

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

Авторитетное мнение

Современный PHP Framework — Symfony, проводил 15-17 февраля 2010 года международную конференцию в Париже symfony live.
На ней был весьма интересный доклад от разработчика из Yahoo! Дастина Уиттла(Dustin Whittle). Он рассказал, как они затачивают symfony под свои проекты.
Так же он отметил, что для маленьких проектов нужно отказываться от ORM, а для средних нужно использовать Doctrine.

Посты по теме

  1. Doctrine tutorial. Первые шаги. Установка, настройка, создание таблиц
23Апр/102

Doctrine tutorial. Первые шаги. Установка, настройка, создание таблиц

По долгу службы я работаю на проектом, в котором возникла необходимость использования этой системы.
Если вкратце Doctrine — это открытый php framework для работы с ORM моделью базы данных.
До этого с ним работать не приходилось и я занялся поиском уроков по началу работы с этим фрэймворком. Но ресурсов на русском языке, почти не было. Статьи были либо уже матерых разработчиков скупо описывающих шаблоны, либо обзорные о возможностях. И тех и тех по пальцам пересчитать. Но, как и с чего начать не найти.
Поэтому я пришел пораньше в пустой офис, чтобы описать, пока свежи в памяти и материалы под рукой, первые этапы разработки на нем.

Итак, Doctrine — это фреймворк, генерирующий по заданным вами правилам, модель базы данных и классы php для работы с ней. Таким образом позволяя полностью абстрагироваться от конкретной БД. PostgreSQL, Oracle, MySQL и т.п. не меняя описания вашей базы данных в doctrine, вы можете использовать любую из них.

1. Установка

С чего начать?
Для начала в папку с проектом нужно загрузить framework. Например так:

svn co http://svn.doctrine-project.org/branches/1.2/lib lib/vendor/doctrine

Теперь в lib/vendor/doctrine лежит наша библиотека.

2. Настройка

Далее в корне создаем конфигурационный файл, в котором буду базовые настройки.

bootstrap.php

require_once(dirname(__FILE__) . '/lib/vendor/doctrine/Doctrine.php');
spl_autoload_register(array('Doctrine', 'autoload'));
spl_autoload_register(array('Doctrine_Core', 'modelsAutoload'));
$manager = Doctrine_Manager::getInstance();
$manager->setAttribute(Doctrine_Core::ATTR_AUTO_ACCESSOR_OVERRIDE, true);
$manager->setAttribute(Doctrine_Core::ATTR_AUTOLOAD_TABLE_CLASSES, true);
$manager->setAttribute(Doctrine_Core::ATTR_MODEL_LOADING, Doctrine_Core::MODEL_LOADING_CONSERVATIVE);

$conn = Doctrine_Manager::connection('mysql://USERNAME:PASSWORD@localhost/DATABASE');
$conn->setCharset('utf8');

Этот файл будет подключаться во всех скриптах, использующих Doctrine:

require_once('bootstrap.php');

3. Создание таблиц

Подготовка завершена. Настало время описать нашу базу данных. Самый распространенный это способ сделать — использовать yaml(доктрин может сгенерировать эти файлы и на основе имеющейся БД)

Начнем с простого, одна таблица user на языке yaml будет выглядеть так:
schema.yml

User:
  tableName: user
  columns:
    id:
      type: integer(8)
      primary: true
      autoincrement: true
    is_active:
      type: integer(1)
      default: '1'
    is_super_admin:
      type: integer(1)
      default: '0'
    created_at:
      type: timestamp(25)
      notnull: true
    updated_at:
      type: timestamp(25)
      notnull: true
    first_name: string(255)
    last_name: string(255)
    username: string(255)
    password: string(255)
    type: string(255)

Оригинальный SQL синтаксис для неё был бы такой:

CREATE TABLE user (
   id bigint(20) NOT NULL auto_increment,
   first_name varchar(255) default NULL,
   last_name varchar(255) default NULL,
   username varchar(255) default NULL,
   password varchar(255) default NULL,
   type varchar(255) default NULL,
   is_active tinyint(1) default '1',
   is_super_admin tinyint(1) default '0',
   created_at TIMESTAMP,
   updated_at TIMESTAMP,
   PRIMARY KEY  (id)
) ENGINE=InnoDB

Но нас он не интересует.

Создаем папку schemas и помещаем в нее вышеуказанный файл schema.yml

Теперь создадим файл generate.php в корне который сделает всю работу по созданию БД и php классов:

include 'bootstrap.php';
Doctrine_Core::dropDatabases();
Doctrine_Core::createDatabases();
Doctrine_Core::generateModelsFromYaml('schemas/schema.yml', 'models');
Doctrine_Core::createTablesFromModels('models');

После запуска, в корневой папке будет создана папка models, с содержащимися в ней php классами, а в базе данных будут создана таблица user (проверьте имя пользователя, пароль и название БД в bootstrap.php).

4. Использование

Ну и тестовый файл:
creareUser.php

require_once('bootstrap.php');
Doctrine_Core::loadModels('models');

$user = new User();

$user->username = 'login';
$user->password = md5('pass'.'salt');

$user->save();

var_dump($user->toArray());

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

5. Бонус

Интриги ради продемонстрируем одну из возможностей Doctrine

Открываем файл models/User.php и заменяем его содержимое на такое:
models/User.php

class User extends BaseUser
{
    public function setPassword($password)
    {
        return $this->_set('password', md5($password));
    }
}

Теперь, создавая пользователя можно сразу писать

$user->password = 'pass';

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

echo $user->password;

Для начала, пожалуй, достаточно.

23Апр/100

Разработка сайтов: Процесс загрузки страницы

Занимаясь оптимизацией работы сайта нужно хорошо представлять, что происходит после того, как посетитель, набрав адрес, нажал клавишу Enter.
Почему тема оптимизации загрузки сайта важна? Дело в том, что интернет сейчас и десять лет назад сильно отличаются. Сейчас люди ожидают, что загрузка должна происходить быстро. А многие, в том числе и поисковые роботы, слишком долго прождав требуемую страницу, просто закроют её (using site speed in web search ranking).

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

Итак, что происходит после того, как пользователь ввел http://osfonder.ru/blog/ и нажал Enter? Заканчивается это все тем, что вылезет список постов, но до этого...

Визуально процесс выглядит так:

У вас отключен JavaScript. Воспользуйтесь ссылкой ниже для просмотра ролика.



оригинал на сайте bbc

1. DNS

Любой сайт в сети физически располагается на каком-либо сервере. Это компьютер, который постоянно работает и подключен к сети. Каждый сервер имеет, как минимум, один IP адрес. Он позволяет сей сервер уникально идентифицировать. IP адрес — это четыре числа от 0 до 255 разделенных точкой.
И после того как был нажат enter, браузер(читай компьютер) пользователя должен каким-то образом определить к какому серверу(читай IP адресу) относиться адрес osfonder.ru.

Для этого в интернете существуют DNS сервера. Они и хранят такую, необходимую для определения, информацию. По сути в определении адреса участвует цепочка DNS серверов, каждый из которых говорит к какому DNS серверу обратиться, дальше(делегируют) пока последний в этой цепи не выдаст желаемый IP адрес. Каждое звено цепи, естественно, тоже создает задержку.
Но ограничимся лишь тем, что система DNS, в итоге преобразует человеко-понятный символьный адрес в IP адрес и сообщает сколько времени считать его действительным и не дёргать систему, пока время не истечет.

2. Маршрутизация

Хорошо, IP-адрес определили. И, по идее, не плохо бы сразу обратиться к этому адресу просто выбрав нужный провод, на другом конце которого находится сервер. Но нет возможности напрямую соединять каждый компьютер с каждым. Да и интернет к вашему компьютеру подсоединен только с помощью одного провода.

А потому пакеты информации от вашего компьютера до сервера добираются через роутеры, работа которых схожа с DNS серверами. Добравшись до ближайшего роутера ваш пакет будет им направлен на следующий. И так далее и так далее пока не достигнет наконец сервера. И какова бы скорость вашего интернет соединения не была, каждый роутер выполняет вычисления, которые незначительно, но тормозят процесс получения вами информации. И фактически количество промежуточных роутеров зависит от расстояния между вами и сервером.

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

Для примера, зайдите на cnn.com, а затем на lenta.ru и почувствуйте разницу. Если вы находитесь на территории РФ скорее всего лента.ру загрузиться быстрее. И дело в том, что в первом случае информация полетит по проводам в Атланту и из Атланты к вам(скорее всего через Москву и Санкт-Петербург), а во втором — ограничиться Москвой. В первом случае количество промежуточных роутеров порядка 50-ти, во втором меньше 10. Каждый из них создает незначительную задержку.

3. Передача данных

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

Еще чуть технической информации и дальше пояснение.
Браузеру(компьютеру) требуются какие-либо данные от сервера. Я ввожу http://lenta.ru нажимаю Enter, значит мне нужна главная страница новостей. Браузер устанавливает соединение пройдя вышеописанный процесс и говорит серверу: "мне нужна главная страница сайта lenta.ru",
а буквально передает серверу

GET / HTTP/1.1
Host: lenta.ru
+ еще немного информации о себе и почти всегда cookie данные

Это называется HTTP запрос.
Сервер говорит: "хорошо у меня есть такая страница"(200 OK + еще немного информации) и начинается передача данных. Т.е. html кода этой страницы. После передачи соединение закрывается.

Любой сайт использует внешние файлы. Проще говоря — это картинки, css-стили, js-скрипты. И для каждого из них выполняется процесс маршрутизации, устанавливается новое соединение и вышеописанная операция повторяется. Чувствуете?
Например, в админ-панели последней версии UMI-CMS загружается около 70-ти внешних файлов(без учета системных xml). Что, в принципе, можно оптимизировать.
Админ-панель подходящий случай, т.к. подразумевает частое использование, её оформление не меняется, а потому может и должна работать быстро. И скорость загрузки админки UMI, чуть не единственная претензия нашего отдела сопровождения к ней.
Но не стоит умолять важность скорости загрузки любых страниц и веб-приложений.

Заключение

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

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

Посты по теме

  1. 10 Золотых принципов успешных Веб-приложений
  2. Используйте CDN для ускорения своих сайтов
  3. Способы ускорения загрузки страницы часть 1
  4. Способы ускорения загрузки страницы часть 2
  5. Способы ускорения загрузки страницы часть 3
19Апр/100

.htaccess защита папок и файлов

В посте внешний вид mod_autoindex говорилось о том, как улучшить отображение и функциональность страниц, автоматически сгенерированных apache'ем при просмотре директорий.

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

Можно легко расширить область его использования и избавиться от этого недочёта.

Для торопливых сразу суть: при просмотре содержимого будет единожды запрошена HTTP авторизация. Опять же, только силами apache и без промежуточных скриптов. Просматривать содержимое можно только при правильном вводе имени пользователя и пароля.

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

Более оптимальный ход — это запретить просмотр содержимого каталога без авторизации, что можно просто сделать с помощью .htaccess и .htpasswd файлов.

.htaccess

В .htaccess добавляем

#Для файлов, не имеющих имени — каталогов
<FilesMatch "^$">
    #Сообщение выводимое сервером с просьбой авторизоваться
    AuthName "Authorization"
    AuthType Basic
    #Полный путь к файлу .htpasswd(его мы получим ниже)
    AuthUserFile /full/path/to/.htpasswd
    Require valid-user
</FilesMatch>

.htpasswd

Файл .htpasswd содержит список допустимых пар пользователь:пароль
Захэшированный пароль, если точнее.
Сгенерировать содержимое .htpasswd можно здесь:



Файл .htpasswd

Заметьте, в .htaccess указывается полный путь до файла .htpasswd.
Его можно узнать, например, выполнив php скрипт со строкой

echo __FILE__;

Ну и последнее: если хотите защитить паролем вообще все файлы, нужно в .htaccess вместо

#Для файлов, не имеющих имени — каталогов
<FilesMatch "^$">

использовать

#Для файлов с любым именем
<FilesMatch "^.*$">

17Апр/100

Внешний вид mod_autoindex или организация FTP

У вас есть сервер, который вы используете(в том числе) для хранения файлов и доступа к ним из любого места через интернет-браузер, а файлы, скорее всего, заливаете по FTP.
Если да, то скорее всего вам знакома такая картина

А нет, извините, вам знакома такая


Это стандартная выдача mod_autoindex сервера apache.

Но предлагаю немного упростить себе жизнь и превратить
её в такую.

Да и вообще в онлайн плеер.

Можно это сделать, установив по умолчанию индексным файлом, например, php скрипт, который и будет делать всю черную работу. Есть проект на sourceforge посвященный этому(autoindex).

Но использовать лишнее звено в виде php нет смысла, если есть возможность воспользоваться стандартными функциями или хотя бы просто добавить javascript файл в выдачу. И такая возможность есть.

Большую часть работы по этому уже проделана. Результат её здесь.

Доработанную её версию вам и предлагаю.

Загрузка

Скачать

Нужно просто распаковать архив в корень вашего ФТП хранилища.

Возможности

  1. Сортировка по имени, дате модификации, размеру, типу
  2. Предпросмотр фотографий и изображений
  3. Онлайн прослушивание mp3 файлов

Ну и приглядный внешний вид с иконками.

Техническая сторона

Ну и на последок немного технической информации.

  1. Предпросмотр изображений выполнен с помощью YUI Tooltip
  2. Проигрыватель музыкальных файлов Yahoo! Media Player
  3. JavaScript'ы и устанавливаются в обрамляющих выдачу файлах(см. .htaccess ниже)

P.S. Музыка на скриншоте моих друзей Waterplea, пишущих большей частью ambient.

#Файлы, вставляемые до и после выдачи(в них и крепяться стили и javascript'ы)
HeaderName /indexoverride/HEADER.html
ReadmeName /indexoverride/FOOTER.html
#Запрещаем в выдаче ненужные и системные файлы
IndexIgnore .htaccess indexoverride Thumbs.db .??* *~ *# RCS CVS *,v *,t

#Соритировка по умолчанию
IndexOrderDefault Ascending Description

#Настроки структуры выдачи
IndexOptions FancyIndexing FoldersFirst IconsAreLinks NameWidth=* IconWidth=32 IconHeight=32

#Кодировка по умолчанию
IndexOptions Charset=UTF-8

#Иконки и описания по расширениям файлов
AddIcon (IMG,/indexoverride/image.png) .jpg .JPG .png .PNG .bmp .BMP .svg .SVG .gif .GIF .wmf .WMF .psd .PSD
AddDescription "image / PNG" 		*.png *.PNG
AddDescription "image / JPG" 		*.jpg *.JPG
AddDescription "image / BMP" 		*.bmp *.BMP
AddDescription "image / SVG" 		*.svg *.SVG
AddDescription "image / GIF" 		*.gif *.GIF
AddDescription "image / WMF" 		*.wmf *.WMF
AddDescription "image / PSD" 		*.psd *.PSD

AddIcon (AUDIO,/indexoverride/audio.png) .mp3 .MP3 .wav .WAV .ogg .OGG
AddDescription "audio / MP3" 		*.mp3 *.MP3
AddDescription "audio / OGG" 		*.ogg *.OGG

AddIcon (VIDEO,/indexoverride/video.png) .mov .MOV .avi .AVI .mpg .MPG
AddDescription "video / QuickTime" 	*.mov *.MOV
AddDescription "image / AVI" 		*.avi *.AVI
AddDescription "image / MPEG" 		*.mpg *.MPG

AddIcon (FLA,/indexoverride/flash_src.png) .fla .FLA .as .AS
AddDescription "flash / FLA" 		*.fla *.FLA
AddDescription "flash / AS" 		*.as  *.AS

AddIcon (SWF,/indexoverride/swf.png) .swf .SWF
AddDescription "flash / SWF" 		*.swf *.SWF

AddIcon (TXT,/indexoverride/text.png) .txt .TXT
AddDescription "document / TXT" 	*.txt *.TXT

AddIcon (XLS,/indexoverride/xls.png) .xls .XLS .csv .CSV
AddDescription "document / XLS" 	*.xls *.XLS
AddDescription "document / CSV" 	*.csv *.CSV

AddIcon (DOC,/indexoverride/doc.png) .doc .DOC
AddDescription "document / DOC" *.doc *.DOC

AddIcon (PPT,/indexoverride/ppt.png) .ppt .PPT
AddDescription "document / PPT" *.ppt *.PPT

AddIcon (PHP,/indexoverride/php.png) .php .PHP
AddDescription "PHP" *.php *.PHP

AddIcon (HTM,/indexoverride/html.png) .htm .html .HTM .HTML
AddDescription "HTML" *.htm* *.HTM*

AddIcon (HTM,/indexoverride/css.png) .css .CSS
AddDescription "CSS" *.css *.CSS

AddIcon (ARCHIVE,/indexoverride/archive.png) .zip .rar .arj .arc .tar .targz .gz .Z
AddDescription "Archive / ZIP" *.zip *.ZIP
AddDescription "Archive / RAR" *.rar *.RAR
AddDescription "Archive / ARJ" *.arj *.ARJ
AddDescription "Archive / ARC" *.arc *.ARC
AddDescription "Archive / TAR" *.tar *.TAR
AddDescription "Archive / GZ" *.gz *.GZ
AddDescription "Archive / TARGZ" *.targz *.TARGZ
AddDescription "Archive / compress" *.Z

#Иконка для родительской дирректории
AddIcon (PAR,/indexoverride/dir.png) ..

#Иконка по умолчанию
DefaultIcon /indexoverride/default.png

#Иконки по типам
AddIconByType (TXT,/indexoverride/text.png) text/*
AddIconByType (IMG,/indexoverride/image.png) image/*
AddIconByType (VID,/indexoverride/video.png) video/*
AddIconByEncoding (CMP,/indexoverride/archive.png) x-compress x-gzip
10Апр/100

PHP Пасхальное яйцо

В PHP есть пасхальное яйцо, иногда позволяющее, определить, что сайт работает именно на нем.

Например вконтакте.ru

Достаточно добавить
?=PHPE9568F36-D428-11d2-A769-00AA001ACF42
в конце адресной строки.

Удаляется, обычно, при помощи mod_rewrite.

3Апр/100

Формы Google Docs

У Google Docs есть замечательный инструмент, который позволяет создавать пользовательские формы. Их можно разослать по почте, вставить на страницу или дать ссылку на нее. Вся информация с них будет собрана в вашей таблице.
Но есть проблема: системные сообщения выводятся на английском языке. Такие как required, submit, etc... Что не очень красиво вставлять на русскоязычный сайт:

google docs form

Имеет она неожиданное решение, в виде выставления языка в настройках Google Docs. Т. е. все ваши формы имеют, установленный в настройках аккаунта язык. Увы даже вездесущим добавлением ?hl=ru к гугловским url'ам это не решается. Надеюсь разработчики в ближайшем будущем обратят на это внимание.

Ну, вот и пример рабочей формы на сайте:

И результат её работы: