Разработка web-сайта о кафе, барах и ресторанах города Челябинска

  • Вид работы:
    Дипломная (ВКР)
  • Предмет:
    Информационное обеспечение, программирование
  • Язык:
    Русский
    ,
    Формат файла:
    MS Word
    2,9 Мб
  • Опубликовано:
    2012-06-05
Вы можете узнать стоимость помощи в написании студенческой работы.
Помощь в написании работы, которую точно примут!

Разработка web-сайта о кафе, барах и ресторанах города Челябинска

Содержание


Содержание        1

ВВЕДЕНИЕ        3

1 ОРГАНИЗАЦИОННО-ТЕХНОЛОГИЧЕСКАЯ ЧАСТЬ          5

1.1 Web-страница        5

1.2 Web-технологии    6

1.2.1 HTML - язык разметки документов        7

1.2.2 CSS - язык описания внешнего вида документа       7

1.2.3 Apache - HTTP-сервер 9

1.2.4 РНР - серверный язык программирования      8

1.2.5 MySQL - система управления базами данных 10

1.3 PHP фреймворки   9

1.3.1 Паттерн MVC     9

1.3.2 Фреймворк CodeIgniter         11

2 Практическая часть  46

2.1 Структура сайта    46

2.1.1 Административная часть      46

2.1.2 Главная страница сайта        47

2.1.3 Страницы со списком заведений конкретной категории    48

2.1.4 Страницы с информацией по конкретному заведению      49

2.2 Модели         51

2.2.1 Модель заведений - Firm      51

2.2.2 Модель категорий - Tag        52

2.2.3 Прочие модели   53

2.3 Контроллеры         53

2.3.1 Контроллер Firms        53

2.3.2 Контроллер Tags         54

2.4 Отображения         54

ЗАКЛЮЧЕНИЕ 55

Литература         56

Приложение A    57

Приложение Б    59

Приложение В    76

Приложении Г    79

ВВЕДЕНИЕ

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

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

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

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

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

Целью данного проекта является создание сайта о кафе, барах и ресторанах города Челябинска.

Для достижения поставленной цели необходимо решить следующие задачи - предоставить возможность пользователям:

быстро и удобно находить интересующие их заведения;

просматривать подробную информацию о заведениях;

оставлять свое мнение о заведениях на сайте;

оценивать данное заведение;

найти местоположение заведения на карте.

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

1 ОРГАНИЗАЦИОННО-ТЕХНОЛОГИЧЕСКАЯ ЧАСТЬ

 

.1 Web-страница

сайт интернет гипертекст язык

Как известно, основной объем информации, доступной в сети Интернет, размещается во всемирной паутине - World Wide Web (WWW) -информационной системе, подобной гигантской библиотеке. В этой библиотеке информация представлена в виде связанных между собой документов, которые называются Web-страницами. Каждая Web-страница может содержать текст, рисунки, видео, звукозаписи, объемные миры и др. Такие страницы могут размещаться на компьютерах в любой части света. При подключении к WWW вы получаете равный доступ к сведениям, разбросанным по всему миру. Собрание страниц, объединенных некоторой общей темой и помещенных, как правило, на одном компьютере, называется Web-сайтом. Web-сайты подобны книгам, а Web-страницы - страницам этих книг. Компьютеры, на которых размещаются сайты, а также, программы, обеспечивающие поддержку сайтов, называются серверами. На одном сервере может размещаться множество Web-сайтов.

Просмотреть любую Web-страницу можно с помощью специальных программ - браузеров, наиболее популярные из которых - Internet Explorer, Opera, Mozilla Firefox, Safari и Google Chrome.страницы могут содержать гипертекстовые ссылки на другие страницы.

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

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

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

Чтобы опубликовать в Интернете документ, содержащий некоторую информацию, достаточно поместить файл с этим документом на сервер, постоянно подключенный к Интернету. Сервер должен уметь общаться с другими серверами с помощью специального протокола передачи гипертекста HTTP - HyperText Transfer Protocol. Множество таких серверов и образует всемирную паутину - World Wide Web.

1.2 Web-технологии

Под Web-технологиями определяют всю совокупность средств для организации WWW (World Wide Web). Поскольку в каждом сеансе взаимодействуют две стороны - сервер и клиент, Web-технологии разделяются на две группы - технологии стороны сервера (server-side) и технологии стороны клиента (client-side).

К технологиям со стороны клиента относятся все технологии создания Web-страниц (HTML, CSS, PHP), а к технологиям со стороны сервера относятся технологии доступа к базам данных в сети Интернет (Apache, PHP, MySQL).

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

 

.2.1 HTML - язык разметки документов

Для подготовки гипертекстовых документов используется язык HTML (Hyper Text Markup Language - язык разметки гипертекстовых документов), предоставляющий широкие возможности по форматированию и структурной разметке документов, организации связей между различными документами, средства включения графической и мультимедийной информации. HTML-документы просматриваются с помощью специальной программы - браузера. Наибольшее распространение в настоящее время получили браузеры Internet Explorer, Opera, Mozilla FireFox, Google Chrome и Safari.является упрощенной версией стандартного общего языка разметки - SGML (Standart Generalised Markup Language), который был утвержден ISO в качестве стандарта еще в 80-х годах. Этот язык предназначен для создания других языков разметки, он определяет допустимый набор тэгов, их атрибуты и внутреннюю структуру документа. Контроль за правильностью использования дескрипторов осуществляется при помощи специального набора правил, называемых DTD-описаниями, которые используются программой клиента при разборе документа. Для каждого класса документов определяется свой набор правил, описывающих грамматику соответствующего языка разметки.

 

.2.2 CSS - язык описания внешнего вида документа

Зачастую у web-дизайнера возникает необходимость применить в процессе создания html-документа сложное форматирование - от абзаца к абзацу менять шрифт, расположение текста, его цвет, формировать различные таблицы данных. Можно решить эту проблему с помощью стандартных средств HTML: описывать каждый абзац отдельным набором команд, но в этом случае итоговый документ будет иметь большой размер, да и само создание кода становится весьма трудоемкой работой. Гораздо лучше пойти другим путем: подключить к странице внешний файл, в котором, с помощью правил языка CSS задать форматирование страницы. Другими словами, файл CSS выполняет роль некоего шаблона, применяемого для форматирования текста, таблиц и иных элементов в документе HTML. Есть возможность подключать один и тот же физический файл CSS к различным web-страницам сайта. CSS можно использовать практически на любом сервере без каких-либо ограничений.

 

.2.3 Apache - HTTP-сервер

Apache - веб-сервер (программа) с открытым исходным кодом. Используется на большинстве современных веб-серверах. Обладает высокой надежностью и расширяемостью. Apache реализует современные протоколы Интернет, такие как HTTP/1.1 - то есть, на его основе можно создавать веб-сайты, и размещать их в интернете.

 

.2.4 РНР - серверный язык программирования

РНР (PHP: Hypertext Preprocessor, ранее Personal Home Page tools) - скриптовый язык программирования общего назначения, используемый, как правило, для придания web-страницам элементов интерактивности. Код, написанный на языке РНР, встраивается в документ HTML подобно подпрограмме: в тот участок документа, где необходимо разместить интерактивный элемент, просто вставляется сценарий РНР. Синтаксис языка сходен с синтаксисом PERL, Java и С, благодаря чему не вызывает каких-либо трудностей при изучении. - один из популярных скриптовых языков (наряду с JSP, Perl и языками, используемыми в ASP.NET) благодаря своей простоте, скорости выполнения, богатой функциональности, кроссплатформенности и распространению исходных кодов на основе лицензии PHP.

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

 

.2.5 MySQL - система управления базами данных

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

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

1.3 CMS

