PHP

Создание интерактивных диаграмм на PHP и FusionCharts

В этом уроки мы научим вас создавать детализированные диаграммы на 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 и всё, диаграмма готова!

Для большего вдохновения можете посетить вот эту демо страницу. Спасибо за внимание!
Добавлено: 19 Августа 2013 01:50:47 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...