В этом уроки мы научим вас создавать детализированные диаграммы на PHP и FusionCharts.
Вступление
В большинстве случаев графическое представление данных наиболее приемлемо в той или иной ситуации. Если же диаграммы ещё и интерактивны, то это совсем круто! Что я имею в виду? Нажатие на элемент диаграммы влечёт за собой открытие другой диаграммы.
Что такое связные диаграммы?
До этого момента, подобные диаграммы соответствовали только одному потоку данных и не были полностью связаны между собой. Что если мы сделаем диаграммы, по которым можно будет двигаться взад и вперёд? Такие диаграммы называются связными и относятся к новому пакету FusionCharts 3.2, которые позволяют вам создать многоуровневые диаграммы извлекая данные из одного источника. В таких диаграммах всё связано между собой.
В этом уроки мы рассмотрим интеграцию таких диаграмм в небольшой проект. База данных MySQL будет содержать данные, PHP будет работать как связующее звено, создающее XML файл, FusionCharts будут принимать этот файл и выводить данные.
Несколько слов о связных диаграммах:
По умолчанию диаграмма потомок, имеет такой же тип отображения (допустим столбцовые диаграммы) как и родитель;
Дополнительные настройки могут быть добавлены на любом уровне иерархии, включая сам тип диаграммы;
Диаграммы можно размещать в HTML контейнере, jQuey диалогах, lightbox, окнах extJS и т.д.;
Поддержка событий средствами JavaScript;
Что мы хотим сделать?
Множества раз перед нами стояла задача отследить рост посетителей на наших сайтах. Так давайте же создадим небольшой проект, который будет показывать число зарегистрированных пользователей за месяц / день / час или другими словами, число пользователей зарегистрировавшихся на нашем сайте за определённый промежуток времени.
Требования:
Любой веб-сервер с PHP;
MySQL сервер с базой данных;
FusionCharts, которые вы можете скачать или купить на их сайте;
Шаг 0. Подготовка
Создайте пустую базу данных с названием fctutorialс.
Создайте пустую папку с названием fcdemo в корне вашего веб-сервера (обычно www)
Шаг 1. Подготовка базы данных
Чтобы придерживаться простоты мы будем использовать только одну таблицу users, которая будет отображать информацию о пользователях. Нам интересно исключительно время регистрации пользователей. Так что наша таблица будет содержать только эту информацию. Вставьте этот код в phpMyAdmin:
CREATE TABLE `users`
(
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`Time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`ID`),
KEY `Time` (`Time`)
)
Мы создали таблицу, содержащую 2 поля: ID и time. В time будет содержаться информация о времени регистрации пользователя. Заметьте, что на данное поле мы поставили индекс т.к. будем использовать множество условий WHERE. Индекс позволит нам ускорить процесс выборки.
Подключение к базе
Напишем небольшой скрипт для подключения к базе данных:
<?php
$db_host = 'localhost';
$db_database = 'fctutorial';
$db_username = 'root';
$db_password = '';
if ( ! mysql_connect($db_host, $db_username, $db_password))
die ("Не смог подключиться к серверу.");
if ( ! mysql_select_db($db_database))
die ("Не смог подключиться к базе.");
?>
Замените настройки на свои собственные и сохраните данный файл под именем connect-to-database.php в папке fcdemo.
Вставим случайные данные
Если бы это был настоящий проект, то таблица users пополнялась бы со временем, но для демонстрации нам необходимо вставить какие-то данные. Напишем небольшой скрипт, который будет вставлять случайные данные в таблицу. Не переживайте, если вы не поймёте следующий код – для этого урока это не принципиально.
<?php
//Подключаемся к базе
require 'connect-to-database.php';
//Устанавливаем значения переменным
$MinTime = strtotime('2010-01-01');
$MaxTime = strtotime('2010-12-12');
$RecordsToInsert = 10000;
//Генерируем случайное время
for($i = 0; $i < $RecordsToInsert; $i++)
{
$RandomTime = rand($MinTime, $MaxTime);
mysql_query("INSERT INTO `users` (Time) VALUES (FROM_UNIXTIME({$RandomTime}))") or die(mysql_error());
}
//Completed
echo "Вставлено {$RecordsToInsert} записей.";
?>
Сохраните этот файл под названием generate-random-data.php всё в той же папке.
Сначала мы инклудим файл подключения к базе. Затем устанавливаем временные рамки, из которых случайным образом будет выбираться время для регистрации пользователя. Вы можете изменить количество вставляемых строк. Для этого вам нужно подправить переменную $RecordsToInsert.
Потом мы запускаем скрипт вставки сгенерированных записей в базу данных. Для того, чтобы запустить этот процесс зайдите по этому адресу - http://localhost/fcdemo/generate-random-data.php.
В конце концов вы должны увидеть сообщение: «Вставлено {$RecordsToInsert} записей»
Шаг 2. Готовим скелет сайта
Нам необходимо создать самую простую страницу для отображения нашей диаграммы. Что-то типа этого:
<html>
<head>
<title>FusionCharts v3.2 - LinkedCharts PHP Demo</title
<script type="text/javascript" src="Charts/FusionCharts.js"></script>
</head>
<body>
<div id="chartContainer">Загрузка FusionCharts </div>
<script type="text/javascript"><!--
var myChart = new FusionCharts( "Charts/Column3D.swf", "myChartId", "800", "400");
myChart.setXMLUrl( "get-data.php?year=2010" );
myChart.render( "chartContainer" );
// -->
</script>
</body>
</html>
Сохраните этот файл под именем demo.html:
В разделе <head> мы подключаем JavaScript библиотеку FusionCharts.js. Вы можете её найти в папке Charts в zip файле FusionCharts.
В разделе <body> мы создали контейнер для нашей диаграммы.
Создали небольшой фрагмент кода, который инициализирует объект FusionChart со следующими параметрами:
Charts/Column3D.swf – адрес swf файла. Для этого примера мы будем использовать диаграмму Column3D.
myChartId – это ID самой диаграммы. Он необходим если мы создаём больше одной диаграммы.
Следующие 2 параметра это ширина и высота диаграммы.
myChart.setXMLUrl( "get-data.php?year=2010" ); - определяет источник данных. Данной строчкой мы сообщаем, что данные будут браться из XML файла со страницы get-data.php?year=2010. Файл get-data.php мы напишем сразу же как закончим этот шаг.
Итак, мы использовали 2 файла из пакета FusionCharts. Для того чтобы всё работало, вам нужно закинуть их в папку fcdemo/Charts.
Шаг 3. Готовим бэк-энд
FusionCharts работают с данными в формате XML или JSON. Мы будем использовать формат XML, так как он знаком большему количеству аудитории. Файл с данными может содержать не только информацию для столбцов диаграммы, но и элементы для оформления заголовков. Нам необходимо сделать нашу систему так, чтобы PHP считывал информацию из базы и генерировал XML файл следующего типа:
<chart caption="Monthly New Users for the Year: 2010" xAxisName="Months" yAxisName="Users" showNames="1" bgColor="E6E6E6,F0F0F0" bgAlpha="100,50" bgRatio="50,100" bgAngle="270" showBorder="1" borderColor="AAAAAA" baseFontSize="12">
<set value="486" name="1"/>
<set value="443" name="2"/>
<set value="553" name="3"/>
<set value="550" name="4"/>
<set value="634" name="5"/>
<set value="622" name="6"/>
<set value="710" name="7"/>
<set value="772" name="8"/>
<set value="850" name="9"/>
<set value="1044" name="10"/>
<set value="1175" name="11"/>
<set value="761" name="12"/>
</chart>
Вот так вот должна выглядеть информация. В теге chart должна быть размещена вся статистическая информация. Кроме того, вы можете увидеть и другие теги, которые отвечают за оформление и заголовки.
Теперь создадим файл get-data.php, который будет доставать данные из базы и создавать из них XML файл:
<?php
//Фильтруем входящие данные
$Year = intval($_GET['year']);
//Формируем запрос.
$Query = "SELECT MONTH(Time) AS Value, COUNT(*) AS Total FROM `users` WHERE YEAR(Time)={$Year} GROUP BY Value";
// Нумерация месяцев
$ResultArray = array_fill(1, 12, 0);
// Готовим заголовки.
$ChartHeading = 'Новые пользователи в году: '.$Year;
$XaxisName = 'Месяца';
//Подключаемся к базе
require 'connect-to-database.php';
//Делаем запрос
$QueryResult = mysql_query($Query);
//Всё копим в массив
while($Row = mysql_fetch_assoc($QueryResult))
$ResultArray[$Row['Value']]=$Row['Total'];
//Генерируем теги оформления:
$Output = '<chart caption="'.$ChartHeading.'" xAxisName="'.$XaxisName.'" yAxisName="Users" showNames="1" bgColor="E6E6E6,F0F0F0" bgAlpha="100,50" bgRatio="50,100" bgAngle="270" showBorder="1" borderColor="AAAAAA" baseFontSize="12">';
//Генерируем тело Chart XML:
foreach($ResultArray as $key => $val) // key is month number (1-12)
$Output .= '<set value="'.$val.'" name="'.$key.'"/>';
//Закрываем Chart XML
$Output .= '</chart>';
//Устанавливаем XML header
header('Content-type: text/xml');
//Отправляем
echo $Output;
?>
Сохраните этот файл под именем get-data.php. Пройдёмся по коду:
В первую очередь мы фильтруем входящие данные $_GET['year'];
Дальше считаем количество пользователей которые были зарегистрированы на нашем сайте в принятом году. Результат сгруппирован при помощи GROUP BY.
Далее мы формируем массив $ResultArray состощий из числа месяцев.
Название диаграммы записываем в переменную X-Axis.
Подключаемся к базе и делаем запрос.
Дальше мы копим результат в массив строчку за строчкой. Если в результате запроса не найдётся ни одного зарегистрированного пользователя, то мы хотим отображать значение 0. Именно поэтому мы в массив $ResultArray записали нули. Это необходимо для сортировки массива.
Далее мы создаём заголовок XML файла. Всю необходимую информацию о диаграмме записываем в $ChartHeading. Тут же задаём все необходимые заголовки и цвета.
Далее мы готовим тело нашего XML файла путём конкатенирования строк в переменную $Output. Всё что там находится, так это теги <code><set>.
Для того чтобы завершить XML документ, мы закрываем его тегом <chart>.
Так же устанавливаем значение content-type для того, чтобы программе было понятно с каким форматом ей нужно иметь дело.
Чтобы посмотреть на сгенерированный XML код, перейдите по адресу http://localhost/fcdemo/get-data.php?year=2010.
Вы должны увидеть, что-то вроде того, что видели в начале этого шага.
Опробуем
Теперь, когда всё готово, мы можем протестировать наш пример. Откройте ваш браузер и перейдите по адресу http://localhost/fcdemo/demo.html.
Если вы всё сделали правильно, то на вашей странице будет отображаться следующая диаграмма:
Шаг 4. Превращаем нашу диаграмму в связную диаграмму
Чтобы превратить нашу диаграмму в связную диаграмму, нам необходимо решить какой параметр мы будем передавать в диаграмму потомка. Мы можем передавать всю строку данных или url данных. Если выбрать первый случай, то данные для каждого потомка будут встроены в диаграммах родителей, а связь между ними будет происходить по уникальным идентификаторам. В нашем случае у нас есть множество всевозможных видов диаграмм (12 месяцев, 30 дней, 24 часа). Так что мы будем использовать строку url для передачи данных. Таким образом, нам остается только связать данные с URL в «горячих точках» (точках, при нажатии на которые будет открываться новая диаграмма).
Усовершенствуем PHP код:
Поскольку нам необходимо делать выборку по месяцам, дням и часам, нам требуется несколько изменить PHP код. Сначала взглянем на него, а затем разберём по кусочкам.
<?php
// Фильтруем входящие данные
$Type = $_GET['type'];
$Year = intval($_GET['year']);
$Month = intval($_GET['month']);
$Day = intval($_GET['day']);
//Имена месяцев
$MonthsNames = array(null, 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
//Готовим данные в зависимости от запроса
switch($Type)
{
default:
case 'monthly':
$Query = "SELECT MONTH(Time) AS Value, COUNT(*) AS Total FROM `users` WHERE YEAR(Time)={$Year} GROUP BY Value";
$ResultArray = array_fill(1, 12, 0);
$ChartHeading = 'Новые пользователи за год: '.$Year;
$XaxisName = 'Месяца';
break;
case 'daily':
$Query = "SELECT DAY(Time) AS Value, count(*) AS Total FROM `users` WHERE YEAR(Time)={$Year} AND MONTH(Time)={$Month} GROUP BY Value";
$ResultArray = array_fill(1, 31, 0);
$ChartHeading = 'Новые пользователи за месяц: '.$MonthsNames[$Month].'/'.$Year;
$XaxisName = 'Дни';
break;
case 'hourly':
$Query = "select HOUR(Time) AS Value, count(*) AS Total FROM `users` WHERE YEAR(Time)={$Year} AND MONTH(Time)={$Month} AND DAY(Time)={$Day} GROUP BY Value";
$ResultArray = array_fill(0, 24, 0);
$ChartHeading = 'Новые пользователи за день: '.$Day.'/'.$MonthsNames[$Month].'/'.$Year;
$XaxisName = 'Часы';
break;
}
//Подключаемся к базе
require 'connect-to-database.php';
//Делаем запрос
$QueryResult = mysql_query($Query);
//Копим всё в массив
while($Row = mysql_fetch_assoc($QueryResult))
$ResultArray[$Row['Value']]=$Row['Total'];
//Генерируем заголовок XMLt
$Output = '<chart caption="'.$ChartHeading.'" xAxisName="'.$XaxisName.'" yAxisName="Users" showNames="1" bgColor="E6E6E6,F0F0F0" bgAlpha="100,50" bgRatio="50,100" bgAngle="270" showBorder="1" borderColor="AAAAAA" baseFontSize="12">';
// Генерируем тело Chart XML:
switch($Type)
{
default:
case 'monthly':
foreach($ResultArray as $MonthNumber => $value) // Месяца (1-12)
$Output .= '<set value="'.$value.'" name="'.$MonthsNames[$MonthNumber].'" link="newchart-xmlurl-get-data.php?type=daily&year='.$Year.'&month='.$MonthNumber.'"/>';
break;
case 'daily':
foreach($ResultArray as $DayNumber => $value) // Дни (1-31)
$Output .= '<set value="'.$value.'" name="'.$DayNumber.'" link="newchart-xmlurl-get-data.php?type=hourly&year='.$Year.'&month='.$Month.'&day='.$DayNumber.'"/>';
break;
case 'hourly':
foreach($ResultArray as $HourNumber => $value) // Часы (0-23)
$Output .= '<set value="'.$value.'" name="'.$HourNumber.'"/>';
break;
}
// Закрываем XML:
$Output .= '</chart>';
// Устанавливаем XML header
header('Content-type: text/xml');
// Отправляем
echo $Output;
?>
Что мы изменили?
Теперь поскольку у нас в наличии имеется несколько видов диаграмм, через $_GET нам будет передаваться типа диаграммы. То же самое и с $Monthand $Hour и $Year;
Далее мы создаём массив $MonthNames, который будет содержать названия месяцев. Поскольку массив начинается с нуля, то первый элемент равен null;
Теперь в зависимости от типа переменные $Query, $ResultArray, $ChartHeading и $XAsixName присваиваются в switch. Если $Type не установлен, то по умолчанию будут отображаться месяца;
Далее мы подключаемся к базе, выполняем запрос, копим результат в массив и генерируем первую часть xml файла;
Далее генерируем тело XML файла. Поскольку тело зависит от типа диаграммы, мы снова используем switch;
Месяца: всё то же самое за исключением ссылки. Теперь она будет такой: newchart-xmlurl-get-data.php; newchart - готовит о том, что мы создаём новую диаграмму, xmlurl – по какому адресу искать данные. Всё что идёт далее является частью URL. Вот полная ссылка к месяцу Январь: newchart-xmlurl-get-data.php?type=hourly&Year=2010&Month=1
Дни: всё тоже самое и в случае с месяцем, только вот URL теперь содержит информацию, касающуюся дней;
Часы: если мы не хотим, чтобы после этой диаграммы следовали другие, просто не установим ей URL;
В самом конце закрываем XML;
Сохраните данный файл как get-data.php; Теперь откройте браузер и проверьте работу скрипта. Например: http://localhost/fcdemo/get-data.php?year=2010
Вы должны увидеть что-то вроде этого:
<chart caption="Monthly New Users for the Year: 2010" xAxisName="Months" yAxisName="Users" showNames="1" bgColor="E6E6E6,F0F0F0" bgAlpha="100,50" bgRatio="50,100" bgAngle="270" showBorder="1" borderColor="AAAAAA" baseFontSize="12">
<set value="486" name="Jan" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=1"/>
<set value="443" name="Feb" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=2"/>
<set value="553" name="Mar" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=3"/>
<set value="550" name="Apr" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=4"/>
<set value="634" name="May" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=5"/>
<set value="622" name="Jun" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=6"/>
<set value="710" name="Jul" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=7"/>
<set value="772" name="Aug" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=8"/>
<set value="850" name="Sep" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=9"/>
<set value="1044" name="Oct" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=10"/>
<set value="1175" name="Nov" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=11"/>
<set value="761" name="Dec" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=12"/>
</chart>
Тестируйте
Теперь мы полностью закончили работу над диаграммами. Для того, что проверить работу зайдите по адресу http://localhost/fcdemo/demo.html
Если вы всё правильно сделали, то на странице увидите Column3D диаграмму. Если вы кликните по одному из столбцов, то откроется новая диаграмма. И так далее…
Вывод
Если вы внимательно изучили данный урок, то уже скорее всего имеете общее представление о связных диаграммах на PHP/MySQL. Точно такие же диаграммы могут быть сделаны для следующей статистики:
Количество продаж за период времени;
Сколько раз ваш сайт переставал работать;
Количество посетителей отдельной страницы;
Структура диаграммы будет одна и та же для любой темы. Используйте какой-то параметр для выборки инфы из базы, затем превратите ответ в XML и всё, диаграмма готова!
Для большего вдохновения можете посетить вот эту демо страницу. Спасибо за внимание!