Систе́ма управле́ния содержи́мым (конте́нтом) (англ. <#"551862.files/image001.gif">

На следующей странице Drupal попросит создать файл settings.php в папке /sites/default. Этот файл нужно создать из файла default.settings.php. Нужно именно создать новый файл, а не переименовать существующий. После этого в этой папке должно быть два файла: default.settings.php и settings.php. Нажимаем ссылку обновите страницу в последней строке.


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


Откроется и вскоре исчезнет страница Установка Drupal, во время которой Drupal внесёт изменения в файл settings.php.


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


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


На следующей странице будет проведена установка языка.


На последней странице установки Drupal сообщит о её завершении и предложит войти в аккаунт. Нажмите ссылку войти в свой аккаунт.


Мы окажемся в аккаунте администратора. На странице будет находиться сообщение, которое выводится на первую страницу сайта в том случае, когда нет не одного документа выведенного на первую страницу. Теперь сделайте то, что обычно не делают: прочитайте эту страницу.


После установки удалять файл install.php нет необходимости, т.к. в install.php есть Verify existing settings.php и установка запуститься только в том случае, если файл settings.php содержит записи совпадающие с default.settings.php. Но если вас все-таки смущает наличие этого фала, вы конечно же можете удалить как install.php, так и все файлы с расширением txt: CHANGELOG.txt, COPYRIGHT.txt, INSTALL.txt, INSTALL.mysql.txt, INSTALL.pgsql.txt, LICENSE.txt, MAINTAINERS.txt, UPGRADE.txt.

 

Ход выполнения приложения

Рисунок 1 показывает, в какой последовательности происходит выполнение приложения:

Рисунок 1 - Ход выполнения приложения

Файл index.php выступает в роли фронт-контроллера, он инициализирует подключение остальных частей кода CodeIgniter.

Роутер анализирует HTTP запрос, чтобы определить, что надо сделать с этим адресом.

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

Безопасность. Перед загрузкой контроллера приложения HTTP запрос и любая информация, отправленная пользователем, фильтруется на предмет безопасности.

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

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

URL в CodeIgniter

По умолчанию адреса в CodeIgniter являются дружественными для поисковых систем и понятны для человека. CodeIgniter использует подход, основанный на сегментах адреса:

www.your-site.com/news/article/my_articleсостоит из сегментов, соответствуют архитектуре MVC и, как правило, строятся таким образом:

www.your-site.com/class/function/ID

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

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

В третьем и последующих сегментах описываются переменные, которые будут переданы в эту функцию.

Класс URI и URL хелпер содержат функции, которые упрощают работу с информацией в URI. Кроме того все адреса можно переопределять при помощи Роутинга, что помогает сделать приложение более гибким.

По умолчанию, index.php будет подключаться URL:

www.your-site.com/index.php/news/article/my_article

Чтобы удалить этот файл из запроса, необходимо сделать несколько записей в файле .htaccess. Вот пример файла, в котором будут перенаправлены все запросы, кроме указанных:

RewriteEngine on$1 !^(index\.php|images|robots\.txt)

RewriteRule ^(.*)$ /index.php/$1 [L]

В приведенном выше примере, любой запрос HTTP, помимо запросов к index.php, изображениям и robots.txt, трактуется как запрос к файлу index.php.

В файле config/config.php можно указать суффикс, который будет добавляться ко всем адресам, созданным CodeIgniter. Например, если URL такой:

www.your-site.com/index.php/products/view/shoes ,

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

www.your-site.com/index.php/products/view/shoes.html

Подключение строки запроса.

В некоторых случаях нужно использовать строки запроса в URL:

index.php?c=products&m=view&id=345

CodeIgniter опционально поддерживает эту возможность, которая может быть подключена в файле application/config.php. В конфигурационном файле есть следующие строки:

$config['enable_query_strings'] = FALSE;

$config['controller_trigger'] = 'c';

$config['function_trigger'] = 'm';

Если изменить «enable_query_strings» в положение TRUE, то эта возможность активируется. Контроллеры и функции в них будут доступны при помощи определенных «триггерных» слов:

index.php?c=controller&m=method

Контроллеры

Контроллеры - это сердце приложения. В контроллере определяется, как необходимо реагировать на тот или иной запрос.

Контроллер это простой файл с классом, названным так чтобы ассоциироваться с URI, по которому он будет вызван.

Рассмотрим URI:

www.your-site.com/index.php/blog/

В приведенном примере CodeIgniter попытается найти контроллер с именем blog.php и загрузить его.

Когда имя контроллера будет найдено в первом сегменте URL - он будет загружен.

Для примера создадим простой контроллер, чтобы посмотреть его в действии. Используя текстовый редактор, создаем файл blog.php и вставляем в него следующий код:

<?phpBlog extends Controller {index()

{'Hello World!';

}

}

?>

Затем сохраняем этот файл в директории application/controllers/.

Теперь заходим на сайт, используя примерно такой адрес:

www.your-site.com/index.php/blog/

В итоге на сайте должны увидеть Hello World!.

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

Правильный вариант:

<?phpBlog extends Controller {

}

?>

Неправильный вариант:

<?phpblog extends Controller {

}

?>

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

Функции.

В приведенном выше примере функция называется index(). Функция с названием «index» всегда будет загружаться по умолчанию, если второй сегмент в URL не определен. Еще один способ просмотреть сообщение «Hello World» - обратиться по этому адресу:

www.your-site.com/index.php/blog/index/

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

Для проверки добавим функцию в ранее созданный контроллер:

<?phpBlog extends Controller {index()

{'Hello World!';

}comments()

{'Взгляни сюда!';

}

}

?>

Чтобы посмотреть на работу функции comment, загружаем следующий адрес:

www.your-site.com/index.php/blog/comments/ ,

где можно увидеть новое сообщение «Взгляни сюда!».

Передача сегментов URL функциям.

Если URI содержит более двух сегментов - они будут переданы функции в качестве параметров.

Например, можно вызвать такой адрес:

www.your-site.com/index.php/products/shoes/sandals/123

Функция получит 3 и 4 сегменты в URL («sandals» and «123»):

<?phpProducts extends Controller {shoes($sandals, $id)

{$sandals; $id;

}

}

?>

Следует отметить, если вы используете URI Роутинг, то сегменты адреса, направленные в функцию, будут сегментами route-адреса.

Объявление контроллера по умолчанию.

Можно сказать CodeIgniter, какой контроллер необходимо загружать, если URI не объявлен. Это возникает при запрашивании корня сайта. Чтобы установить контроллер, выполняемый по умолчанию, в файл application/config/routes.php следует установить эту переменную:

$route['default_controller'] = 'Blog';

Где Blog - это имя контроллера, который нужно использовать. При загрузке основного index.php, появится приветственное сообщение «Hello world».

Переадресация вызова функции.

Как было отмечено выше, второй сегмент URI определяет, какая функция должна быть вызвана в этом классе. CodeIgniter позволяет переопределить это поведение при помощи функции _remap():

_remap()

{

// Здесь любой код...

}

Если контроллер содержит функцию _remap(), то она всегда будет определять, какую функцию загружать независимо от того, что написано в URL запросе. Она перекрывает нормальное поведение контроллера, создавая свой локальный роутинг.

В _remap() передается название вызываемой функции, обычно это второй сегмент в URI:

function _remap($method)

{($method == 'some_method')

{

$this->$method();

}

{

$this->default_method();

}

}

Результат обработки.имеет класс вывода, который принимает готовое отображение и отдает его браузеру пользователя. В некоторых случаях может понадобиться пост-обработка сформированного отображения, и выдача ее браузеру самостоятельно. CodeIgniter позволяет добавить в контроллер функцию _output(), которая будет принимать готовые к выдаче данные.

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

Например:

function _output($output)

{

echo $output;

}

Функция _output() будет получать данные в их окончательном состоянии. Бенчмарк и загрузка будут посчитаны, файл будет записан в кеш, все заголовки будут отправлены (при использовании Output Class), и только после этого будет выполнена функция _output(). Если на странице выводится информация о времени выполнения и нагрузке скриптом, то эта информация не будет точной, т.к. в ней учитывается только время исполнения до вызова _output().

Защищенные функции.

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

_utility()

{

// какой-то код

}

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

www.your-site.com/index.php/blog/_utility/

Организация контроллеров в подпапках.

При разработке большого проекта может оказаться вполне удобным деление контроллеров по подпапкам. CodeIgniter позволяет это сделать.

Просто нужно создать внутри папки application/controllers каталог и разместить класс контроллера внутри него.

При использовании этой возможности в первом сегменте URL необходимо указать папку с этим контроллером. Например, контроллер расположен здесь:/controllers/products/shoes.phpдля вызова этого контроллера будет выглядеть так:

www.your-site.com/index.php/products/shoes/123

Каждая из вложенных папок может содержать контроллер по умолчанию, который будет вызван, если URL не содержит название контроллера. Нужно просто назвать его именем по умолчанию, которое указано в файле application/config/routes.php.

Так же вы можете переадресовать контроллеры, используя URI Роутинг.

Конструкторы классов.

Если есть необходимость в каком-либо из контроллеров использовать конструктор, то необходимо разместить в нем следующую строчку:::Controller();

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

Можно отметить, что в PHP 4 конструктор - это просто функция, название которой совпадает с названием класса:

<?phpBlog extends Controller {Blog()

{::Controller();

}

}

?>

В PHP 5 конструктор использует следующий синтаксис:

<?phpBlog extends Controller {

function __construct()

{::Controller();

}

}

?>

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

Отображения

Отображение - это простая веб-страница или ее фрагмент, например шапка, подвал, боковая панель или т.п. Одни отображения могут быть очень гибко встроены в другие отображения.

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

Для ранее описанного контроллера создадим отображение.

Создание отображения.

Используя текстовый редактор, создадим файл с названием blogview.php и вставим в него следующие строки:

<html>

<head>

<title>Мой блог</title>

</head>

<body>

<h1>Добро пожаловать в мой блог!</h1>

</body>

</html>

Затем сохраним этот файл в директории application/views/.

Загрузка отображения.

Чтобы загрузить необходимое отображение, используем эту функцию:

$this->load->view('name');

Где name это имя файла с отображением. Следует отметить, что расширение .php не надо указывать.

Теперь откроем контроллер, ранее названный blog.php и заменим в нем функцию echo на функцию загрузки отображения:

<?phpBlog extends Controller {index()

{

$this->load->view('blogview');

}

}

?>

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

www.your-site.com/index.php/blog/

Загрузка нескольких отображений.правильно обработает несколько вызовов $this->load->view из одного контроллера. Если произойдет более одного вызова, то будут загружены все отображения. Например, можно хранить отдельно отображение шапки, отображение меню, контента и подвала. Это может выглядеть примерно так:

<?php

class Page extends Controller {

function index()

{

$data['page_title'] = 'Your title';

$this->load->view('header');

$this->load->view('menu');

$this->load->view('content', $data);

$this->load->view('footer');

}

}

?>

В приведенном выше примере используется «динамическое добавление данных».

Хранение отображений в подпапках.

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

$this->load->view('имя_папки/имя_файла');

Добавление динамических данных в отображение.

Данные передаются в отображение из контроллера при помощи массива или объекта вторым параметром функции загрузки отображения. Вот пример с использованием массива:

$data = array(

'title' => 'My Title',

'heading' => 'My Heading',

'message' => 'My Message'

);

$this->load->view('blogview', $data);

А сейчас пример с использованием объекта:

$data = new Someclass();

$this->load->view('blogview', $data);

При использовании объекта его переменные будут превращены в массив.

Посмотрим на примере, как работает отображение. Откроем ранее рассмотренный контроллер и добавим следующий код:

<?phpBlog extends Controller {index()

{

$data['title'] = "My Real Title";

$data['heading'] = "My Real Heading";

$this->load->view('blogview', $data);

}

}

?>

Теперь откроем файл с отображением и сменим находящийся там текст на переменные, названия которых соответствуют ключам массива:

<html>

<head>

<title><?php echo $title;?></title>

</head>

<body>

<h1><?php echo $heading;?></h1>

</body>

</html>

Затем загрузим страницу по ранее определенному URL и увидим, что все переменные заменены текстом.

Создание циклов.

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

Например. Добавим эти строки в контроллер:

<?phpBlog extends Controller {index()

{

$data['todo_list'] = array('Clean House', 'Call Mom', 'Run Errands');

$data['title'] = "My Real Title";

$data['heading'] = "My Real Heading";

$this->load->view('blogview', $data);

}

}

?>

Теперь откроем файл с отображением и создадим цикл:

<html>

<head>

<title><?php echo $title;?></title>

</head>

<body>

<h1><?php echo $heading;?></h1>

<h3>My Todo List</h3>

<ul>

<?php foreach($todo_list as $item):?>

<li><?php echo $item;?></li>

<?php endforeach;?>

</ul>

</body>

</html>

В приведенном выше примере используется альтернативный синтаксис PHP.

Модели

Модели используются опционально, если применять более традиционный подход к MVC.

Модели - это PHP классы, создаваемые для работы с информацией из базы данных. Например, предположим, что используем CodeIgniter для ведения блога. В этом случае необходим класс модели с функциями для вставки, обновления и удаления записей, а так же поиска по блогу. Вот пример класса модели, который выполняет некоторые из этих действий:

class Blogmodel extends Model {$title = '';$content = '';$date = '';Blogmodel()

{

// Call the Model constructor::Model();

}get_last_ten_entries()

{

$query = $this->db->get('entries', 10);$query->result();

}

insert_entry()

{

$this->title = $_POST['title'];

$this->content = $_POST['content'];

$this->date = time();

$this->db->insert('entries', $this);

}update_entry()

$this->title = $_POST['title'];

$this->content = $_POST['content'];

$this->date = time();

$this->db->update('entries', $this, array('id' => $_POST['id']));

}

}

