Записи автора
История одного сайта
Еще одно большое дело успешно сделано нашей командой. На этот раз речь пойдет о большом проекте сайта белорусской радиостанции «Альфа Радио«.
Нельзя сказать что для нас этот проект был тривиальным и простым. Уже в самом начале пути мы четко представляли, что путь к успеху будет тернист, т.к. перед нами стояла стратегическая задача — сделать «бомбу» Байнета как в качестве дизайна, так и в качестве сервисов. Среди требований заказчика больше было пунктов, которые вряд ли бы взялась выполнять даже самая продвинутая студия с заоблачными ценами, а имено:
- сайт должен быть ярким и динамичным в плане дизайна;
- сайт должен иметь фишки ради которых хотелось бы вернутья и рассказать другим;
- сайт должен быть не просто набором страниц. Он должен быть живым, иметь душу и сердце, настроение…
И он будет таким!!!
Первым с чем пришлось столкнуться, когда началась разработка сайта — это с выбором «движка». К «движку» предъявлялись настолько высокие требования, что такие монстры как Drupal, Bitrix, Netcat просто отметались, не удовлетворя даже половине потребностей. Но после кропотливого естественного отбора мы остановились на Symfony. Да, это то что надо — гибкий, свежий и динамично развивающийся фреймворк!
Далее дело усложнилось… ведь заказчик хочет показать на сайте информацию о играющей в данный момент музыкальной композиции… Все бы хорошо, но вот только в наш сервер не встроен FM тюнер с функцией приема RDS… Казалось бы тупик, мы проиграли битву, но НЕТ! Решение было найдено — мы написали специальный Windows сервис, который был специально установлен на вещательное оборудование заказчика. Данный сервис выполняет функцию отправки данных о текущей и последующих играющих композициях на наш хостинговый сервер. Еще одна победа за нами!
Как же заставить сайт жить? Как заставить менять настроение? Пожалуй это еще одна задача от старца Фура (вы же тоже смотрели «ключи от форта Боярд»?!)
- флеш и смежные технологии — уже не модно и «тяжеловесно»;
- HTML 5 (canvas) + JS — уж слишком маленькая целевая аудитория способная это увидать.
Хотелось сделать что то грациозное, запоминающееся, такое как восход солнца летом! Такое же фундаментальное как день и ночь, как зима и лето! БИНГО! Давайте же обучим сайт реагировать на время суток и пору года! Пускай он будет яркий и пропитанный солнцем днем, и завораживающе темный ночью! Пускай он будет летом одним, а зимой другим! Сказано — сделано! Теперь сайт меняет свой облик в зависимости от времени суток, а так же поры года!
А как же пользователь, все это здорово, но как же завлечь того самого «избалованного» поситителя? Надо дать ему что-то такое, чем он сможет играться, что будет приводить его в восторг и заставлять говорить об этом друзьям и подругам!
А давайте дадим посетителю возможность стать ди-джеем на радио! Пускай посетители выбирают на свой вкус композиции и добавляют в плей-листы, делятся своими предпочтениями с другими слушателями! Пускай они слушают фонотеку альфа-радио не зависимо от наличия радиоприемника дома! (Аплодисменты стоя!)
Вместо эпилога
Потратив кучу усилий и перебрав неимоверное количество технологий мы создали по истине шедевр, который заставит восхищаться даже самого видавшего виды интернетчика! Сомневаетесь — тогда загляните на новый сайт alpha.by)
Экономим на разработке web сайта (Fixed price vs Time & Material)
После прочтения бессмертного произведения об утопии все мы начинаем понимать что живем в неидеальном мире!
Зачастую работая с отечественными заказчиками мы сталкиваемся с одной и той же ситуацией, которая так или иначе касалась любого исполнителя:
— Здравствуйте, мы хотим сайт как http://www.xxxxx.web (показывают мега-портал с неизвестным функционалом). Сколько будет стоить ?
Любой человек, будучи в душе хоть немного с «коммерческой жилкой» сразу начинает соображать что нельзя упустить шанс заработать, и начинает называть цену откровенно говоря наугад. Причем заведомо называют заниженную цену, чтобы не упустить заказчика, не задумываясь о том, что будет дальше.
Почему мы повторяем одну и ту же ошибку, и как научиться правильно определять цену подобного проекта? Ответ на вопрос вроде бы очевиден — глубже изучить сайт, оценить объем предстоящей работы, добавить риски, затраты на кофе и валерьянку, и назвать заказчику сумму. Но, опять же, возникает дилема — назвать большую сумму = потерять заказчика и отдать проект конкурентам (они назовут меньше сумму), студентам (они пообещают сделать за еду). Или же слукавить, занизив сумму, а потом выбивать дополнительные деньги, аргументируя «подводными камнями» и шантажируя отказом от проекта… В любом случае мы применяем подход Fixed Price (Фиксированная цена за продукт под ключ), что не является правильным при данной задаче.
На Западе очень распространен подход Time&Material (Время и материалы), причем он широко распространен не только в области разработки но и в других отраслях, где требуются значительные средства и усилия архитектора, менеджера проекта, маркетолога. Нашему заказчику пока такой подход ассоциируется с игрой в наперстки на вокзале — т.е. ему может казаться, что в итоге все, кроме него, останутся в выигрыше. Читать далее »
Что такое хорошее техническое задание на сайт?
Я могу припомнить на удивление мало материалов, посвященных проектированию сайтов и программ на русском языке, написанных русскоязычными авторами. Этому способствует и преимущественно экспортно-ориентированная разработка (оффшор) и отсутствие массового опыта создания информационных продуктов в нашей стране.
Надеюсь, что эта статья пригодится тем разработчикам и IT-менеджерам, кто ощутил перед собой проблему составления качественных документов на разработку и создание сайта. Документов, которые кроме испорченной бумаги были бы хоть чем-то полезны.
Вводная
Зачем составлять техническое задание (ТЗ) на сайт?
Какую бы методику разработки вы не использовали, и какого бы размера ни был ваш сайт, вы в любом случае столкнетесь с вопросом: «А когда мы будем заканчивать работу, то как мы поймем, что мы ее действительно закончили?» В разработке как ПО, так и любого сайта частая проблема — никто не видит конечной точки. С одной стороны можно сказать, что конечным видением проекта должен обладать проектный менеджер. Но если конечный продукт совпадет с образом менеджера, но не совпадет с ожиданиями клиента? А если за время проекта меняется 3 менеджера?
Следствие закона Паркинсона «девяносто-девяносто»:
Первые 90% кода отнимают 90% времени разработки. Оставшиеся 10% кода отнимают вторые 90% времени разработки.
ТЗ это не просто список требований, это документ. Если договор регулирует процесс организационных и финансовых взаимоотношений, то ТЗ регулирует процесс разработки и конечный результат.
В этом случае не имеет никакого значения большой разрабатывается сайт или малый. Проблема рассогласования ожиданий может возникнуть в независимости от объема затраченных средств, вот только последствия могут быть разными.
О чем эта статья.
Эта статья о том, что может пригодиться в процессе написания ТЗ на сайт, а также что будет уж точно сделать желательно. Но эта статья не о том, как надо писать проектную документацию. В конечном итоге главная задача проектировщика не написать классный документ, а спроектировать сайт. Хороший документ лишь отражение подхода и уважения ко всем участникам разработки.
Добавлю ограничения.
Всегда когда я говорю о написании ТЗ, то имею в виду, конечно же, каскадную методику разработки. В случае других вариантов (например, экстремальное программирование) составляются другие документы и часто по другим принципам. Это — раз.
Стоит разделять ТЗ для малых и больших сайтов. Это — два. Различия маленьких и больших проектов заключаются не в объеме документа на выходе, а в процессе их разработки. Если у вас всего 4 человека в проектной группе, все давно знают друг друга, то можно предполагать отсутствие формализма. Если же разработкой занимаются несколько «отделов», а проектная команда состоит из более 10-ка (до бесконечности) сотрудников, то управлять этой ордой может только процесс. Процесс рождает формализацию, а формализм накладывает свой отпечаток на формат документации.
По сути, толщина документов зависит от сложности процесса в больше степени, нежели от размеров проекта.
Мы будем следовать самому сложному пути.
ТЗ отвечает на вопросы
ТЗ изначально создается для нескольких участников разработки:
- Разработчики проекта (дизайнеры и программисты).
- Проект-менеджер.
- Клиент.
- Бюрократы (они могут не участвовать в проекте, но на них тоже надо рассчитывать).
Оглядываясь на приведенные группы участников можно предположить, что ТЗ в первую очередь должно отвечать на их вопросы. В идеале вся предпроектная документация в каскадном методе создается так, чтобы снять вопросы в процессе разработки.
Итак, на какие вопросы отвечает ТЗ.
Для кого создается сайт и для чего?
Сайт создается для Заказчика и для его клиентов. Это основанные пользователи будущего проекта.
Наилучшим вариантом будет, если в Техническом задании вы опишите всех пользователей сайта, как внутренних, так и внешних. Это описание может включать в себя маркетинговые, демографические, социальные данные, цели и задачи потенциальных пользователей, их требования к будущему сайту.
Как будут решены задачи заказчика и пользователей?
Собственно если не ответить на этот вопрос, то написание ТЗ можно признать бумагомарательством. Это основной и значимый вопрос. Ему может быть посвящена отдельная статья, поэтому останавливаться на нем подробном пока не будем.
Как будет проходить создание проекта?
Как я уже писал выше, ТЗ (а может и отдельный документ) иногда описывает процесс разработки проекта. Это совершенно необходимо, если принять во внимание, что сайт может разрабатываться по отличной от принятой в компании методики разработки, которая как правило не описывается ни одним документом. Можно сколько угодно долго мучить себя мечтами о стандартизации по ISO, но что показать дотошному заказчику?
По ГОСТу предусмотрен отдельный раздел «Этапы разработки системы». В таком разделе можно не слишком подробно описать процесс и установить майлстоуны.
Что будет приниматься на выходе?
ТЗ начинает разработку и ставит в ней точку.
В идеале вы должны пройтись по всем пунктам ТЗ вместе с заказчиком, свериться с полученной системой и спустя неделю сказать: «Уф-ф. Вроде все сделали».
«ТЗ является средством верификации выполненных работ.» — такая фраза записана во введении многих моих ТЗ.
Что требуется для дальнейшего запуска проекта?
Это вопрос, на который по-хорошему должен получить ответ заказчик. Это уже консалтинг, но в части случаев его необходимо провести в процессе проектирования. Необходимо спланировать количество рабочих мест, требуемое программное и аппаратное обеспечение и т.п.
Из чего состоит ТЗ
У меня ушел целый час на принятие решения: описывать состав ТЗ в виде конкретной четкой структуры или просто рассказать о том, что должно там быть. Вспомнив все свои ТЗ, я пришел к выводу, что структура этого документа так часто менялась в зависимости от целого ряда факторов, что четкое указание структуры будет напоминать плохой совет по выбору костюма. Представьте, что вам советуют что-то надеть на вечер, даже не осведомившись, куда вы направляетесь.
Общая информация
Первая часть ТЗ содержит введение и общую информацию о документе и проекте в целом. Введение надо написать один раз и на всю жизнь. Как правило, там пишутся настолько абстрактные фразы, что в каждом новом проекте надо лишь подправить пару слов.
Общая информация включает в себя:
- Информацию о заказчике и исполнителе.
Обязательно указание ответственных лиц с каждой стороны. Указываются документы, на основании которых производится разработка. Как правило, подобным документом является договор. Статус текущего документа и конфиденциальность. - Назначение проекта.
Указывается: для чего будет использоваться полученный продукт. - Цели создания и задачи, которые должен решить ресурс.
С одной стороны это довольно короткий раздел, но по важности проработки он занимает первое место. Если цели и задачи поставлены нечетко и неизмеримо, то может быть довольно сложно им следовать. - Описание аудитории проекта.
Критично важная информация для разработки хороших и правильных сайтов. Ясно, что информацию об аудитории не только надо правильно собирать, но еще важнее это уметь этой информацией пользоваться.
Описание аудитории должно содержать не только информацию, которую так любят маркетологи (демография, потребности, сегментирование и т.п.), но также информация, которая пригодится дизайнерам и проектировщикам: какие задачи решает пользователь, какие его цели в работе с сайтом, что его привлекает. Алан Купер рекомендует описывать аудиторию сайта не в виде безликой массы, а выделять персонажи — описывать собирательный образ конкретных людей. - Термины и определения.
В большом документе вы сможете употребить огромное количество терминов и сленговых выражений, которые редко понимают специалисты по маркетингу или крупные руководители. Они могут читать этот документ, поэтому лучше предусмотреть для них список определений. Я не тешу себя надеждой, что этот список хоть раз в жизни был прочтен, но зато я могу всегда сослаться на него.
Вводная общая часть документа содержит информацию о том, с чего мы начинали при проектировании. Конечно, в процессе анкетирования специалистов заказчика информации накапливается на порядок больше, но читать ее никому не интересно.
Эта информация собирается в рамки проекта.
Рамки проекта
Если подальше отойти от своего дома и, обернувшись, взглянуть на него, то издали вы не сможете различить детали строения. Вы можете подсчитать окна, но не разберете из какого они материала, вы можете любоваться архитектурой («любоваться», конечно, можно не каждым домом), но сможете только догадываться о принципах его строительства, вам не будут видны внутренности квартир или нацарапанное слово на входной двери.
Рамки проекта примерно то же самое. Прочитав эту главу каждый должен представлять, что будет получено в процессе разработки, но абсолютно не вдаваясь в детали. Вы пишите, что на сайте будет работать «регистрация пользователей», но не пишите, как конкретно она будет устроена, или какие поля должен будет заполнить пользователь.
Рамочный уровень проектирования в любом случае проходит любой проект, поэтому записать его будет не лишним. Кроме того, большие шефы как со стороны разработчиков, так и стороны заказчика очень не любят долго читать, но любят быть в курсе всего что происходит. Этот раздел надо написать в том числе и для них.
Рамки проекта пишутся в виде сценариев работы пользователей с сайтом и описывают общую функциональность и интеракции с интерфейсом.
Информационная архитектура и интерфейс
Раздел посвященный информационной архитектуре (ИА) сайтов не стандартизируется ни одним известным стандартом (автору такие пока не знакомы). Но любой, кто разрабатывал сайты, понимает, что ИА это чуть ли не главное, что нужно знать для разработки сайта. ИА определят как будет выглядеть и работать сайт с пользователями.
Для описания ИА потребуется описывать сверху вниз:
- Структуру сайта. Это так называемые высокоуровневые прототипы.
- Шаблоны страниц. Низкоуровневые прототипы, описывающие непосредственно интерфейс сайта.
- Опись контента. Табличное описание содержания каждой страницы сайта.
Структура сайта
Карта сайта выполняется графическим способом в одной из известных нотаций: Visio или Garrett. Я советую именно рисовать карту сайта, потому как в этом случае полученная структура получается наиболее наглядной и удобной в дальнейшем использовании. С одной стороны может показаться, что в виде списка написать карту сайта будет куда проще, но когда вы сами задумаетесь над связями различных областей сайта между собой, вы волей неволей начнете чиркать квадратики на бумаге.
О том, как можно рисовать структуру сайта с помощью нотаций, используя Visio, написаны целые статьи, поэтому останавливаться на этом не будем. Статьи написаны, правда, на английском, но вы легко сможете воспользоваться ими.
Не забывайте присваивать номер каждой отдельной странице карты сайта. Это потребуется на этапе описания контента.
Полезные советы при рисовании карты сайта:
- Не жалейте места. Старайтесь располагать блоки так, чтобы они были отделены друг от друга. Это поможет читабельности карты.
- Не мельчите. Прочитать текст, напечатанный 4 кеглем, в принципе можно, но это уже причина для ненависти.
- Выравнивайте «квадратики» страниц относительно друг друга, выстраивая в линии. Это улучшит восприятие уровней вложенности страниц.
- Не пересекайте линии. Старайтесь избегать большого количества пересечений линий связей. Если они пересекаются, то должны «перескакивать» одна над другой. Кто занимался черчением функциональных схем в университете, меня поймет.
- Подписывайте карту. Подпишите саму карту, а также отдельные блоки. Это позволит меньше путаться в дальнейшем.
- Почаще сохраняйте файл. Банально, но надо просто помнить об этом. Не стоит лишний раз вспоминать родственников разработчиков программы Visio, в сущности, они ни в чем не виноваты.
Шаблоны страниц
На уровне карты сайта каждая страница представляет для нас только «квадратик» на листе бумаги. Для дизайнера, верстальщика и программиста этого недостаточно, чтобы разработать сайт. Надо еще знать наличие и расположение блоков информации и функций на страницах сайта. Поэтому мы переходим к шаблонам сайта. В идеале каждый квадратик должен быть детализирован до схемы каждой отдельной страницы. Это прототипирование сайта. Использование прототипирования зависит от принятой схемы работы в компании-разработчике, но стоит признать, что это становится для заказчика крайне недешево.
Для упрощения выделяют ряд шаблонов интерфейса сайта, которые описываются вслед за картой сайта.
Описание шаблонов состоит из 3х частей:
- Перечень шаблонов. Выявляются основные типы страниц и описывается их использование.
- Типовой шаблон. Основные блоки. Описываются основные блоки страниц с целью уменьшить повторяемость информации.
- Описание каждого шаблона согласно перечня. Шаблоны отрисовываются в любом графическом пакете (Adobe Illustrator, Adobe InDesign, MS Visio и др.), а затем дополняются кратким описанием.
Оговорка: шаблоны интерфейса сайта не надо путать с шаблонами в программной системе, на которой будет работать сайт. Шаблоны интерфейса описывают количество типовых страниц, достаточное для дизайна сайта.
Описание контента
Самая долгая и нудная часть работы. Описание контента должно включать в себя перечень всех страниц сайта с точным указанием размещаемого на каждой странице текста, картинок и т.п. Также там указывается какой шаблон используется для данной страницы (см. выше). Я рекомендую использовать для этого таблицу.
Далеко не всегда на момент написания ТЗ можно с уверенностью знать какой будет контент на сайте: точное количество информационных страниц, размещение графической информации, поэтому не думайте, что в данном разделе приводится самое точное описание. Часто это не так. Но если вы опишите требуемый контент на данном этапе, то далее проект-менеджер на его основе сможет составить план поставки контента и оценить объем внесения этой информации на сайт. У клиента же всегда перед глазами будет перечень того, что ему потребуется подготовить и отредактировать.
Хорошее описание контента залог спланированной работы на этапе запуска сайта и внесения информации.
Функционал
Описание функционала сайта в техническом задании один из ключевых разделов. В особенности это касается сайтов с большим процентом программных работ: электронная коммерция, онлайн-сервисы и т.п.
Хороший пример описания функционала дает ГОСТ. Рекомендую держаться стандарта при описании функционала разрабатываемого в рамках сайта программ. Должны быть описаны: общая система, общие функциональности подсистем и модулей, взаимосвязь подсистем и модулей между собой и, наконец, перечисление всех функций модулей с более или менее подробным описанием их работы. Для каждого модуля должны быть расписаны объекты, которые создаются или используются в работе программы.
Можно также описывать структуру базы данных, предварительные алгоритмы работы, но само по себе техническое задание этого не требует. По ГОСТу подобные подробности должны описывать в дальнейших документах: эскизный и технический проекты.
Иногда при разработке крупных сайтов приходится долго посидеть, чтобы описать весь функционал внешней и внутренней части сайта. Некоторые разработчики против такой детализации. Они считают, что функционал надо описывать поверхностно, чтобы «клиенту было понятно». Полная ерунда! По опыту могу сказать, что лишней детализации не бывает. В случае проблем в проекте менеджеры проекта с обоих сторон становятся редкостными буквоедами! Они вычитывают ТЗ вдоль и поперек стараясь доказать свою правоту. Поэтому если функционал в ТЗ прописан общими словами клиент все равно заставит сделать то, что ему надо.
Требования
Отдельный раздел должен быть посвящен требованиям к проекту или проекта к окружению. Требования, которые могут быть описаны в техническом задании на сайт:
- Технические требования к системе;
- Требования к персоналу;
- Требования к надежности;
- Требования к эргономике и технической эстетике;
- Требования к защите информации от НСД;
- Требования по сохранности информации при авариях;
- Требования к видам обеспечения;
- Требования к программным средствам;
- Требования к информационному обеспечению;
- Требования к техническим средствам;
Может быть также ряд специфических требований.
Все требования необходимо четко формулировать и стараться не забыть ничего из аспектов разработки вашего проекта.
Конечно, в небольших проектах нет необходимости прописывать все приведенные выше требования. Так, например, часто персонала в веб-сайте вообще нет, поэтому такие разделы пропускают.
Прочее
В процессе ведения проектов вы можете заметить, что возникают ситуации, выходящие за рамки технического задания. Возможно, вы что-то упустили, или возникла нештатная ситуация, которую вы ранее не могли предусмотреть. Все это поможет вам в дальнейшем развивать документ, привнося в него новую информацию, которая поможет использовать его в коммуникациях с заказчиком и разрешать проблемы.
Что дальше?
ТЗ составлено, подписано и поступило в работу. Что дальше? Заканчивается ли работа с ним на этом этапе? Нет.
Проект далеко не всегда идет по заранее запланированному пути. Мы стараемся что-то улучшить, изменить, часто меняются требования заказчика. Техническое задание это документ, а не скрижали. С изменением требований к проекту должно меняться и техническое задание. Обычно это делается дополнительными документами со списком изменений. Естественно, они составляются только в том случае если это действительно необходимо, на практике встречается редко.
Также вы должны быть готовы, что в процессе глубокого изучения ТЗ всеми участниками разработки в процессе работы над проектом будут найдены ошибки. Количество ошибок в большом документе прямо пропорционально его объему и обратно пропорционально времени, затраченному на его написание. Т.к. времени постоянно не хватает, следует ожидать, что ошибки в ТЗ будут возникать.
В сухом остатке
Эту статью я написал больше года назад. Прошло довольно много времени, а я за это время не написал ни одного большого ТЗ. Но, перечитав представленную информацию, согласился со всем, что здесь написано. Итак хорошее ТЗ на сайт должно содержать в себе:
- Общую информацию о документе и его составителях;
- Цели и задачи сайта;
- Описание пользователей сайта, их цели и задачи;
- Рамки проекта;
- Информационная архитектура (ИА) сайта: карта сайта, шаблоны, описание интерфейса;
- Описание контента сайта;
- Описание функционала сайта;
- Описание процесса и майлстоунов, если требуется;
- Перечень всевозможных требований при разработке сайта и верификации полученной работы.
Надеюсь, что информация будет полезна широкому кругу читателей.
Создание таблиц Excel на PHP
Подразумевается, что у Вас есть элементарные знания Excel, но ничего слишком серьезного. Вам даже не обязательно иметь копию, все приведенные примеры работают так же хорошо и с OpenOffice Calc.
Знакомство с PEAR:: Spreadsheet_Excel_Writer
* Знакомство с PEAR::Spreadsheet_Excel_Writer
* Продолжаем работу: знакомство с API
* Добавлениe форматирования ячеек
* Добавление функции Excel: C1+D1=2!
Подразумевается, что у Вас есть элементарные знания Excel, но ничего слишком серьезного. Вам даже не обязательно иметь копию, все приведенные примеры работают так же хорошо и с OpenOffice Calc.
Знакомство с PEAR:: Spreadsheet_Excel_Writer
Excel — ом пользуются те, кто работает с финансами и деньгами. Иными словами Буxгалтерский департамент, который не заплатил вашу сумму вовремя, использует ее. Сделайте жизнь буxгалетеров легче и они ответят Вам тем же.
Разве не было бы лучше, если бы Вы могли дать Вашим клиентам возможность доступа к загружаемым данным в виде листов Excel? Xорошие новости состоят в том, что Вы это можете сделать при помощи PEAR::Spreadsheet_Excel_Writer.
«Невозможно!» Вы скажете. «Excel использует файловый формат Microsoft. Это сделать невозможно!».
Да, да это возможно. Spreadsheet_Excel_Writer генерирует «реальные вещи», с функциями Excel, форматированием и все остальным. Нет, тут мы не говорим о файлаx разделенных запятыми, или использующиx COM расширения (или любие другие расширения). Написан он при помощи простого PHP, и будет работать под Unix сервером так же хорошо как и на Windows серверах Если быть кратким, то PEAR::Spreadsheet_Excel_Writer, вместе с дополнительными возможностями PEAR::OLE «понимает» формат Microsoft Excel.
Давайте снимем шляпы перед Xavier Noguer, который сделал удивительную работу для внедрения этого в PHP, с помощью Mika Tuupola для Spreadsheet_Excel_Writer.
Сейчас, без дальнейшего шума, и вооруженными полными знаниями управления пакета PEAR, который у Вас должен быть установлен, начнем загрузку библиотек. Откройте Вашу командную строку и введите в нем следующее:
$ pear install Spreadsheet_Excel_Writer
Вот и все. Мы готовы!
Важное замечание: Для примеров в этой статье я использовал PEAR::OLE version 0.5 и PEAR::Spreadsheet_Excel_Writer version 0.7. Предупреждаю, что кое — что может изменится в будущиx версияx.
Продолжаем наш путь. Давайте создадим простой лист данных.
Имя файла: example_1.php
// Внедрение PEAR::Spreadsheet_Excel_Writer
require_once «Spreadsheet/Excel/Writer.php»;
// Создание случая
$xls =& new Spreadsheet_Excel_Writer();
// Отправка HTTP заголовков для сообщения обозревателю о типе вxодимыx //данныx
$xls->send(«test.xls»);
// Добавление листа к файлу, возвращение объекта для добавления данныx
$sheet =& $xls->addWorksheet(‘Binary Count’);
// Пишем несколько цифр
for ( $i=0;$i<11;$i++ ) {
// Использование функции PHP decbin()для преобразования целого числа в //бинарные данные
$sheet->write($i,0,decbin($i));
}
// Конец листа, отправка обозревателю
$xls->close();
?>
Откройте скрипт в Вашем обозревателе, (подразумевается, что он «знаком» с Excel или OpenOffice Calc) и он отобразит лист Excel с номерами от 0 до 10 в бинарном виде.
Сохранение файлов
В этом случае лист создается динамически — ничего не соxраняется на сервере. Если Вы xотите вместо этого создать файл, Вы можете отбросить часть для создания листа который не изменился, для этого просто отправляя конструктору имя файла и путь к нему, и этим избегая необxодимости отправки HTTP заголовков:
Имя файла: example_2.php
// Создался ли лист?
if ( !file_exists(‘sheets/binary.xls’) ) {
// Внедрение PEAR::Spreadsheet_Excel_Writer
require_once «Spreadsheet/Excel/Writer.php»;
// Создание случая, отправка имени файла для создания
$xls =& new Spreadsheet_Excel_Writer(‘sheets/binary.xls’);
//Добавление листа к файлу, возвращение объекта для добавления данныx
$sheet =& $xls->addWorksheet(‘Binary Count’);
// Пишем несколько цифр
for ( $i=0;$i<11;$i++ ) {
// Использование функции PHP decbin()для преобразования целого числа в //бинарные данные
$sheet->write($i,0,decbin($i));
}
// Конец листа, отправка обозревателю
$xls->close();
}
?>
Если Вы используете систему семейства Unix, то не забудьте изменить разрешения к папке в которой Вы xраните листы данных, чтобы PHP смог добавить в ниx данные.
Обзор API
Xорошо, мы разобрались с основными понятиями. Чтобы получить максимум от PEAR::Spreadsheet_Excel_Writer, Вам нужно знать немного больше об API. Документация API, которая доступна на сайте PEAR сейчас устаревшая (она стал намного больше, с теx пор была создана версия документации). Благодаря авторам, которые добавили много документации непосредственно в код, Вы можете создать свою собственную документацию API, если Вы загрузите phpDocumentor и укажете его на папку, которая содержит все исxодные коды Spreadsheet_Excel_Writer.
Основной класс, с которого Вы всегда будете начинать работу — Spreadsheet_Excel_Writer, представляет из себя пункт доступа ко всем остальным классам в библиотеке. Он предоставляет два важныx заводскиx метода (которые определены в родительном классе Spreadsheet_Excel_Writer_Workbook:)
* addWorksheet()- возвращает случай Spreadsheet_Excel_Writer_Worksheet. Большая часть работы выполняется с случай этого класса, давая Вам возможность вписывать данные в ячейки одного листа.
* addFormat()- возвращает случай Spreadsheet_Excel_Writer_Format, который используется для добавления визуального форматирования ячеек.
Библиотека также содержит три другиx класса, которыx Вы должны опосаться, xотя Вам врят ли когда нибудь потребуется иx использовать.
* Spreadsheet_Excel_Writer_Validator делает возможным добавление проверочных правил для ячеек. Сейчас для этого класса не существует документации. Оно как бы является экспериментальным кодом, следовательно я не буду здесь его обсуждать. В основном, он предоставляет возможность проверки данныx введенныx в ячейку конечным пользователем. Более сложные правила проверки могут быть установлены при помощи расширения класса. Класс Spreadsheet_Excel_Writer_Workbook предоставляет метод addValidator() для создания случая проверки, в то время как Spreadsheet_Excel_Writer_Worksheet дает возможность правилам проверки назначиться в ячейки при помощи метода setValidation()
* Spreadsheet_Excel_Writer_Parser, который является Parser — ом для листов данныx Excel, и помогает Вам проверить, является ли функция правильным синтаксисом Excel.
* И наконец — Spreadsheet_Excel_Writer_BIFFwriter — используется для создания Формата Бинарныx Файлов для xранения файлов Excel. Если Вы интересуетесь взломом Excel, то Вам будет интересно изучить что он делает, если же нет, то Вам ни к чему волноваться об этом, так как библиотека полностью скрывает этот класс.
Замешательство нулевого индекса.
Один из методов примечания — Spreadsheet_Excel_Writer_Worksheet::write(), который мы видели в вышеизложенном примере, Вы будете использовать много раз для добавления данныx в ячейки. Этот метод немного запутывающий по ставнению с тем же методом в Excel.
Первым аргументом функции write()является номер строки. Номером первой строки в таблицах PEAR::Spreadsheet_Excel_Writer является 0, а не 1, как принято в Excel.
Вторым аргументом является номер столбца. Теперь, колонки в Excel, идентифицированы буквами алфавита а не числами, так что Вы только должны будете привыкнуть к переводу между двумя. Буква F является 6-ым в алфавите, так что второй аргумент… 5 (конечно!) — крайняя левая колонка — 0 (ноль) в PEAR::Spreadsheet_Excel_Writer, так что Вы должны вычесть, чтобы получить номер колонки.
Третьим аргументом функции write()являются данные, которые нужно вставить в ячейки; также существует четвертый не обязательный аргумент и используется для визуального форматирования ячеек.
Существуют еще множество методов в классе Spreadsheet_Excel_Writer_Worksheet, такие как для «замораживания» или «таяния» частей листа, для форматирования листа в целом для печати и т.д. О ниx я немного расскажу в последующих примераx, но большинство Вы должны будете исследовать самим.
Добавление форматирования ячеек.
Так как насчет более красивыx листов? Мы можем достигнуть этого при помощи PEAR::Spreadsheet_Excel_Writer используя функцию addFormat()для преобразования объекта в Spreadsheet_Excel_Writer_Format. Мы применяем форматирование к этому объекту, используя методы, которые он обеспечивает, затем передаваем его методом write() функции Spreadsheet_Excel_Writer_Worksheet, для добавления форматирования ячейке, которую мы добавили.
Ради примера «Реального Мира», давайте представим, что я xочу дать своим клиентам Интернет магазина phpPetstore.com возможность скачивания чека для купленныx ими вещей в виде Книги (Workbook) содержащей один лист (Worksheet).
Я начинаю свой лист обычным материалом.
require_once «Spreadsheet/Excel/Writer.php»;
// создание книги
$xls =& new Spreadsheet_Excel_Writer();
// создание листа
$cart =& $xls->addWorksheet(‘phpPetstore’);
Далее мы добавим заголовок к листу — сливая некоторые ячейки, для его размещения. Здесь мы получим первое представления того, как делается форматирование:
// какой нибудь текст в роли заголовка листа
$titleText = ‘phpPetstore: Receipt from ‘ . date(‘dS M Y’);
// Создание объекта форматирования
$titleFormat =& $xls->addFormat();
// Определение шрифта — Helvetica работает с OpenOffice calc тоже…
$titleFormat->setFontFamily(‘Helvetica’);
// Определение жирного текста
$titleFormat->setBold();
// Определение размера текста
$titleFormat->setSize(’13’);
// Определение цвета текста
$titleFormat->setColor(‘navy’);
// Определения ширину границы основания в «thick»
$titleFormat->setBottom(2);
// Определение цвета границы основания
$titleFormat->setBottomColor(‘navy’);
// Определения выравнивания в специальное значение
$titleFormat->setAlign(‘merge’);
// Добавление заголовка в верxную левую ячейку листа ,
// отправляя ему строку заголовка а также объект форматирования
$cart->write(0,0,$titleText,$titleFormat);
// Добавление треx пустыx ячеек для сливания
$cart->write(0,1,»,$titleFormat);
$cart->write(0,2,»,$titleFormat);
$cart->write(0,3,»,$titleFormat);
// Высота строки
$cart->setRow(0,30);
// Определение ширины колонки для первых 4 колонок
$cart->setColumn(0,3,15);
Сперва заметьте, что я получил объект форматирования вызвав addFormat() посредством объекта $xls, который представляет текущий лист. Затем я применил к объекту некоторое специфическое форматирование (методы под названием setBold() говорят сами о себе — для более подробной информации смотрите документацию API).
Когда форматирование закончено, я вызываю функцию write() для объекта $cart, для добавления к ячейке, передавая объект как четвертый аргумент.
Единственный нестандартный ход я здесь сделал, это объединение четырех ячеек. Вызывая setAlign(‘merge’) для объекта форматирования (обычно Вы используете для этого ‘left’, ‘right’ или ‘center’), я приказал Spreadsheet_Excel_Writer, что он должен объединить все ячейки к которым относиться это форматирования. Вот почему я создал три пустых ячеек и применил к ним форматирование.
Использование setRow() позволяет мне изменить высоту строки, сделая ее больше, чем установка высоты строки Excel по умолчанию. Этот метод имеет много дополнительных аргументов форматирования, которые позволяют Вам, например, применить объект форматирования к текущей строке. Подобно setColumn() я могу установить ширину столбца и применить к нему дальнейшее форматирование. Разница состоит в том, что setRow() применяется только лишь к одной строке, когда setColumn() применяется ко многим столбцам.
Теперь мне нужны данные для добавления к листу. Чтобы не усложнять пример (добавляя базу данных), я буду использовать индексированный массив ассоциативных массивов, который якобы является результатом отбора SQL.
array( ‘description’=>’Parrot’ ,’price’=>34.0, ‘quantity’=>1),
array( ‘description’=>’Snake’ ,’price’=>16.5, ‘quantity’=>2),
array( ‘description’=>’Mouse’ ,’price’=>1.25, ‘quantity’=>10),
);
«Столбцы в базе данных» являются ключами массива — ‘description’, ‘price’ и ‘quantity’, второе, что мы должны сделать, это добавить заголовки столбцов с дополнительным заголовком ‘Total’, который мы скоро будем использовать:
$colHeadingFormat =& $xls->addFormat();
$colHeadingFormat->setBold();
$colHeadingFormat->setFontFamily(‘Helvetica’);
$colHeadingFormat->setBold();
$colHeadingFormat->setSize(’10’);
$colHeadingFormat->setAlign(‘center’);
// Массив с данными заголовок для столбцов
$colNames = array(‘Item’,’Price($)’,’Quantity’,’Total’);
// Добавление всех заголовок единым вызовом
// оставляем строку пустым для более приятного вида
$cart->writeRow(2,0,$colNames,$colHeadingFormat);
Вы уже видели форматирование. Вы раньше не видели метод writeRow(). Этот метод делает одно и то же, что и write(), но позволяет Вам добавлять массив данных с лева направо, начиная с определенного номера строки или столбца. Этот метод позволяет значительно сократить код программы.
Еще я хочу сделать так, чтобы заголовки столбцов были всегда видны, когда мы прокручиваем страницу. В Excel — e сделать это можно посредством «замораживания» — выбирая блок ячеек, которые будут видны, когда пользователь будет прокручивать лист, позволяя ему видеть заголовки столбцов (в этом случае), которые объясняют что предствалвют эти данные. То же самое возможно в PEAR::Spreadsheet_Excel_Writer:
// 1-ый Аргумент — позиция вертикального обьединения
// 2-ой Аргумент — позиция горизонтального обьединения (0 = нет горизонтального обьединения)
// 3-ий Аргумент — верхняя видимая строка внизу вертикального объединения
// 4-ий Аргумент — левый видимый столбец после горизнотального объединения
$freeze = array(3,0,4,0);
// Заморозить эти ячейки!
$cart->freezePanes($freeze);
Заметьте, что «замораживание» было применено непосредственно объектом $cart, а не посредством объекта форматирования, так как оно было применено к нескольким ячейкам. С другой стороны, форматирование было применено к отдельным ячейкам.
Наконец я прохожу через обьекты в «своей сумке», добавляя данные к листу:
$items = array (
array( ‘description’=>’Parrot’ ,’price’=>34.0, ‘quantity’=>1),
array( ‘description’=>’Snake’ ,’price’=>16.5, ‘quantity’=>2),
array( ‘description’=>’Mouse’ ,’price’=>1.25, ‘quantity’=>10),
);
// Используйте это для отслеживания текущего номера строки
$currentRow = 4;
// Пройдите через данные, добавляя их в лист
foreach ( $items as $item ) {
// Write each item to the sheet
$cart->writeRow($currentRow,0,$item);
$currentRow++;
}
Вот в принцыпе и все. Если Вы новичок ООП в PHP, на первый взгляд это может показаться немного отпугивающим, но Вы могли уже заметить, что все методы очень понятно названы и Вы можете понять их значения только лишь взглянув на них. Идея притяжения одного объекта другим может быть новшевством для Вас, но когда Вы думаете об этом, то кажется, что Вы создаете объект Worksheet вызывая метод addWorksheetSheet() и что Вы добавляете объекты форматирования к ячейке тогда, когда Вы write() (пишете) в Worksheet.
Добавление функции Excel.
Теперь Вы умеете создавать приятные на вид крупноформатные таблицы, но, как любой ас Excel -a скажет, простое отображение данных не так уж и полезно. Жизнь становится интересней когда Вы используете функции Excel для подсчета данных и преобразования их во что нибудь более интересное.
Теперь я не ас Excel — a (и это не руководство по Excel), но ясно, что мой чек должен быть более умным, так что мне нужно добавить некоторые расчеты основанные на данные, которые я уже внес в таблицу. Для каждой строки я хочу отобразить «total item cost» (сумма купленных вещей) — данные содержат цену единицы измерения а также количество купленных изделий:
«total item cost» = «unit price» * «number of items purchased»
Переведя на термины Excel, для получения суммы пятой строки надо написать формулу подобную следующей:
[Cell D5] =PRODUCT(B5:C5)
Для достижения этого с PEAR::Spreadsheet_Excel_Writer, мне всего лишь нужно подправитьть код, который проводит проход через данные:
$currentRow = 4;
// Пройдите через данные, добавляя их в лист
foreach ( $items as $item ) {
// Добавление каждого предмета к листу
$cart->writeRow($currentRow,0,$item);
// Помните, что Excel начинает подсчет строк с #1!
$excelRow = $currentRow + 1;
// Создание строки PHP содержащую формулу
$formula = ‘=PRODUCT(B’ . $excelRow . ‘:C’ . $excelRow .’)’;
// Добавление формулы к строке
$cart->writeFormula($currentRow,3,$formula);
$currentRow++;
}
Добавление формулы не предствляет из себя труда — мы всего лишь воспользуемся методом writeFormula(). Но самое главное то, как я упомянул ранее, —что Excel начинает отсчет строк начиная с единицы, тогда как PEAR::Spreadsheet_Excel_Writer начинает с нуля. Это означает, что при создании функции я должен помнить об этом, в противном случае я буду ссылаться на неправильные ячейки. Вот почему я создал переменную $excelRow, которая из себя представляет $currentRow + 1.Вы можете подумать, что это design flaw on behalf of the authors, но помните, что в PHP, так же как и во многих языках программирования, индексированные массивы начинаются с нулевого индекса.
Теперь мой отображает суммы для каждой строки. Но как насчет того, чтобы сложить все суммы, чтобы посетитель знал о величине той суммы которая будет на чеке их кредитной карточки? Для этого достаточно сложить все суммы и результат отобразить в какой нибудь ячейке.
Терминами Excel, мне нужно использовать функцию SUM(), для сложения всех сумм, которые отображаются в столбце D.
[Grand Total Cell] =SUM(D5:D7)
Для помещения этого в лист, после того как проход через данные окончен, я добавляю следующее:
$startingExcelRow = 5;
// Последняя строка как в Excel
// (которая та же как и currentRow после окончания прохода)
$finalExcelRow = $currentRow;
// Формат Excel для получения суммы всех значений
$gTFormula = ‘=SUM(D’.$startingExcelRow.’:D’.$finalExcelRow.’)’;
// Некоторое дополнительное форматирование для ячеек общей суммы
$gTFormat =& $xls->addFormat();
$gTFormat->setFontFamily(‘Helvetica’);
$gTFormat->setBold();
$gTFormat->setTop(1); // Top border
$gTFormat->setBottom(1); // Bottom border
// Добавление некоторого текста и форматирования
$cart->write($currentRow,2,’Grand Total:’,$gTFormat);
// Добавление формулы общей суммы с форматом
$cart->writeFormula($currentRow,3,$gTFormula,$gTFormat);
Наконец я заканчиваю создание своего чека отправляя лист непосредственно в обозреватель.
$xls->send(«phpPetstore.xls»);
$xls->close();
Вот и все. Лист готов для скачивания.
Создание PDF из PHP
В наше время формат документов PDF приобретает большую популярность. Он был разработан компанией Adobe Systems Incorporated. Как указано в документации, THE ADOBE PORTABLE DOCUMENT FORMAT (PDF) — переносимый формат документов, является «родным» для программных продуктов семейства Adobe Acrobat. Их цель — дать пользователю возможность легко обмениваться электронными документами и просматривать их независимо от той среды, в которой эти документы были созданы.
PDF опирается на графическую модель, позволяющую отображать картинки и текст вне зависимости от установленных на компьютере устройств и разрешения. В документах этого формата присутствуют такие объекты, как гиперссылки и аннотации, что делает их интерактивными.
С другой стороны, web-приложения зачастую нуждаются в отображении динамически составленных документов, таких как отчеты, прайслисты, счета и многое другое. Это позволяет персонализировать приложение и сделать его более мощным по своим функциональным возможностям. Помимо PDF, существуют и другие решения, но этот формат можно назвать одним из самых удачных, так как PDF документ без потери форматирования можно вывести на принтер или конвертировать в HTML или текст.
PHP, как один из самых мощных и популярных современных средств разработки web-приложений, справляется с задачей генерации PDF документов «на лету». Для этого разработано несколько дополнительных инструментов. Не возьмусь перечислить их все, но назову одни из самых известных — библиотеку PDFLib, ClibPDF и PHP класс FPDF.
FPDF — только PHP
Названные в предыдущей главе PDFLib и ClibPDF требуют дополнительной настройки PHP, в то время как класс FPDF является чистым PHP кодом и легко подключается к скриптам командой include() и другими подобными. Скачать класс и ознакомиться с подробной документацией можно на сайте www.fpdf.org. Дополнительным (порой решающим) аргументом в пользу этого решения можно рассматривать его бесплатность для использования как в личных, так и коммерческих целях. Цитата из лицензионного соглашения:
«FPDF is Freeware (it is stated at the beginning of the source file). There is no usage restriction. You may embed it freely in your application (commercial or not), with or without modification».
Разрешается также видоизменять исходный код класса. Никаких ограничений.
Решение проблемы с кириллицей
При создании русскоязычных документов средствами иностранных программных продуктов (библиотек, приложений и прочего) часто возникает проблема правильного отображения кириллических шрифтов. Не всякий зарубежный продукт корректно работает (а то и вовсе не работает) с кириллицей. К счастью, класс FPDF не принадлежит к их числу и легко настраивается на работу с русским языком.
Если быть точным, то сам класс настраивать практически не придется. Проблема может возникнуть с файлами кириллических шрифтов. Оговорюсь, что тестирование класса я проводил на wintel платформе (впрочем, весь приведенный код работал и на коммерческом *nix хостинге). В windows одним из самых основных форматов шрифтов (наряду с PostScript) является TTF (True Type Font). Но для правильной работы наших скриптов необходим и еще один формат файлов — AFM (файл метрики шрифта). Как считается, AFM файлы поставляются вместе с TTF. В своей ОС я AFM файлов не обнаружил.
Здесь нам на помощь приходят полезные утилиты, в частности — ttf2pt1. Одна из задач данной утилиты — сгенерировать метрический файл для True Type или PFB. Другими словами, появляется возможность взять из директории /fonts (ОС Windows) любой .TTF файл шрифта с поддержкой кириллицы и получить для него метрику при помощи нашей волшебной утилиты. Скачать утилиту можно по следующим линкам: http://ttf2pt1.sourceforge.net и http://fpdf.org/fr/dl.php?id=22 (для Windows).
После того, как утилита скачана, ее необходимо запустить из командной строки (в windows Пуск->Выполнить команду cmd). Формат вызова утилиты для нужной нам цели выглядит следующим образом:
К примеру, если вы положили скачанный экземпляр ttf2pt1 прямо на диск C: , а файл шрифта times.ttf в C:CyrFonts, то вам будет необходимо запустить следующую команду:
где c:ttf2pt1 — вызов программы, -A — ключ, указывающий на необходимость сформировать файл AFM, c:CyrFontstimes.ttf — это адрес файла True Type шрифта и, наконец, times — это имя будущего метрического файла. Итак, AFM файл готов.
Следующим шагом является генерация файла описания шрифта. Этот файл будет иметь знакомое нам расширение — PHP. Вместе с классом FPDF поставляется полезный скрипт для решения этой задачи. Его можно найти в директории font/makefont/ класса. Использовать его просто. Для этого создадим РНР файл (скажем, mf.php) и в нем укажем:
require(‘font/makefont/makefont.php’);
MakeFont(‘times.ttf’,times.afm’,’cp1251′);
?>
Используя require, мы подключаем нужный скрипт. Понятно, что для этого рядом с нашим файлом должна быть папка font, содержащая в себе makefont/makefont.php. А вот функция MakeFont() уже является специфической и по определению имеет следующий формат:
где fontfile — путь к TTF или PFB файлу, afmfile — путь к AFM файлу, enc — имя используемой кодировки (по умолчанию это cp1252), patch — опциональное изменение кодировки и type — тип шрифта (по умолчанию True Type). Для выбора кодировки можно воспользоваться следующим списком:
* cp1250 (Central Europe)
* cp1251 (Cyrillic)
* cp1252 (Western Europe)
* cp1253 (Greek)
* cp1257 (Baltic)
* ISO-8859-1 (Western Europe)
* ISO-8859-2 (Central Europe)
* ISO-8859-4 (Baltic)
* ISO-8859-4 (Cyrillic)
* ISO-8859-7 (Greek)
* ISO-8859-15 (Western Europe)
* ISO-8859-16 (Central Europe)
* KOI8-R (Cyrillic)
Кодировка определяет связь между кодом (от 0 до 255) и символом. Для выбора кириллической кодировки в Windows используйте cp1251. Обычно кодировки с префиксом cp используются в Windows, в то время как Linux системы используют ISO.
Составленный нами скрипт mf.php необходимо открыть в браузере. Он подготовит для наших нужд необходимый файл с расширением php. Итак, что мы имеем? У нас теперь есть комплект из трех файлов шрифта — times.ttf, times.afm и times.php. Важно два из них (times.ttf и times.php) положить в нужное место. Этим местом является директория font, находящаяся в папке класса. Впрочем, вы вольны сами указать место директории, которая будет хранить шрифты. Для этого нужно определить константу FPDF_FONTPATH обыкновенным для PHP способом:
define(‘FPDF_FONTPATH’,’font/’);
Теперь наша система готова к разработке web приложения с динамической генерацией русскоязычного PDF документа.
Начинаем работу
Для наглядного иллюстрирования возможностей FPDF класса попробуем создать реальный документ — прайс-лист фирмы, занимающейся оптово-розничной продажей алкогольных напитков. Краткое техническое задание следующее:
* в шапке документа должны быть данные: логотип, наименование фирмы, заголовок документа;
* в теле документа должны быть приведены данные по товарным позициям, включающие наименование товара, розничную цену и оптовую цену;
Сразу разобьем нашу работу на три этапа. Первый этап — вывод статической информации. Для простоты примера к статической информации мы отнесем все, кроме данных по товарным позициям. На втором этапе уделим внимание табличному выводу товарных позиций в теле документа. Уточним, что в этой статье мы рассмотрим загрузку данных из файла CSV, где разделителем является точка с запятой. Я остановился на этом решении по одной причине — такой файл легко получить из формата xls и, одновременно, с ним легко работать из РНР приложения в других целях (например, организовать вывод в HTML). На третьем этапе мы рассмотрим доставку PDF файла конечному пользователю.
Приступим к практическому знакомству с классом FPDF. Для начала создадим файл price.php, который будет осуществлять вывод PDF документа прямо в браузер (остальные способы мы рассмотрим в главе 6). Рядом с этим рабочим файлом положим скачанный ранее fpdf.php (файл класса) и папку font с вложенными в нее файлами кириллических шрифтов (см. предыдущую главу). Теперь в файле price.php подключим класс FPDF и установим путь к папке шрифтов.
define(‘FPDF_FONTPATH’,’font/’);
require(‘fpdf.php’);
?>
Необходимо уточнить, что тэг <?php должен стоять на самой первой строке файла, так как в последствии мы будем самостоятельно отправлять заголовки (headers), и пустая строка, текст или разметка HTML в начале файла могут нам помешать.
Для вывода статической информации (логотип, название фирмы, название документа) мы будем использовать следующие методы класса FPDF: cell() и image(). Метод cell() выводит ячейку (прямоугольную фигуру) с опциональной установкой границы, цветовой заливкой и строкой текста. Формат записи метода следующий:
Cell(float w [, float h [, string txt [, mixed border [, int ln [, string align [, int fill [, mixed link]]]]]]])
Метод image() отвечает за вывод графического изображения JPG или PNG. Формат вызова метода следующий:
Image(string file, float x, float y, float w [, float h [, string type [, mixed link]]])
Конечно, перед тем, как воспользоваться методами класса, сначала необходимо создать экземпляр этого класса. Приведем наш файл к следующему виду:
define(‘FPDF_FONTPATH’,’font/’);
require(‘fpdf.php’);
//Создадим экземпляр класса
$price = new FPDF();
$price->Open();
?>
После создания экземпляра класса нам будет необходимо указать используемые шрифты. Так как кириллический Times New Roman (рассмотренный в предыдущей главе) не является в классе FPDF шрифтом, установленным по умолчанию, сначала придется его «показать» скрипту. Это мы сделаем при помощи метода AddFont().
define(‘FPDF_FONTPATH’,’font/’);
require(‘fpdf.php’);
//Создадим экземпляр класса
$price = new FPDF();
$price->Open();
//Подключаем кириллический шрифт
$price-> AddFont(‘TimesNewRomanPSMT’,»,’times.php’);
$price-> SetFont(‘TimesNewRomanPSMT’,»,12);
?>
Первым аргументом функции мы указываем наименование шрифта. Его можно посмотреть в сгенерированном РНР файле (значение переменной $name). Второй аргумент — форматирование текста (B — Bold, I — Italic и смешанный BI или IB). Если аргумент пустой, то шрифт обычный. Для использования B и I необходимо также подключить соответствующие типы шрифтов (для Times New Roman это могут быть файлы timesI.ttf и timesBd.ttf). Третий аргумент — РНР файл описания (его мы сгенерировали в предыдущей главе). Теперь шрифт можно применять в данном документе. Для использования на странице установим его размер методом SetFont(). Этот метод можно вызывать несколько раз в одном скрипте, в то время как добавление AddFont() делается один раз для каждого шрифта. Формат записи SetFont() следующий:
SetFont(string family [, string style [, float size]])
Наконец-то можно сформировать содержимое страницы. На этом этапе мы столкнемся с увеличением количества кода, и поэтому, во избежание путаницы, расширим класс FPDF своими методами. Конечно, нет необходимости вносить изменения в сам FPDF класс. Мы напишем свой price.class.php, наследуемый от FPDF.
Листинг 1
class Price extends FPDF {
function PrintTitle($title,$image,$company) {
//Выводим логотип
$this->Image($image,6,6,40,20);
//Устанавливаем шрифт для наименования компании
$this->SetFont(‘TimesNewRomanPSMT’,»,20);
//Выводим наименование компании
$this->Cell(210,4,$company,0,0,’C’);
//Переходим на следующую строку
$this->Ln();
//Переходим на следующую строку
$this->Ln();
//Делаем отступ от левого края (рисуя прозрачную ячейку)
$this->Cell(37);
//Устанавливаем цвет заливки следующих ячеек (R,G,B)
$this->SetFillColor(209,204,244);
//Устанавливаем шрифт для наименования документа
$this->SetFont(‘TimesNewRomanPSMT’,»,12);
//Выводим наименование документа
$this->Cell(150,8,$title,0,0,’C’,1);
//Переходим на следующую строку
$this->Ln();
}
}
?>
Листинг 2
define(‘FPDF_FONTPATH’,’font/’);
require(‘fpdf.php’);
require(‘price.class.php’);
$price = new Price();
$price->Open();
$price->AddFont(‘TimesNewRomanPSMT’,»,’times.php’);
//Добавляем страничку в документ
$price->AddPage();
//Выводим заголовок, используя написанный нами метод в файле класса //price.class.php
$price->PrintTitle(‘Прайс-лист’,’logo.jpg’,’Компания «ALKO SELL»‘);
//Выводим документ в браузер
$price->Output();
?>
В этом файле мы столкнулись еще с несколькими методами класса FPDF. Необходимо заметить, что документ сначала создается в буфере и лишь потом, при вызове метода Output(), выводится в браузер. Поэтому общая схема работы с документом следующая: создаем в буфере документ методом Open(), затем для работы добавляем в этот документ страничку методом AddPage(), формируем содержимое документа различными методами типа Cell() и, наконец, выводим его из буфера в браузер. Если у вас установлен adobe acrobat версии не ниже 5.0, то при запуске price.php в браузере должен открыться документ price.pdf (в Internet Explorer) или сформируется документ doc.pdf для скачивания (в Opera).
Этот документ пока не представляет собой практической ценности, однако на его примере мы разобрали основы вывода статических данных в документ .PDF.
Подключаем источник данных
Перейдем к самому интересному — динамическому формированию содержимого документа. Именно этой возможностью и ценен для РНР разработчика класс FPDF. Я уже говорил выше, что здесь мы рассмотрим вариант получения данных из CSV файла.
Как указано в нашем коротком техническом задании, тело прайс-листа должно состоять из трех граф: наименование товара, розничная цена и оптовая цена. Соответственно, подготовим и файл данных следующего вида:
Пиво «Балтика»;15.00;13.45
Пиво «Оболонь»;14.00;12.30
Водка «Nemiroff», 1 л.;100.00;89.45
Сохраним его как price.csv. Конечно, в реальном прайс-листе товарных позиций и граф будет больше.
Возможны так же деления по группам товаров (например «пиво», «водка», «вино»), но в данном конкретном примере попробуем рассмотреть упрощенную версию (количество записей можно увеличить).
Перед нами встает необходимость получить данные динамически и представить их в виде обыкновенной таблицы в три колонки, с заголовками колонок (столбцов). Перед созданием экземпляра объекта Price добавим инициализацию массива заголовков (соберем все заголовки в массив):
Далее нам понадобится еще больше расширить класс Price (унаследованный от класса FPDF) методами LoadData() и ImprovedTable(). Первый метод должен будет извлекать данные из CSV файла в массив $data, а второй метод пригодится для отрисовки таблицы с данными из этого массива. Рассмотрим метод LoadData() для класса Price.
//Получаем данные в массив строк
$lines=file($file);
$data=array();
//Разделяем столбцы каждой строки по точке с запятой.
foreach($lines as $line)
$data[]=explode(‘;’,chop($line));
//Возвращаем массив с данными
return $data;
}
Вставим этот код в файл класса price.class.php. Теперь перейдем к рассмотрению метода ImprovedTable().
Вот его код:
//Указываем ширину столбцов
$w=array(100,40,40);
//Выводим заголовки столбцов
for($i=0;$i<count($header);$i++)
$this->Cell($w[$i],7,$header[$i],1,0,’C’);
$this->Ln();
//Выводим данные
//Сначала установим шрифт для данных
$this-> SetFont(‘TimesNewRomanPSMT’,»,8);
foreach($data as $row)
{
/*Первый параметр Cell() — ширина столбца, указанная ранее в массиве $w, второй параметр — высота столбца, третий параметр — строка для вывода, LRBT — означает прорисовку границ со всех сторон ячейки (Left, Right, Bottom, Top). Можно также указать выравнивание в ячейке по правому краю (‘R’) */
//Рисуем ячейку наименования товара
$this->Cell($w[0],6,$row[0],’LRBT’);
//Рисуем ячейку розничной цены
$this-> Cell($w[1],6,number_format($row[1]),’LRBT’,0,’R’);
//Рисуем ячейку оптовой цены
$this-> Cell($w[2],6,number_format($row[2]),’LRBT’,0,’R’);
//Переходим на следующую строку
$this->Ln();
}
//Closure line
$this->Cell(array_sum($w),0,»,’T’);
}
Вставим и этот метод в код класса Price. Теперь, когда мы обросли двумя новыми методами, попробуем их применить. Изменим код нашего главного файла (листинг 3).
Можно смотреть на промежуточный результат. Это практически все, чего мы хотели достичь.
Добавим только небольшую деталь — номера страниц с указанием их общего числа в нижней части каждой страницы. Ведь наш источник данных может состоять не из трех записей, а, например, из ста.
Для этого необходимо организовать вывод «подвала» (footer) на каждой странице. С этой целью напишем метод Footer() нашего класса Price. Следует отметить, что методы Footer() и Header() заранее прописаны в классе FPDF и вызываются автоматически при выполнении метода AddPage() и Close().
По умолчанию они пустые, но их можно определить в своих наследуемых классах, при этом ни Footer() ни Header() не потребуется явно вызывать из приложения. Добавим в класс Price() следующий код метода:
//Позиционирование в 1.5 см от нижней границы
$this->SetY(-15);
//TimesNewRomanPSMT italic 8
$this->SetFont(‘TimesNewRomanPSMT’,»,8);
//Номер страницы
$this->Cell(0,10,’Страница ‘.$this->PageNo().’/{nb}’,0,0,’C’);
}
Листинг 3
define(‘FPDF_FONTPATH’,’font/’);
require(‘fpdf.php’);
require(‘price.class.php’);
$header = array(«Наименование товара»,»Розн. цена»,»Опт. цена»);
$price=new Price();
$price->Open();
//Получим массив данных из файла в $data
$data = $price->LoadData(«price.csv»);
$price->AddFont(‘TimesNewRomanPSMT’,»,’times.php’);
$price->AddPage();
$price->SetFont(‘TimesNewRomanPSMT’,»,12);
$price->PrintTitle(‘Прайс-лист’,’logo.jpg’,’Компания «ALKO SELL»‘);
//Нарисуем таблицу. Аргументами метода являются массив наименований
// столбцов и массив данных из файла price.csv
$price->ImprovedTable($header,$data);
$price->Output();
?>
Теперь этот метод будет автоматически исполняться при вызове метода AddPage(). Для корректной работы необходим последний штрих — вызов из файла приложения (price.php) метода $price->AliasNbPages() перед $price->AddPage().
AliasNbPages([string alias])
При написании метода Footer() мы использовали также PageNo(), метод, возвращающий номер текущей страницы и параметр {nb}, который по умолчанию будет заменен цифрой общего количества страниц в текущем документе. Документ готов, и перед нами встает необходимость его вывода в браузер.
Вывод в браузер
По идее, существует всего два варианта вывода документа в браузер — открытие (если установлен adobe acrobat) и скачивание без непосредственного открытия. В классе FPDF выводом документа в браузер управляет метод Output(). В нашем примере мы использовали этот метод без дополнительных аргументов. Однако документация к FPDF приводит следующий формат его записи:
Output([string file [, boolean download]])
Метод предназначен для сохранения PDF документа в локальный файл или для непосредственного вывода в браузер (если установлена программа просмотра PDF файлов).
Аргумент file означает имя файла. Если таковое отсутствует, то производится попытка открыть документ в окне браузера. Если аргумент file определен, то аргумент download указывает, что файл должен быть сохранен на сервере (значение false) или у пользователя (при установке true выводится диалог «Сохранить как»).
Соответственно, можно выделить три варианта написания метода Output() для нашего документа. Первый — Output() — пытается открыть документ в окне браузера. Второй вариант написания выведет у пользователя диалоговое окно «Сохранить как» и предложит скачать документ на его диск — Output(«AlkoPrice.pdf», true). И, наконец, третий вариант просто сохранит документ на локальном для скрипта сервере — Output(«AlkoPrice.pdf»,false) или просто Output(«AlkoPrice.pdf»), так как по умолчанию атрибут download всегда имеет значение false.
Стоит отдельно рассмотреть компрессию полученного файла. По умолчанию будет произведена попытка его «ужать» средствами Zlib. Это расширение (extension) должно быть установлено в системе. Если установка не была произведена, то документ получится не сжатым, и будет весить немного больше.
WordPress как ERP ??!
Как известно информация правит миром, бизнесом, расписанием авиарейсов и даже сигналами светофоров. Имея какую-то информацию важно вовремя довести ее до заинтересованного лица. И не важно — будь то биржевые котировки, новые цены поставщика или новости с соседнего отдела — любая информация не будь спамом представляет конечную стоимость.
Зачастую компании разрабатывают сложные ERP системы, для глубокой интеграции информации в повседневные операции всех сотрудников компании. Но цена таких решение достигает сотен и даже миллионов долларов.
Сегодня я расскажу решение для мелкого и среднего уровня бизнеса, которое по себестоимости будет в сотни раз дешевле любой ЕRP, а по приносимой прибыли сможет сравняться с подобной системой.
Итак давайте сначала обрисуем список целей и требований для нашей системы:
- Новостная информация по компании. Что, где происходит, каких успехов достигли, кто больше всего отличился.
- Оперативная информация с полев боя вашего бизнеса. Кто, где, когда.
- Информация о ресурсах, в случае если бизнес информационный — важно знать компетенции каждого из сотрудников
- Было бы не плохо иметь единую точку авторизации, например Microsoft Active Directory т.е. один логин для всех систем
- Общий доступ к документообороту, файлам, шаблонам документов и т.д.
- Стандартные новости в виде блогов. Более того можно подписать всех сотрудников через RSS (сейчас куча RSS читалок)
- Имея несколько блогов их можно объединить кросс-постами. Таким образом всегда будет связь с дальних тылов
- Каждый сотрудник может вести свой блог, таким образом просто по меткам мы можем отобрать всех пользователей допустим со знаниями технологии XSLT. А по постам в блоге понять даже глубину их знаний
- Уже разработано куча плагинов для WP которые могут без проблем авторизовать пользователей в различных системах.
- Так же можно с помощью плагинов прикреплять документы, шаблоны к различным постам, что намного упростит доступность и поиск информации.
Средства удовлетворения заказчика
Все люди делятся на 2 роли, заказчики и исполнители. И роли эти зачастую меняются. Будучи по одну сторону прилавка магазина мы являемся заказчиками (покупателями), но стоит нам перелезть через прилавок — как мы становимся исполнителями.
В свою очередь заказчики делятся на подкованых в области ИТ, и на абсолютно подкованных. Оба эти типа имеют свои приемущества, а о недостатках мы говорить не будем ибо любой заказчик должен расцениваться исключительно с положительной стороны.
Итак условия задачи:
Создать сайт, такой который бы соответствовал всем страндартам, всем требованиям заказчика, приносил прибыль и удовлетворение.
Дано: заказчик — 1 шт.
Необходимый результат: удовлетворенный заказчик — 1 шт.
Первый шаг
Для начала необходимо узнать, что же в итоге хочет получить заказчик. Для этого советую использовать опросник, который будет мягко вести заказчика от того что у него есть к тому что он хочет. Не надо использовать технические понятия или сгруппированные вопросы. Пускай будет больше но легче.
Неверный вопрос заказчику: Необходимо ли вам в поректе древовидная структура наследования объектов.
Верный вопрос заказчику: Будет ли у вас каталог со вложенными разделами ?
Важно уже чтоб на этом этапе заказчик увидел в Вас заботу. Пройдите вместе все вопросы — подскажите что где именно лучше заполнять. Ни в коем случае не отсылайте ему такой опросник на емэйл с коментариями — «заполните, нам это надо.»
Если это надо на самом деле Вам — позаботьтесь самостоятельно об том чтоб заказчик заполнил его.
Далее важный момент — ТЗ. Не так давно я уже писал о его необходимости. Оно необходимо — и это аксиома!
Планирование работ:
Используйте в своей работы инструменты планирования работы с возможностью просмотра стадий, контрольных точек. Даже если вы уверенны что заказчик этим не будет пользоваться, а вы и так гений планирования и все планы готовы предоставить на post-it листочках — не стоит этого делать. Вы профессионал, и надо работать профессионально. Инструменты планирования проектов намного упрощают работу в проекте. А лишняя информативность заказчика никогда не помешает.
В интернете бесконечное множество готовых решений для этих целей — выбирите и установите ту, которая больше всего вам подходит.
Контрольные стадии проекта
Как и в любом производстве — у вас должны быть определены контрольные точки сдачи проекта. Особенно актуально для больших проектов, которые делаются в несколько этапов. Определите сроки и то что вы будете показывать и строго следуйте им. Для небольшого проекта можно оговорить следующие контрольные точки:
- сдача дизайна
- сдача верстки
- сдача модуля ХХХ (новости, каталог)
Презентация конечного продукта
Сделав проект — не поленитесь сделать презентацию к нему — расскажите заказчику какой титанический объем работ вы выполнили. Включите в презентацию рассказ о больших событиях в проекте (освоили новый подход к решению тривиальной задачи) — пускай он даже ничего не поймет, но ему будет приятно что заплатив за сайт он получил множество всего.
Сдал — забыл ??
Многие студии так и поступают, и происходит это в первую очередь из за отсутствия интереса к продукту со стороны самого заказчика. Сайт расценивается им как что то типа «купил и забыл». Не поленитесь потревожить заказчика звонками раз в месяц по поводу сайта. Все ли им понятно, все ли хорошо, может они еще что то хотят.
Несколько бесплатных советов
Предоплата — ничто не добавляет уверенности в заказчике как предоплата 🙂 Но если заказчик старый и проверенный друг — думаю вы уже доверяете друг другу.
Передача исходных кодов — весьма спорный вопрос. Впринципе заказчик заплатил за проект и может расччитывать на обладанием прав на исходный код. Нет никакого смысла его кодировать (Zend Encoder..) т.к. это просто НЕ логично.
Макеты сайта нарисованные в фотошопе тоже впринципе могут быть переданы заказчику — он заплатил за них.
Итого
Чтобы получить удовлетворенного заказчика нам надо следовать следующим правилам:
- Заказав сайт заказчик должен получить не только сайт но и заботу.
- Не скупитесь на удобства для заказчика. Отчеты о работе, презениации и системы -все это добавляет вес вам.
- Сдав проект не забывайте о заказчике. Интересуйтесь его делами, пригласите в офис для совместного распития чая
- Постоянно работайте над улучшением качество своего обслуживания. Нет пределу совершенства!
Требования для подготовки контента
На мой взгляд, если Заказчик сам готовит контент для наполнения сайта, лучше всего подготовить для него список необходимых текстовых и графических материалов, а кроме этого выслать требования по их подготовке. Сейчас я попробую перечислить, какие требования могут быть:
1. Тексты на статичные страницы
Необходимо ещё раз повторить структуру сайта (даже если она есть в Концепции), указав, для каких из них какие тексты нужны.
Например, для страницы «Услуги компании» требования могут звучать следующим образом:
Необходимо предоставить список услуг компании с кратким описанием каждой из них, а также подробные тексты о каждой услуге для размещения их на отдельных страницах.
Требования по высылаемым материалам могут выглядеть так:
Текст для каждой страницы должен быть помещён в отдельный текстовый документ. Название документа соответствует названию страницы (по Концепции).
2. Тексты новостей
(аналогично для статей и пресс-релизов)
Надо объяснить Заказчику, что для размещения на сайте новости необходима следующая информация:
- заголовок новости;
- дата публикации;
- имя автора (если это необходимо);
- краткое описание, для вывода его в общем списке новостей
краткое описание должно содержать 2-3 предложения, можно использовать первый абзац полного текста новости; - полный текст новости;
- ссылка на источник (если это необходимо).
Требования по высылаемым материалам:
Вся информация по одной новости должна размещаться в одном текстовом документе. Название документа соответствует дате публикации новости и её заголовку.
3. Фотографии
Если обработка фотографий не входит в стоимость проекта, то нужно указать Заказчику:
- размер фотографий (или несколько размеров, если это требуется по Концепции);
- формат изображений;
- требования по оптимизации изображений под web;
- описания для тех фотографий, которые используются в фотогалерее сайта.
Требования по высылаемым материалам:
Изображения, высылаемые для фотогалереи необходимо разместить в отдельных папках, соответствующих названиям разделов фотогалереи. Внутри каждой папки фотографии должны быть отсортированы в том порядке, в котором они будут размещаться на сайте, фотографии должны иметь названия 01, 02 и т.д. Все описания фотографий должны быть перечислены в общем текстовом документе, в виде:
- 01 — описание 1
- 02 — описание 2 и т.д.
4. Каталог
Что касается каталога, многое зависит от того, чем занимается компания и насколько полный каталог будет представлен на сайте. Могу привести пример того, какая информация для каталога может понадобиться:
- наименование позиции каталога;
- описание позиции каталога;
- раздел и подраздел (если в каталоге выделено несколько разделов и подразделов);
- фотография;
- чертёж;
- фотографии для фотогалереи;
- ширина, высота, вес и т.п.;
- таблица технических характеристик;
- документация для скачивания;
- инструкция по использованию и т.д.
Требования по высылаемым материалам:
Вся информация по одной позиции каталога должна размещаться в одном текстовом документе. Название документа соответствует наименовании позиции каталога. Все текстовые документы необходимо разместить в отдельных папках, соответствующих названиям разделов и подразделов каталога.
5. Сотрудники компании
Информация о сотрудниках компании может использоваться на странице о руководстве или структуре компании. В этом случае будет нужна следующая информация:
- фамилия, имя, отчество;
- занимаемая должность;
- контактный телефон;
- контактный e-mail;
- фотография.
6. Сервисы на сайте
Если на сайте будут предусмотрены онлайновые сервисы, позволяющие общаться посетителям сайта и сотрудникам компании, то понадобится следующий список:
- фамилия, имя, отчество сотрудника;
- его контактный e-mail (на который будут отправляться сообщения от посетителей сайта);
- услуга или вопросы, за которые данный сотрудник является ответственным (например, вопросы по доставке или по техническому обслуживанию).
7. Интекрактивная карта
Это может быть карта дилеров компании, её офисов или клиентов, может быть карта построенных домов или, например, АЗС. В этом случае вся информация для карты должна быть представлена в следующем виде (на примере дилеров, расположенных в разных городах):
- название компании дилера;
- город;
- адрес;
- логотип;
- контактный телефон;
- контактное лицо;
- схема проезда.
Примечание: адрес, логотип, телефон, контактное лицо и схема проезда будут нужны, если на карте предусмотрены окошки с более подробной информацией, которые всплывают при наведении на одного дилера.
Думаю, на этом примеров достаточно. Все остальные уже будут являться частными случаями, подходящими для одного конкретного сайта.
Чего хотят заказчики?
Однажды, когда я только начал доставать до верхнего шкафчика на кухне, я решил сделать себе кофе.
До этого я пробовал кофе, один глоточек (больше мне не разрешали) это было ну очень вкусно. Я видел, что мама кладет в чашку кофе из жестяной банки, которая стоит в верхнем шкафчике.
В один прекрасный день, едва оставшись дома один, я залез в шкафчик и достал заветную банку. «Сделаю кофе повкуснее«, — подумал я и щедро бухнул в чашку две ложки. Хорошенько размешав, я попробовал сделать глоток и тут же выплюнул: кофе получился ужасно горький.
«Мало кофе!«, — подумал я и положил еще две ложки… дальше описывать не буду, понятно, что в результате кофе отправился в раковину.
Заказчики очень хотят получить хороший сайт, в том числе когда предлагают свои варианты достижения этой цели. Именно поэтому не стоит сразу делать все, что они пожелают, иначе результат отправится следом за первой чашкой кофе, которую я приготовил.
Техническое задание на разработку сайта — бюракратия или жизненная необходимость
В начале все работали как работали, но темпы жизни нарастают, приходиться или что то менять в процеессах работ или тешиться «остатками» еды от монстров рынка. Тоже самое и касается web разработки. Многие основатели студий начинали наверняка с «слушай, вот сделай нам по быстрому вот то, то и то…». Потом «быстренько» перерастало в бесконечный труд, трату времени а как следствие и ресурсов, и в результате интересов (как финансовых, так и мотивационных).
По специфике работы зачастую встречаешь клиентов, которые хотят сделать сайт, который приносил бы как минимум удовлетворение (заикнуться о финансовой прибыли просто глупо!) но так, чтоб быть минимально вовлеченным в процесс, ибо не царское это дело.
— «Вот смотрите, мы хотим чтоб было все! Что б все было классно, чтоб было не как у всех, чтоб мы были в первой строчке выдачи всех поисковиков! » — типичные слова 50% заказчиков. Безусловно мы не имеем морального права спорить с заказчиком, ибо он прав по умолчанию, но речь идет именно о взаимных интересах. Веб студия зачастую ничего не знает ни о бизнесе заказчика, ни о его процедурах, его преимуществах перед конкурентами, не тем более о вкусах ответственного за выполнение работы со стороны заказчика.
Решением данной дилемы служит Техническое задание — обычный документ, описывающий то, что хочет заказчик и в каком виде. С первого взгляда это может показаться лишней бюракратией, излищками «крупного» производства, или пустой тратой времени. Но поработов не один год по обеим вариантам могу заявить что всю мою жизнь можно разделить на два этапа — до того как я писал технические задания для заказчиков и после того. Я полностью убедился что техническое задание — не просто бумажка, не просто бюракратия — инструмент для работы, ровно такой же как клавиатура, мышка и web-сервер.
Как известно заказчик платит именно за время, потраченное на разработку проекта, или работает по fixed price (оговоренная сумма за конечный продукт). ТЗ на 99% процентов закрывает вопросы по оценке проекта (всегда известно что надо делать), всегда служит доказательством того что вы правы то что сделали — заказчик не упрекнет вас в том что вы что то не сделали или сделали не так — т.к. все что вы должно — описано в ТЗ. Да и в любой момент можно найти на возникающие вопросы — как где и что должно быть и работать на сайте.
Со стороны заказчика это является доказательством солидности компании с которой собираетесь завязать отношения, доверить им создание «лица» компании во всемирной паутине; доказательством прозрачности расчетов бюджетов его проектов а так же гарантом того что вы получите то что хотите, и еще одним страховочным парашютов с случае судебных тяжб.
Итак что же должно включать в себя техническое задание?! Вот мое примерное видение того что должно быть оговорено в ТЗ:
1. Наименование предприятия Заказчика Системы и его реквизиты — раздел, дающий общую информацию о предприятии. Контакты и т.д. Зачастую инмеенно отсюда вся информация попадает в раздел Контакты на сайте
2. Назначение проекта — описание функционального предназначения сайта. По функциям сайт может делиться на информационный сайт, портал, магазин, и т.д.
3. Задача проекта — кратко сочинение на тему того, для чего вообще создается сайт — для отмывания денег, для рекламы, для продвижения продукта.
4. Целевая аудитория проекта — несколько слов о том какого вы выидите конечного пользователя — возростная категория, социальный статус и даже цвет кожи могут играть роль
5. Требования к стилистическому и шрифтовому оформлению — всего скорей созрев до сайта у заказчика уже есть так называемый фирменный цвет. Было бы не плохо описать его здесь
6. Требования к графическому дизайну — здесь главное не увлекаться описанием и не начинать вольных сочинений на тему «красненькую точку надо разместить 33 пикселя от правой границы окна браузера…» Общих фраз типа легкий, изящный, тщательно проработаный детальный..
7. Требования к контенту и наполнению — структура сайта — далеко не сам сайт. Самое дорогое далеко не система управления, бизнес логика или дизайн — самое дорогое — тщательно проработаный контент. Опишите ваши требования, кто в каком виде предоставляет материалы
9. Структура сайта — один из ключевых разделов. Здесь описывается структура сайта, в виде разделов, их описаний и данных, которые будут представленны на этих страницах
10. Приложения к заданию — собственно говоря наша смета. Смета должна покрывать те пункты, которые описаны в задании. Если это пункт, говорязий что у нас на сайте будет авторизация и регистрация — значит в смете должен быть этот пункт.
Как видите тут нету почти ни слова про дизайн, какой он будет, эскизы и т.д. Почему мы его не включаем — потому что любое производство должно быть мануфактурным, т.е. ответственные за дизайн должны быть дизанеры, а за разработку — разработчики.
Мы отдельно назначаем встречу с дизанером, который описывает свое видение проекта, дискутирует с заказчиком и выдает свои версии на согласование.
Резюме: если вы заказчик — не соглашайтесь начинать работу и какие то отношения с исполнителем не получив от него письменного подтверждения того что получите в результате. Если же вы исполнитель — перестрахуйтесь от двойной, тройной (n-ной) работы и бесконечных переделок с того как я вижу на то как надо — составьте ТЗ и будет взаимное счастье.