Функции, в приведенном выше примере, используют функции работы с базой данных Active Record.

Устройство модели.

Классы моделей хранятся в папке application/models/. Они могут располагаться в подпапках, если необходима такая организация.

Вот основной прототип класса модели:

class Model_name extends Model {Model_name()

{::Model();

}

}

Где Model_name это имя класса. Имена классов должны начинаться с заглавной буквы, в то время как остальные буквы должны быть в нижнем регистре. Следует убедиться, что класс расширяет базовый класс модели.

Имя файла должно соответствовать имени модели, но быть целиком в нижнем регистре. Например, вот класс:

User_model extends Model {User_model()

{

parent::Model();

}

Имя файла должно быть таким:

application/models/user_model.php

Загрузка модели.

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

$this->load->model('Model_name');

Если модель находится в под-папке, то надо указать относительный путь до нее. Например, если модель располагается по адресу application/models/blog/queries.php, то для ее загрузки используем:

$this->load->model('blog/queries');

После загрузки можно получить доступ к модели, используя объект с именем, аналогичным названию модели:

$this->load->model('Model_name');

$this->Model_name->function();

Если нужно обратиться к модели используя не ее, а другое имя, то надо передать временное название в функцию загрузки вторым параметром:

$this->load->model('Model_name', 'fubar');

$this->fubar->function();

Вот пример контроллера, который загружает модель, а потом отображение:

class Blog_controller extends Controller {blog()

{

$this->load->model('Blog');

$data['query'] = $this->Blog->get_last_ten_entries();

$this->load->view('blog', $data);

}

}

Авто-загрузка моделей.

Если некоторая модель нужна на глобальном уровне, то можно сообщить CodeIgniter, что эту модель необходимо загружать при инициализации системы. Это можно сделать, открыв файл application/config/autoload.php и добавив модель в массив автозагрузки.

Соединение с базой данных.

При загрузке модели автоматического подключения к базе не происходит. Доступны следующие варианты подключения к базе данных:

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

Можно передать в функцию загрузки модели третий параметр TRUE (boolean), который сообщит модели о том, что надо сразу подключиться. При этом будут использованы настройки соединения по умолчанию, которые определены в файле с настройками базы данных:

$this->load->model('Model_name', '', TRUE);

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

$config['hostname'] = "localhost";

$config['username'] = "myusername";

$config['password'] = "mypassword";

$config['database'] = "mydatabase";

$config['dbdriver'] = "mysql";

$config['dbprefix'] = "";

$config['pconnect'] = FALSE;

$config['db_debug'] = TRUE;

$this->load->model('Model_name', '', $config);

 

Создание библиотек

Когда мы используем термин «библиотеки», то, как правило, ссылаемся на классы, которые лежат в папке libraries. Однако я хочу рассказать о том, как создавать собственные классы в каталоге application/libraries, чтобы сохранить разделение между локальными ресурсами и глобальными ресурсами фреймворка.позволяет расширять родные классы фреймворка, если просто необходимо добавить какую-то функциональность. Или можно полностью заменить родную библиотеку, просто разместив новую с идентичным названием в папке application/libraries.

Класс Database не может быть расширен или заменен, а так же для PHP 4 нельзя заменять класс Loader. Все прочие классы можно свободно расширять/заменять.

Хранение.

Созданные библиотеки классов должны быть расположены в директории application/libraries, CodeIgniter будет искать их там во время инициализации.

Правила именования:

Имена файлов с большой буквы. Например: Myclass.php

Имя класса с большой буквы. Например: class Myclass

Имя файла и имя класса должны совпадать.

Файл класса.

Классы должны следовать этому прототипу:

<?php if (!defined('BASEPATH')) exit('Нет доступа к скрипту'); Someclass {some_function()

{

}

}

?>

Использование созданных пользователем классов.

Из любой функции контроллера можно инициализировать библиотеку следующей стандартной функцией:

$this->load->library('someclass');

Где someclass - это имя файла без расширения «.php». Можно указать имя файла в любом регистре.

После загрузки класса, следует обращаться к нему, используя нижний регистр:

$this->someclass->some_function(); // Имя объекта всегда в нижнем регистре

Передача параметров при инициализации класса.

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

$params = array('type' => 'large', 'color' => 'red');

$this->load->library('Someclass', $params);

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

<?php if (!defined('BASEPATH')) exit('Нет доступа к скрипту');Someclass {Someclass($params)

{

// Какие-то операции с $params

}

}

?>

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

Использование ресурсов CodeIgniter в библиотеке

Для доступа к родным ресурсам CodeIgniter в библиотеке используется функция get_instance(). Эта функция вернет супер-объект CodeIgniter.

При помощи этого можно обращаться к любой родной функции при помощи конструкции $this:

$this->load->helper('url');

$this->load->library('session');

$this->config->item('base_url');

и т.п.

$this, однако, работает только в контроллере, модели или отображении. Если нужно использовать родные классы CI внутри собственных, то можно сделать это следующим образом:

Во первых присвоить указатель на родной объект переменной:

$CI =& get_instance();

После того как присвоили объект переменной - нужно использовать эту переменную вместо $this:

$CI =& get_instance();

$CI->load->helper('url');

$CI->load->library('session');

$CI->config->item('base_url');

и т.п.

Функция get_instance() передается по ссылке:

$CI =& get_instance();

Что важно, т.к. указатель позволяет использовать оригинальный объект CodeIgniter, а не создавать его копию.

Кроме того, при работе с PHP 4 лучше избегать вызова get_instance() внутри конструктора класса. PHP 4 имеет проблемы с созданием ссылок на супер-объект CI в контроллере, т.к. объекты не существуют до тех пор, пока класс полностью не обработан.

Замена родных библиотек версиями. Достаточно назвать собственный класс таким же именем, как и родной, и CI загрузит его, вместо родного. Например, чтобы заменить родной класс Email, можно создать файл application/libraries/Email.php и создать класс внутри него:

class CI_Email {

}

Отммечу, что большинство родных классов имеют префикс CI_.

Для загрузки библиотеки используем родную функцию загрузки:

$this->load->library('email');

На данный момент класс Database не может быть заменен.

Расширение родных библиотек. Если надо расширить функциональность библиотеки, возможно добавить одну-две функции, то стоит не переопределять всю библиотеку, а просто расширить ее функциональность. Расширение класса практически идентично его замене за парой исключений: - Объявление класса должно расширять родительский класс.- Новое имя класса должно начинаться с префикса MY_ (это можно настроить).Например, чтобы расширить родной класс Email, нужно создать файл application/libraries/MY_Email.php и объявить внутри класс:

class MY_Email extends CI_Email {

}

Если в классе необходимо использовать конструктор, то нужно вызвать в нем родительский конструктор:

class MY_Email extends CI_Email {My_Email()

{::CI_Email();

}

}

Загрузка подкласса.

Для загрузки собственного подкласса, как правило, используется стандартный синтаксис. Не надо указывать здесь префикс. Так, например, для класса Email, который расширяет стандартный одноименный класс, небходимо использовать:

$this->load->library('email');

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

$this->email->some_function();

Установка собственного префикса.

Для установки собственного подклассового префикса откроем файл application/config/config.php и напишем там следующее:

$config['subclass_prefix'] = 'MY_';

Стандартным для CodeIgniter является префикс CI_. В данном случае нельзя использовать его.

Создание классов ядра

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

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

Перечень системных классов.

Вот перечень основных системных файлов, которые вызываются при инициализации CodeIgniter:

Benchmark

Замена классов ядра.

Для использования созданных скриптов вместо скриптов по умолчанию нужно разместить их в папке application/libraries:/libraries/some-class.php

Если такой папки нет, то нужно ее создать.

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

Созданный класс должен использовать CI в качестве префикса. Например, если файл назван Input.php, то класс должен объявляться так:

CI_Input {

}

Расширение классов ядра.

Расширение класса практически идентично его замене за парой исключений:

Объявление класса должно расширять родительский класс.

Новое имя класса должно начинаться с префикса MY_ .

Например, чтобы расширить родной класс Input, вы должны создать файл application/libraries/MY_Input.php и объявить внутри класс:

class MY_Input extends CI_Input {

}

Если в классе необходим конструктор - нужно в нем вызвать конструктор родителя:

class MY_Input extends CI_Input {My_Input()

{::CI_Input();

}

}

Любая функция в классе, название которой аналогично функции в родительском классе будет использоваться вместо родной (это называется «метод переопределения»). Это позволяет существенно менять ядро CodeIgniter'а.

Установка собственного префикса.

Для установки собственного префикса откройте файл application/config/config.php и найдите там:

$config['subclass_prefix'] = 'MY_';

2 Практическая часть


Согласно цели дипломной проект был создан сайт, содержащий информацию о ресторанах, кафе и барах города Челябинска. Данная информация заноситься администратором сайта и храниться в базе данных MySQL.

 

.1 Структура сайта


Данный сайт состоит из четырех частей:

·  Административная часть

·        Главная страница сайта

·        Страницы со списком заведений конкретной категории

·        Страницы с информацией по конкретному заведению

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

 

.1.1 Административная часть

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

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

2.1.2 Главная страница сайта

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

Рисунок 2 - Главная страница сайта

Карта Челябинска взята с сервиса Яндекс.Карты, который предоставляет возможность использовать карту на свом сайте. На данной карте отображаются иконки заведений, которые присутствуют на этой странице.

В верхней части сайта есть гиперссылка «Облако тэгов», при щелчке по которой появляется список ссылок на категории заведений (Рисунок 3). Размер шрифта каждой ссылки зависит от количества заведений в данной категории.

Рисунок 3 - Облако тэгов

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

 

.1.3 Страницы со списком заведений конкретной категории

На эту страницу пользователь переходит, выбрав одну из категорий в облаке тэгов (Рисунок 4). На странице можно увидеть постраничный перечень всех заведений, которые относятся к данной категории. Так же каждое заведение отображается на карте в виде иконки. Одно и то же заведение может относиться к разным категориям, например, зведение «Шафран» относиться к категориям «Ресторан», «Живая музыка», «Летнее кафе» и «Восточная кухня».

Рисунок 4 - Страница со списком заведений категории «Ресторан»

 

.1.4 Страницы с информацией по конкретному заведению

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

Рисунок 5 - Страница с информацией по конкретному заведению

(общая информация и карта)

Любой пользователь так же может оставить свой комментарий об этом заведении и оценить его (Рисунок 6). Оценка повышает рейтинг заведения и оно может попасть в список на главной странице. Для лучшего представления о заведении, представлен список фотографий - фотогалерея, При нажатии на любую фотографию, она увеличивается.

Рисунок 6 - Страница с информацией по конкретному заведению (комментарии и фотогалерея)

2.2 Модели

 

.2.1 Модель заведений - Firm

Модель Firm предоставляет доступ к информации о заведениях, хранимой в базе данных MySQL. Модель позволяет сделать следующие выборки данных:

·    getFieldsByFirm - информация о заведение для отображения ее в таблице,

·        getStats - общее количество заведений на сайте,

·        getOneByField - информация о заведении по ее условному обозначнию,

·        search - постраничный список заведений удовлетворяющих поисковому запросу,

·        getListByTag - постраничный список заведений относящихся к конкретной категории,

·        getListFavorites - постраничный список заведений, отсортированный по убыванию рейтинга,

·        getListLatest - постраничный список заведений, отсортированный по убыванию даты регистрации заведения.

Каждая запись модели Firm содержит следующие поля:

·    name - Название заведения

·        slug - Условное обозначение

·        address - Адрес заведения

·        point - Координаты на Яндекс.Картах

·        avg_price - Средняя цена на человека

·        date_open - Дата открытия

·        raion_id - Район, в котором распологается заведение

·        cat_id - Основная категория заведения

·        short - Краткое описание заведения

·        full - Особенности конкретного заведения

·        count_zal - Количество залов

·        order_table - Заказ столика

·        advanced_services - Дополнительные услуги

·        count_places - Общее количество мест

·        parking - Парковка

·        phones - Телефоны

·        timetable - Время работы

·        programm - Развлечения и программа

Полный код модели представлен в Приложении Б.

 

.2.2 Модель категорий - Tag

Модель Tag предоставляет доступ к информации о категориях, хранимой в базе данных MySQL. Модель позволяет сделать следующие выборки данных:

·    getListOrderByCount - список категорий, с количеством заведений в каждой категории,

·        getListByFirm - список категорий конкретного заведения.

Каждая запись модели Tag содержит следующие поля:

·    name - Название категории

·        slug - Условное обозначение

Полный код модели представлен в Приложении В.

 

.2.3 Прочие модели

Так же были созданы следующие модели:

Banner - Модель баннеров

Cat - Модель основных категорий заведений

Counter - Модель счетчиков

Firms_comment - Модель комментариев к заведениям

Firms_photo - Модель фотогалереи

Firms_rate - Модель рейтингов

menu - Модель меню сайта

option - Модель параметров сайта

raion - Модель районов города

resize_image - Модель создания уменьшеных изображений для фотогалереи- Модель пользователей (менеджеров сайта)

 

.3 Контроллеры

 

.3.1 Контроллер Firms

Контроллер Firms отвечает за обработку запроса пользователя по конкретному заведению. Для этого используется метод класса display. В этом методе вызываются функции моделей Firm, Tag, Firms_comment, Firms_rate и Firms_photo, для получения информации о фирме, списка категорий, относящихся к фирме, списка комментариев и фотографий и рейтинга заведения. Затем эта информация передается в отображение firms/display.html

 

.3.2 Контроллер Tags

Контроллер Tags отвечает за обработку запроса пользователя по конкретной категории и запроса главной странице.

Для обработки запроса главной страницы используется метод класса index. В этом методе вызываются функции моделей Firm и Tag, для получения информации о списке популярных и недавно добавленных заведений. Затем эта информация передается в отображение tags/index.html.

Для обработки запроса пользователя по конкретной категории используется метод класса display. В этом методе вызываются функции моделей Firm и Tag, для получения информации о списке заведений, относящихся к данной категории и собственно о категории. Затем эта информация передается в отображение tags/display.html.

 

.4 Отображения


Все отображения наследуются от общего шаблона layouts_html.html. В этом отображении содержиться общие для всех страниц сайта элементы - верхняя часть сайта (название сайта, статистическая информация и форма поиска), карта от сервиса Яндекс.Карт, нижняя часть сайта. Полный код шаблона приведен в Приложении Г.

ЗАКЛЮЧЕНИЕ


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

Запуск данного сайта позволит пользователям:

быстро находить необходимое заведение;

просматривать информацию о них;

оставлять свои комментарии о заведениях;

оценивать данное заведение;

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

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

При размещении его в глобальной сети география распространения возрастает до масштабов всего мира.

Литература


1.   Зандстра М. PHP. Объекты, шаблоны и методики программирования. - Вильямс: 2010, 560 c.

2.   Котеров Д. PHP 5. - BHV-СПб: 2008, 1104 с.

3.   Мейер Э. CSS - каскадные таблицы стилей. Подробное руководство, 3-е издание. - Символ-Плюс: 2008, 576 с.

4.      Флэнаган Д. JavaScript. Подробное руководство, 5-е издание. - Символ-Плюс: 2009, 992 с.

.        Грабер М. SQL. - Лори: 2007, 644 с.

.        Дюбуа П. MySQL. Сборник рецептов. - Символ-Плюс: 2004, 1056 с.

.        Заводны Д., Шварц Б., Зайцев П., Ткаченко В., Ленц А. MySQL. Оптимизация производительности, 2-е издание. - Символ-Плюс: 2010, 816 с.

Приложение A

FirmDescriptor extends CMSK_Descriptor

{$className = 'Firm';$common_fields = array(

'slug'=>array('name'=>'Url','type'=>'text','slug'=>'name_ru','rules'=>'trim|required','display_in_index'=>'text',),

'address'=>array('name'=>'Адрес','type'=>'text','rules'=>'trim|required',),

'point'=>array('name'=>'Координаты','type'=>'point'),

'avg_price'=>array('name'=>'Средняя цена на человека','type'=>'text','rules'=>'trim',),

'raion_id'=>array('name'=>'Район','type'=>'select','model'=>'Raion','value_field'=>'id','name_field'=>'name',),

'showed'=>array('name'=>'Показывать','type'=>'checkbox','default_value'=>true,'display_in_index'=>'showed_toogler',),

'tags'=>array('name'=>'Категории','type'=>'multiselect','model'=>'Tag','value_field'=>'id','name_field'=>'name','table'=>'firms_tags','inner_field'=>'firm_id','outer_field'=>'tag_id'),

);$multi_language_fields = array(

'name'=>array('name'=>'Название','type'=>'text','rules'=>'trim|required','display_in_index'=>'text',),

'short'=>array('name'=>'Кратко','type'=>'textarea','rules'=>'trim',),

'full'=>array('name'=>'Подробно','type'=>'textarea','rules'=>'trim',),

'count_zal'=>array('name'=>'Количество залов','type'=>'text','rules'=>'trim',),

'order_table'=>array('name'=>'Заказ столика','type'=>'text','rules'=>'trim',),

'advanced_services'=>array('name'=>'Дополнительные услуги','type'=>'text','rules'=>'trim',),

'count_places'=>array('name'=>'Общее количество мест','type'=>'text','rules'=>'trim',),

'parking'=>array('name'=>'Парковка','type'=>'text','rules'=>'trim',),

'phones'=>array('name'=>'Телефоны','type'=>'text','rules'=>'trim',),

'timetable'=>array('name'=>'Время работы','type'=>'text','rules'=>'trim',),

'title'=>array('name'=>'Title','type'=>'text',),

'keywords'=>array('name'=>'Keywords','type'=>'text',),

'description'=>array('name'=>'Description','type'=>'text',),

);$orderby = 't1.orderby,t1.id';$multi_lang_field = 'firm_id';

}

Приложение Б


<?php if (!defined('BASEPATH')) exit('No direct script access allowed');Firm extends CMSK_Model {$count_per_page = 10;$count_per_page_favorites = 6;$count_per_page_last = 12;

/**

* Информация о фирме

*

* @param object $firm фирма

*

* @return array

*/getFieldsByFirm($firm, $tags)

{

$firm_fields = array();($this->descriptor->common_fields as $name=>$field) {(isset($field['for_out']) && $field['for_out'] && $firm->{$name}) {

$firm_fields[] = array(

'name' => $field['name'],

'value' => $firm->{$name},

);

}

}($this->descriptor->multi_language_fields as $name=>$field) {(isset($field['for_out']) && $field['for_out'] && $firm->{$name}) {

$firm_fields[] = array(

'name' => $field['name'],

'value' => $firm->{$name},

);

}

}($tags as $tag) {($tag->for_out) {

$firm_fields[] = array(

'name' => $tag->name,

'is_have' => true,

);

}

}

return $firm_fields;

}

/**

* Информация для статистики

*

* @return integer

*/getStats()

{

$q = $this->db->select()->from($this->descriptor->getTable(), array());

$q->escape(false)->column('count(distinct t1.id) as c')->escape(true);

$q->where('t1.showed', true);

$items = $q->get()->result();(count($items)>0) {$items[0]->c;

} else {0;

}

}

/**

* Статьи по списку адресов

*

* @param array $urls список адресов

*

* @return array

*/getByUrls($urls)

{

$items = array();($urls as $url)

{

$items[] = $this->getByField('url',$url);

}

return $items;

}

/**

* выборка записи по полю и значению

*

* @param integer $field поля таблице для выборки

* @param string $value значение для выборки

* @param boolean $separate_lang признак будут ли разделены языки? иначе будет выбран текущий

*

* @return object

*/function getOneByField($field, $value=true)

{

$q = $this->db->select()->from($this->descriptor->getTable(), array());

$q->join('langs', "t2.lang_id=t3.id", array());

$q->where('t3.short', $this->Lang->default_lang);

$q->whereIsNotNull('t3.short');

$q->escape(false)->column('t3.*, t2.*')->escape(true);

$q->escape(false)->column('x(point) as point_x, y(point) as point_y, t1.*')->escape(true);

$q->escape(false)->column('round(avg(t4.rate)) as rate,count(distinct t4.id) as count_rate')->escape(true);

$q->join('firms_rates', "t1.id=t4.firm_id", array());

$q->escape(false)->column('t5.img as cat_img,t6.name as cat_name')->escape(true);

$q->join('cats', "t5.id=t1.cat_id", array());

$q->join('cats_content', 't5.id=t6.cat_id', array());

$q->join('langs', "t6.lang_id=t7.id", array());

$q->where('t1.'.$field, $value);(!$this->obj->is_admin && $this->load->database_original()->field_exists('showed', $this->descriptor->getTable())) {

$q->where('t1.showed', true);

}

$q->groupBy('t1.id');

$q->limit(1);

$items = $q->get()->result();(count($items)>0) {

$item = $items[0];$item;

} else { false;

}

}

/**

* выборка записи по полю и значению для админки

*

* @param integer $field поля таблице для выборки

* @param string $value значение для выборки

* @param boolean $separate_lang признак будут ли разделены языки? иначе будет выбран текущий

*

* @return object

*/function getByField($field, $value=true, $separate_lang=false)

{

$q = $this->db->select()->from($this->descriptor->getTable(), array());(!$separate_lang && $this->descriptor->multi_lang_field) {

$q->join($this->descriptor->getTable().'_content', 't1.id=t2.'.$this->descriptor->multi_lang_field, array());

$q->join('langs', "t2.lang_id=t3.id", array());

$q->where('t3.short', $this->Lang->default_lang);

$q->whereIsNotNull('t3.short');

$q->escape(false)->column('t3.*, t2.*')->escape(true);

}

$q->escape(false)->column('x(point) as point_x, y(point) as point_y, t1.*')->escape(true);

$q->where('t1.'.$field, $value);(!$this->obj->is_admin && $this->load->database_original()->field_exists('showed', $this->descriptor->getTable())) {

$q->where('t1.showed', true);

}

$q->groupBy('t1.id');

$q->limit(1);

$items = $q->get()->result();(count($items)>0) {

$item = $items[0];

// TODO: убрать бы id...($separate_lang && $field=='id' && $this->descriptor->multi_lang_field) {

$q = $this->db->select()->from($this->descriptor->getTable().'_content', array());

$q->escape(false)->column("t2.short as lang_short_name, t1.*")->escape(true);

$q->join('langs', "t1.lang_id=t2.id", array());

$q->where('t1.'.$this->descriptor->multi_lang_field, $value);

$langs_values = $q->get()->result();(count($langs_values)>0) {($langs_values as $values) {($values as $key=>$val) {(isset($item->{$key})) {(is_array($item->{$key})) {

$item->{$key}[$values->lang_short_name] = $val;

}

} else {

$item->{$key} = array($values->lang_short_name => $val);

}

}

}

}

}($separate_lang && $field=='id') {($this->descriptor->common_fields as $name=>$field) {($field['type'])

{'multiselect':

$q = $this->db->select()->from($field['table'], array());

$q->escape(false)->column('t1.*')->escape(true);

$q->where('t1.'.$field['inner_field'], $value);

$item->{$name} = $q->get()->result();;

}

}

}$item;

} else {false;

}

}

/**

* условие для поиска

*

* @param string $tag_slug slug тэга

*

* @return array

*/function _sub_search($q, $search)

{

$q->where()

>like('t2.name', $search['q'])

>where('or')

>like('t2.short', $search['q'])

>where('or')

>like('t2.full', $search['q'])

>where('or')

>like('t2.advanced_services', $search['q'])

>where('or')

>like('t2.phones', $search['q'])

>where('or')

>like('t2.programm', $search['q'])

>where('or')

>like('t2.title', $search['q'])

>where('or')

>like('t2.keywords', $search['q'])

>where('or')

>like('t2.description', $search['q'])

>where('or')

>like('t1.address', $search['q'])

>end();$q;

}

/**

* поиск фирм

*

* @param array $search условия поиска

*

* @return array

*/function search($search, $page=0)

{(!$search['q'])array(array(),0,0);

$q = $this->db->select()->from($this->descriptor->getTable(), array());($this->descriptor->multi_lang_field) {

$q->join($this->descriptor->getTable().'_content', 't1.id=t2.'.$this->descriptor->multi_lang_field, array());

$q->join('langs', "t2.lang_id=t3.id", array());

$q->where('t3.short', $this->Lang->default_lang);

$q->whereIsNotNull('t3.short');

$q->escape(false)->column('t3.*, t2.*')->escape(true);

}

$q->join('firms_tags', "t1.id=t4.firm_id", array());

$q->join('tags', "t5.id=t4.tag_id", array());

$q->escape(false)->column('x(point) as point_x, y(point) as point_y, t1.*')->escape(true);

$q->escape(false)->column('round(avg(t6.rate)) as rate,count(distinct t6.id) as count_rate')->escape(true);

$q->join('firms_rates', "t1.id=t6.firm_id", array());

$q->escape(false)->column('t7.img as cat_img,t8.name as cat_name')->escape(true);

$q->join('cats', "t7.id=t1.cat_id", array());

$q->join('cats_content', 't7.id=t8.cat_id', array());

$q->join('langs', "t8.lang_id=t9.id", array());

$q->where('t1.showed', true);

$q->where('t5.showed', true);

$this->_sub_search($q, $search);

$q->escape(false)->orderBy('t1.id')->escape(true);

$q->groupBy('t1.id');

$q->limit($this->count_per_page, $this->count_per_page*$page);

$items = $q->get()->result();

// общее число записей

$q = $this->db->select()->from($this->descriptor->getTable(), array());

$q->join($this->descriptor->getTable().'_content', 't1.id=t2.'.$this->descriptor->multi_lang_field, array());

$q->join('langs', "t2.lang_id=t3.id", array());

$q->where('t3.short', $this->Lang->default_lang);

$q->whereIsNotNull('t3.short');

$q->join('firms_tags', "t1.id=t4.firm_id", array());

$q->join('tags', "t5.id=t4.tag_id", array());

$q->escape(false)->column('count(distinct t1.id) as c')->escape(true);

$q->where('t1.showed', true);

$q->where('t5.showed', true);

$this->_sub_search($q, $search);

$count_items = $q->get()->result();

$count = $count_items[0]->c;

$count_page = ceil($count/$this->count_per_page);array($items, $count, $count_page);

}

/**

* список фирм по тэгу

*

* @param string $tag_slug slug тэга

*

* @return array

*/function getListByTag($tag_slug, $page=0)

{

$q = $this->db->select()->from($this->descriptor->getTable(), array());($this->descriptor->multi_lang_field) {

$q->join($this->descriptor->getTable().'_content', 't1.id=t2.'.$this->descriptor->multi_lang_field, array());

$q->join('langs', "t2.lang_id=t3.id", array());

$q->where('t3.short', $this->Lang->default_lang);

$q->whereIsNotNull('t3.short');

$q->escape(false)->column('t3.*, t2.*')->escape(true);

}

$q->join('firms_tags', "t1.id=t4.firm_id", array());

$q->join('tags', "t5.id=t4.tag_id", array());

$q->escape(false)->column('x(point) as point_x, y(point) as point_y, t1.*')->escape(true);

$q->escape(false)->column('round(avg(t6.rate)) as rate,count(distinct t6.id) as count_rate')->escape(true);

$q->join('firms_rates', "t1.id=t6.firm_id", array());

$q->escape(false)->column('t7.img as cat_img,t8.name as cat_name')->escape(true);

$q->join('cats', "t7.id=t1.cat_id", array());

$q->join('cats_content', 't7.id=t8.cat_id', array());

$q->join('langs', "t8.lang_id=t9.id", array());

$q->where('t1.showed', true);

$q->where('t5.showed', true);

$q->where('t5.slug', $tag_slug);

$q->escape(false)->orderBy('t1.id')->escape(true);

$q->groupBy('t1.id');

$q->limit($this->count_per_page, $this->count_per_page*$page);

$items = $q->get()->result();

// общее число записей

$q = $this->db->select()->from($this->descriptor->getTable(), array());

$q->join('firms_tags', "t1.id=t2.firm_id", array());

$q->join('tags', "t3.id=t2.tag_id", array());

$q->escape(false)->column('count(distinct t1.id) as c')->escape(true);

$q->where('t1.showed', true);

$q->where('t3.showed', true);

$q->where('t3.slug', $tag_slug);

$count_items = $q->get()->result();

$count = $count_items[0]->c;

$count_page = ceil($count/$this->count_per_page);array($items, $count, $count_page);

}

/**

* список популярных фирм

*

* @return array

*/

public function getListFavorites($is_main=true, $page=0)

{

$q = $this->db->select()->from($this->descriptor->getTable(), array());($this->descriptor->multi_lang_field) {

$q->join($this->descriptor->getTable().'_content', 't1.id=t2.'.$this->descriptor->multi_lang_field, array());

$q->join('langs', "t2.lang_id=t3.id", array());

$q->where('t3.short', $this->Lang->default_lang);

$q->whereIsNotNull('t3.short');

$q->escape(false)->column('t3.*, t2.*')->escape(true);

}

$q->escape(false)->column('x(point) as point_x, y(point) as point_y, t1.*')->escape(true);

$q->escape(false)->column('round(avg(t4.rate)) as rate,count(distinct t4.id) as count_rate')->escape(true);

$q->join('firms_rates', "t1.id=t4.firm_id", array());

$q->escape(false)->column('t5.img as cat_img,t6.name as cat_name')->escape(true);

$q->join('cats', "t5.id=t1.cat_id", array());

$q->join('cats_content', 't5.id=t6.cat_id', array());

$q->join('langs', "t6.lang_id=t7.id", array());

$q->where('t1.showed', true);

$q->escape(false)->orderBy('rate desc')->escape(true);

$q->groupBy('t1.id');($is_main)

{

$q->limit($this->count_per_page_favorites);

$count = 0;

$count_page = 0;

}

{

$q->limit($this->count_per_page, $this->count_per_page*$page);

}

$items = $q->get()->result();

(!$is_main) {

// общее число записей

$q = $this->db->select()->from($this->descriptor->getTable(), array());

$q->escape(false)->column('count(distinct t1.id) as c')->escape(true);

$q->where('t1.showed', true);

$count_items = $q->get()->result();

$count = $count_items[0]->c;

$count_page = ceil($count/$this->count_per_page);

}array($items, $count, $count_page);

}

/**

* список новых фирм

*

* @return array

*/

public function getListLatest($is_main=true, $page=0)

{

$q = $this->db->select()->from($this->descriptor->getTable(), array());($this->descriptor->multi_lang_field) {

$q->join($this->descriptor->getTable().'_content', 't1.id=t2.'.$this->descriptor->multi_lang_field, array());

$q->join('langs', "t2.lang_id=t3.id", array());

$q->where('t3.short', $this->Lang->default_lang);

$q->whereIsNotNull('t3.short');

$q->escape(false)->column('t3.*, t2.*')->escape(true);

}

$q->escape(false)->column('x(point) as point_x, y(point) as point_y, t1.*')->escape(true);

$q->escape(false)->column('round(avg(t4.rate)) as rate,count(distinct t4.id) as count_rate')->escape(true);

$q->join('firms_rates', "t1.id=t4.firm_id", array());

$q->escape(false)->column('t5.img as cat_img,t6.name as cat_name')->escape(true);

$q->join('cats', "t5.id=t1.cat_id", array());

$q->join('cats_content', 't5.id=t6.cat_id', array());

$q->join('langs', "t6.lang_id=t7.id", array());

$q->where('t1.showed', true);

$q->escape(false)->orderBy('t1.create desc')->escape(true);

$q->groupBy('t1.id');($is_main)

{

$q->limit($this->count_per_page_last);

$count = 0;

$count_page = 0;

}

{

$q->limit($this->count_per_page, $this->count_per_page*$page);

}

$items = $q->get()->result();(!$is_main) {

// общее число записей

$q = $this->db->select()->from($this->descriptor->getTable(), array());

$q->escape(false)->column('count(distinct t1.id) as c')->escape(true);

$q->where('t1.showed', true);

$count_items = $q->get()->result();

$count = $count_items[0]->c;

$count_page = ceil($count/$this->count_per_page);

}array($items, $count, $count_page);

}

}FirmDescriptor extends CMSK_Descriptor

{$className = 'Firm';$common_fields = array(

'slug'=>array('name'=>'Условное обозначение','type'=>'text','slug'=>'name_ru','rules'=>'trim|required','display_in_index'=>'text',),

'address'=>array('name'=>'Адрес','type'=>'text','rules'=>'trim|required','for_out'=>true,),

'point'=>array('name'=>'Координаты','type'=>'point'),

'avg_price'=>array('name'=>'Средняя цена на человека','type'=>'text','rules'=>'trim','for_out'=>true,),

'date_open'=>array('name'=>'Дата открытия','type'=>'date','rules'=>'trim','for_out'=>true,),

'raion_id'=>array('name'=>'Район','type'=>'select','model'=>'Raion','value_field'=>'id','name_field'=>'name',),

'cat_id'=>array('name'=>'Основная категория','type'=>'select','model'=>'Cat','value_field'=>'id','name_field'=>'name',)

'showed'=>array('name'=>'Показывать','type'=>'checkbox','default_value'=>true,'display_in_index'=>'showed_toogler',),

'tags'=>array('name'=>'Категории','type'=>'multiselect','model'=>'Tag','value_field'=>'id','name_field'=>'name','table'=>'firms_tags','inner_field'=>'firm_id','outer_field'=>'tag_id'),

);$multi_language_fields = array(

'name'=>array('name'=>'Название','type'=>'text','rules'=>'trim|required','display_in_index'=>'text',),

'short'=>array('name'=>'Кратко','type'=>'textarea','rules'=>'trim',),

'full'=>array('name'=>'Особенности','type'=>'textarea','rules'=>'trim','for_out'=>true,),

'count_zal'=>array('name'=>'Количество залов','type'=>'text','rules'=>'trim','for_out'=>true,),

'order_table'=>array('name'=>'Заказ столика','type'=>'text','rules'=>'trim','for_out'=>true,),

'advanced_services'=>array('name'=>'Дополнительные услуги','type'=>'text','rules'=>'trim','for_out'=>true,),

'count_places'=>array('name'=>'Общее количество мест','type'=>'text','rules'=>'trim','for_out'=>true,),

'parking'=>array('name'=>'Парковка','type'=>'text','rules'=>'trim','for_out'=>true,),

'phones'=>array('name'=>'Телефоны','type'=>'text','rules'=>'trim','for_out'=>true,),

'timetable'=>array('name'=>'Время работы','type'=>'text','rules'=>'trim','for_out'=>true,),

'programm'=>array('name'=>'Развлечения и программа','type'=>'text','rules'=>'trim','for_out'=>true,),

'title'=>array('name'=>'Title','type'=>'text',),

'keywords'=>array('name'=>'Keywords','type'=>'text',),

'description'=>array('name'=>'Description','type'=>'text',),

);$orderby = 't1.orderby,t1.id';$multi_lang_field = 'firm_id';

}

/* End of file firm.php */

/* Location: ./application/models/firm.php */

Приложение В


<?php if (!defined('BASEPATH')) exit('No direct script access allowed');Tag extends CMSK_Model {$count_per_page_for_cloud = 20;

/**

* список тэгов отсортированных по количеству фирм

*

* @return array

*/function getListOrderByCount()

{

$q = $this->db->select()->from($this->descriptor->getTable(), array());($this->descriptor->multi_lang_field) {

$q->join($this->descriptor->getTable().'_content', 't1.id=t2.'.$this->descriptor->multi_lang_field, array());

$q->join('langs', "t2.lang_id=t3.id", array());

$q->where('t3.short', $this->Lang->default_lang);

$q->whereIsNotNull('t3.short');

$q->escape(false)->column('t3.*, t2.*')->escape(true);

}

$q->join('firms_tags', "t1.id=t4.tag_id", array());

$q->join('firms', "t5.id=t4.firm_id", array());

$q->escape(false)->column('count(distinct t5.id) as count_tags,t1.*')->escape(true);

$q->where('t1.showed', true);

$q->where('t5.showed', true);

$q->escape(false)->orderBy('t2.name,t1.id')->escape(true);

$q->groupBy('t1.id');

$q->limit($this->count_per_page_for_cloud);

$items = $q->get()->result();$items;

}

/**

* список тэгов фирмы

*

* @param object $firm фирма

*

* @return array

*/function getListByFirm($firm)

{

$q = $this->db->select()->from($this->descriptor->getTable(), array());($this->descriptor->multi_lang_field) {

$q->join($this->descriptor->getTable().'_content', 't1.id=t2.'.$this->descriptor->multi_lang_field, array());

$q->join('langs', "t2.lang_id=t3.id", array());

$q->where('t3.short', $this->Lang->default_lang);

$q->whereIsNotNull('t3.short');

$q->escape(false)->column('t3.*, t2.*')->escape(true);

}

$q->escape(false)->column('t1.*')->escape(true);

$q->join('firms_tags', "t1.id=t4.tag_id", array());

$q->join('firms', "t5.id=t4.firm_id", array());

$q->where('t5.id', $firm->id);

$q->where('t5.showed', true);

$q->escape(false)->orderBy('t1.id')->escape(true);

$q->groupBy('t1.id');

$items = $q->get()->result();$items;

}

}TagDescriptor extends CMSK_Descriptor

{$className = 'Tag';$common_fields = array(

'slug'=>array('name'=>'Url','type'=>'text','slug'=>'name_ru','rules'=>'trim|required','display_in_index'=>'text',),

'showed'=>array('name'=>'Показывать','type'=>'checkbox','default_value'=>true,'display_in_index'=>'showed_toogler',),

'for_out'=>array('name'=>'Для показа в фирме','type'=>'checkbox','default_value'=>true,'display_in_index'=>'showed_toogler',),

);$multi_language_fields = array(

'name'=>array('name'=>'Название','type'=>'text','rules'=>'trim|required','display_in_index'=>'text',),

'title'=>array('name'=>'Title','type'=>'text',),

'keywords'=>array('name'=>'Keywords','type'=>'text',),

'description'=>array('name'=>'Description','type'=>'text',),

);$orderby = 't1.orderby,t1.id';$multi_lang_field = 'tag_id';$parent_field = 'tag_id';

}

/* End of file tag.php */

/* Location: ./application/models/tag.php */

Приложении Г


{{ "Content-Type: text/html; charset=utf-8"|header }}

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">

<head>

<meta http-equiv="content-type" content="text/html; charset=UTF-8" />

<meta name="description" content="{% block description %}{{ seo.description }}{% endblock %}" />

<meta name="keywords" content="{% block keywords %}{{ seo.keywords }}{% endblock %}" />

<title>{% block title %}{{ seo.title }}{% endblock %}</title>

{% block javascript %}

<script type="text/javascript" src="/js/jquery.js"></script>

<script type="text/javascript" src="/js/jquery.scrollTo-min.js"></script>

<script type="text/javascript" src="/js/swfobject.js"></script>

<script type="text/javascript" src="/js/thickbox.js"></script>

<script src="http://api-maps.yandex.ru/1.1/index.xml?key={{ yandex_api }}" type="text/javascript"></script>

<script src='/js/star/jquery.rating.js' type="text/javascript" language="javascript"></script>

<script type="text/javascript" src="/js/script.js"></script>

<script>pre_init()

{.setCenter(new YMaps.GeoPoint({{ user_center_x }}, {{ user_center_y }}), {{ user_zoom }});

};

</script>

{% endblock %}

{% block css %}

<link rel="shortcut icon" href="/img/favicon.ico" type="image/x-icon" />

<link rel="stylesheet" type="text/css" href="/css/reset.css" media="all" />

<link rel="stylesheet" type="text/css" href="/css/style.css" media="all" />

<link rel="stylesheet" type="text/css" href="/css/print.css" media="print" />

<link rel="stylesheet" type="text/css" href="/css/thickbox.css" />

<link href='/js/star/jquery.rating.css' type="text/css" rel="stylesheet"/>

{% endblock %}

</head>

<body>

<div>

<h1><a href="/">{% trans %}Кафе,&nbsp;рестораны Челябинска{% endtrans %}</a></h1>

<div>

<h4>{% trans %}На&nbsp;нашем&nbsp;сайте{% endtrans %}</h4>

<p>заведений{% endtrans %}</p>

<p>голосов{% endtrans %}</p>

<p>комментария{% endtrans %}</p>

<p>фотографии{% endtrans %}</p>

</div>

<div>

<ul>

</ul>

<form>

<input type="hidden" value="" name="t"/>

<input type="text" value="{{ content.search.q }}" name="q">

<input type="submit">

</form>

<a href="#">Сложный&nbsp;поиск{% endtrans %} &rarr;</a>

<a href="#">Облако&nbsp;тэгов{% endtrans %}</a>

<ol>

{% for item in cloud_tags %}

<li>

{% endfor %}

</ol>

</div>

</div>

<div>

{% block map %}

<div id="YMaps" style="height:400px"></div>

{% endblock %}

</div>

<div>

{% block content %}

{% endblock %}

</div>

<div>

<div>

</div>

</body>

</html>

Похожие работы на - Разработка web-сайта о кафе, барах и ресторанах города Челябинска

 

Не нашли материал для своей работы?
Поможем написать уникальную работу
Без плагиата!