Владимир Зайцев
Когда достаём из базы данных много подобной
информации мы её конечно же в массив оформляем.
Если нам надо блок разнотипной информации как
одно целое хранить и обрабатывать - создаём
объект, используя описание класса как трафарет.
Ну а если подобных объектов несколько - массив
обектов. Как такую штуку запустить попробую
показать.
Например стоит старинная задача: из пункта
"А" доехать в пункт "В" на автобусе.
Всего автобусных маршрутов в городке - 34,
остановок по городку - 99, в некоторые дни
отдельные маршруты не ходят. Но вся информация
имеется в базе данных и организована следующим
образом:
table common
id
int(4) |
name varchar(100) |
1 |
Academic I |
2 |
Anthony Seeger |
3 |
Ashby Crossing |
4 |
Blue Ridge Dr. @ Madison Manor |
5 |
Blue Ridge Hall |
.................................. |
......................................... |
98 |
Waterman Square |
99 |
Zane Showker Hall |
В этой таблице перечисленны ID остановок ( int ) и
их названия ( string )
table common_2
id_stop int(4) |
routes_string
(varchar(250) |
1 |
;9;10;11;12; |
2 |
;5;6;6a;7;7a;9; |
3 |
;4w;7;7a;10;12; |
4 |
;2; |
............................... |
..................................... |
98 |
;3; |
99 |
;1;2;4;4w;5;6;6a;7;7a;9;7a;10;12; |
Здесь показано на какой остановке - её ID ( int )
какие маршруты останавливаются ( string )
table routes
progr_name varchar(10) |
real_name varchar(10) |
sunday varchar(10) |
monday varchar(10) |
tuesday varchar(10) |
wednesday varchar(10) |
thursday varchar(10) |
friday varchar(10) |
saturday varchar(10) |
01 |
1 |
n |
y |
y |
y |
y |
y |
y |
02 |
1w |
y |
y |
y |
y |
y |
y |
y |
03 |
2 |
n |
y |
y |
y |
y |
y |
y |
04 |
2w |
y |
y |
y |
y |
y |
y |
y |
...... |
....... |
....... |
...... |
....... |
...... |
....... |
....... |
....... |
33 |
12_1 |
y |
y |
y |
y |
y |
y |
y |
34 |
12_2 |
y |
y |
y |
y |
y |
y |
y |
Показывает програмное имя маршрута ( string ), его
реальное имя ( string ) и в какой день недели этот
автобус ходит, а в какой нет ( начинаем с
воскресенья )
и по каждому маршруту у нас имеется таблица
rt01, rt02, ..., rt34 ( приведу пример лишь для первого
маршрута )
table rt01
curent int(4) |
stop_name int(4) |
time_string
varchar(250) |
1 |
26 |
;7:00;8:00;9:00;10:00;11:00;12:00;13:00;14:00; |
2 |
91 |
;7:03;8:03;9:03;10:03;11:03;12:03;13:03;14:03; |
3 |
54 |
;7:07;8:07;9:07;10:07;11:07;12:07;13:07;14:07; |
4 |
69 |
;7:11;8:11;9:11;10:11;11:11;12:11;13:11;14:11;15: |
............ |
.............. |
............................................ |
24 |
99 |
;7:49;8:49;9:49;10:49;11:49;12:49;13:49;14:49; |
25 |
26 |
;7:51;8:51;9:51;10:51;11:51;12:51;13:51;14:51; |
где показан порядковый номер остановки ( int ) , ID
этой остановки ( int ) и строка ( string ) в которой
перечисленно время в которое данный автобус
останавливается на каждой остановке.
Необходимо определить на каком автобусе можно
доехать до нужной останвки, а если невозможно на
одном, то на какой остановке пересесть на другой
маршрут. Возможность двух пересадок
рассматривать не будем, так как на скрипте такие
вычисления гонять неразумно - долго будет. Вся
необходимая информация - названия, времена
выдаётся пользователю.
Вытаскиваем ( из базы данных ) все автобусы
останавливаюшиеся на остановке start. Смотрим, а
можем ли добраться на каком нибудь из них до
остановки finish? Выдаём информацию, далее смотрим
все автобусы останавливающиеся на остановке finish
( не совпадающие с первым запросом ) и смотрим, а
где же можем пересесть на эти автобусы с тех, что
идут с остановки start. Выдаём результат. Вроде всё
просто, но запутаешься во всех этих переменных. И
другое дело если есть объект, который хранит всю
информацию о маршруте, и другой объект, хранящий
всю информацию о автобусной остановке, который
содержит массив объектов первого типа - маршруты.
Классы, по которым будем создавать эти объекты
назовём Route - маршрут, Bus_stop - остановка.
Получается что нам надо создать две переменных
типа Bus_stop - одна на остановку start и одна на
остановку finish. Ну а колличество объектов типа Route
в каждом объекте типа Bus_stop будет определяться
колличеством останавливающихся на этой
остановке маршрутов. При данном подходе
оперируем на уровне объектов, то есть переменных
немного и всё наглядно. При необходимости
вытаскиваем нужную информацию из объекта.
Ну а как это работает:
Файл choice.php3
<form action="find.php3" method=post >
<?php
$db = mysql_connect("localhost", "root");
mysql_select_db("BUS_STOP",$db);
$sql="select name from common ";
echo "<table><tr><td>Enter where are you</td>";
echo "<td>Enter Destination</td></tr>";
echo "<tr><td>";
$result = mysql_query($sql,$db); //выбрали
имена остановок из ДБ
echo "<select
name="place_is" size=10>";
while($myrow=mysql_fetch_row($result)) {
echo "<option>$myrow[0]"; }
echo "</select>";
echo "</td><td>";
$result = mysql_query($sql,$db); //выбрали имена остановок из ДБ
echo "<select name="place_targ" size=10>";
while($myrow=mysql_fetch_row($result)) {
echo "<option>$myrow[0]"; }
echo "</select>";
echo "<td></tr></table>";
mysql_close();
?>
<br><input type="submit" value="find all available
routes">
</form>
генерит картинку
и позволяет пользователю задать пункт
отправления и пункт назначения. Данные, понятное
дело, выбираются из базы данных ( ну не писать же
дважды по сотне остановок в html форме ),
оформляются в виде стандартной формы, ну а запрос
пользователя пересылаем в файл
find.php3
<?php
include "functions.php3";
echo "<br>Need from: $place_is To: $place_targ ";
$day=get_day();
echo" DAY - $day";
get_result($place_is, $place_targ);
?>
с которым то же всё просто - выдать на экран
некоторую контрольную информацию - день недели и
запустить собственно программу get_result(...).
Основной код - в файле functions.php3.
Функция get_result($start, $finish)
открывает базу данных и создаёт две переменных
типа Bus_stop.
$db = mysql_connect("localhost",
"root");
mysql_select_db("BUS_STOP",$db);
$routes_start=new Bus_stop($start, $db);
$routes_finish=new Bus_stop($finish, $db);
mysql_close();
При создании каждой переменной этого типа
запускается constructor, извлекаеся нужная информация
об этой автобусной остановке из базы данных, с
помощью вспомогательной функции cut_str(...)
строка,где перечисленны все останавливающиеся
здесь автобусы, разделяется на составляющие и в
результате получаем массив названий
автобусов,которые останавливаются на этой
остановке.
function Bus_stop($name, $db) {
$this->name_busstop=$name;
$sql="select id_stop, routes_string";
$sql="$sql from common_2, common";
$sql="$sql where name='$name' and
id_stop=id";
if($result = mysql_query($sql,$db)) {
$que=mysql_fetch_row($result);
$que[]=mysql_num_rows($result); //last element
for control
}
$this->id_busstop=(int)$que[0];
$real_n=cut_str($que[1]); //get all real names
for routes stoped
После чего контрольный вывод этих самых имён.
Теперь в цикле создаём объекты типа Route и
упаковываем их в массив
for($ll=0; $ll<$k;
$ll++) {
$this->route[$ll]=new
Route($real_n[$ll],$db);
$this->number_routes++;
}
Tак же constructor класса Route получает имя
маршрута и по нему, извлекая нужную информацию из
базы данных, создаёт объект - переменную этого
типа.
function Route($name, $db) {
global $day_now;
$sql="select prog_name, $day_now";
$sql="$sql from routes";
$sql="$sql where real_name='$name'";
if($result = mysql_query($sql,$db)) {
$que=mysql_fetch_row($result);
$que[]=mysql_num_rows($result); //last element
for control
}
$this->name_route=(string)$name;
$this->id_route=$que[0];
$this->rout_today=(string)$que[1];
if($que[1]=="y") {
//do you have this rout today ?
$sql="select stop_name, time_string";
$sql="$sql from rt$que[0]";
if($result = mysql_query($sql,$db)) {
$k=0;
while ($myrow = mysql_fetch_row($result)) {
$r_stop[$k]=(int)$myrow[0];
$r_times[$k]=$myrow[1];
$k++;
}
$this->rout_stop=$r_stop;
$this->rout_times=$r_times;
$this->number_stop=$k;
}}
В итоге имеем две переменных - $routes_start содержит
всё о остановке start, другая $routes_finish о остановке finish.
Теперь, для поиска автобусов, на которых можем
добраться от start до finish, вызываем функцию
find_direct(...) принадлежащую объекту остановки start,
передав в неё ID остановки finish. Ну и смотрим, есть
ли у маршрутов, на которые мы можем сесть на
остановке start остановка на которую нужно попасть,
но важно чтоб она была после того как мы сядем,
поскольку марщруты в основном кольцевые и
возвращаютсядругой дорогой. Если есть такая, то
нужная информация извлекается из объекта и
выдаётся пользователю.
function find_direct($id_stop_finish) {
$find=0;
for($i_rout=0; $i_rout<$this->number_routes; $i_rout++) {
$this_rout=$this->route[$i_rout];
if($this_rout->rout_today == "y")
{
$numb_stop=$this_rout->number_stop; // for
this route
$arr_id=$this_rout->rout_stop;
$i_stop_start=0;
do {
$id_bst=$arr_id[$i_stop_start];
if($id_bst ==
$this->id_busstop) break;
$i_stop_start++;
}
while($i_stop_start<$numb_stop);
$i_stop_finish=$i_stop_start;
do {
$id_bst=$arr_id[$i_stop_finish];
if($id_bst ==
$id_stop_finish) {
$id_first=$this->id_busstop;
$id_second=$id_stop_finish;
$name_rout=$this_rout->name_route;
$all_time=$this_rout->rout_times;
$time_start=$all_time[$i_stop_start];
$time_finish=$all_time[$i_stop_finish];
echo"<p> YOU
CAN USE ONE ROUT AND GET YOUR DESTINATION:";
echo"<br>Rout $name_rout will be on the start at time: $time_start";
echo"<br>And
on the destination will be at time: $time_finish";
$find++;
break;
}
$i_stop_finish++;
}
while($i_stop_finish<$numb_stop);
}
}
return $find;
}
А вот вторым шагом мы в объект типа Route,
созданный для остановки start передаём такой же
объект созданный для остановки finish как параметр
функции find_one_change(...), для поиска возможных
пересадок с маршрута который останавливается на
остановке start, на маршрут, останавливающийся на
остановке finish.
function find_one_change($routes_finish) {
$db = mysql_connect("localhost", "root");
mysql_select_db("BUS_STOP",$db);
$find=0;
$numb_startr=$this->number_routes;
$numb_finishr=$routes_finish->number_routes;
$all_startr=$this->route; // array of objects
$all_finishr=$routes_finish->route; // array of objects
$id_stop_finish=$routes_finish->id_busstop;
$id_stop_start=$this->id_busstop;
for($i=0; $i<$numb_startr; $i++) {
for($j=0; $j<$numb_finishr; $j++) {
$id_strout=$all_startr[$i]->id_route;
$id_fnrout=$all_finishr[$j]->id_route;
$today_finish=$all_finishr[$j]->rout_today;
$today_start=$all_startr[$i]->rout_today;
if($id_strout !=
$id_fnrout & $today_start == "y" & $today_finish == "y") {
$res=
find_able($all_startr[$i], $all_finishr[$j]);
if($res[3] != 0) {
echo"<p>we can reach destination use bus with change:";
$name_start=$all_startr[$i]->name_route;
$all_timestart=$all_startr[$i]->rout_times;
$prog_name=$all_startr[$i]->id_route;
$timestart_sit=$all_timestart[$res[0]];
$timestart_chg=$all_timestart[$res[1]];
$sql="select name";
$sql="$sql from common, rt$prog_name";
$sql="$sql where curent='$res[1]' and stop_name=id";
if($result = mysql_query($sql,$db)) {
$que=mysql_fetch_row($result);
$que[]=mysql_num_rows($result); //last element for control
}
$name_finish=$all_finishr[$j]->name_route;
$all_timefinish=$all_finishr[$j]->rout_times;
$timefinish_sit=$all_timefinish[$res[2]];
$timefinish_out=$all_timefinish[$res[3]];
echo"<br>On the start bus-stop sit on the $name_start rout which stop
here:";
echo"<br>$timestart_sit";
echo"<br>name BUS-STOP for change:$que[0]";
echo"<br>And Bus $name_start will be here at time:";
echo"<br>$timestart_chg";
echo"<br>on the Bus-stop $que[0] you have to sit on the";
echo"<br>next bus:$name_finish, which will be here at time:";
echo"<br>$timefinish_sit";
echo"<br>And you get your destination at time:";
echo"<br>$timefinish_out";
$find++;
}
}
}
}
mysql_close();
return $find; // number finded routes
}
}
Для работы этой функции привлекается
вспомогательная функция find_able(...) В которую
как параметр передаём объект - маршрут отходящий
от остановки start и объект - маршрут который
останавливантся на остановке finis. Проверям
возможность пересадки с первого на второй. При
этом для каждого автобуса отходящего от
остановки start сканируем по его становкам от
остановки посадки и смотрим, а есть ли такая же у
автобуса, который останавливается на остановке
finish. Если есть, то в возвращаемую переменную
$ret ( array ) записываем индексы для этой
остановки для первого и для второго $ret[1]=$i;
$ret[2]=$j; и потом смотрим, а есть ли у
финиширующего автобуса остановка назначения
после этой самой остановки пересадки. Если есть -
записываем $ret[3]=$j;
Отработав, функция возвращает $ret[] и если 4-й
элемент $ret ( $ret[3] ) равен 0, то
значит мы не можем пересесть с первого на второй
и достичь остановки назначения. Найдя искомую
остановку ( то есть ту, на которой
останавливаются и тот и другой маршруты ) по её ID
из базы данных получим имя, вся остальная
информация находиться в объектах и остаётся
только выдать её пользователю.
В данном случае не найдено прямого маршрута, то
есть на который мы можем сесть на остановке start и
добраться до остановки finish, но есть возможность
добраться до остановки назначения с пересадкой -
указан маршрут на который нужно сесть и строка
времён, кагда он останавливается здесь. Указана
остановка на которой необходимо сойти для
пересадки на другой маршрут и строка времён,
когда вы прибудете на неё. Далее такая же
информация про маршрут, на который следует
пересесть: строка времён, когда он бывает на
данной остановке и когда он останавливается на
остановке finish. В данном примере, несмотря на то
что маршрут 1 останавливается и на остановке start и
на остановке finish как возможный он не показан -
дело в том, что проходит он их в обратном для нас
порядке.
В фолдере create_tables найдёте всё необходдимое. На
Linux просто "руками" создайте базу данных
BUS_STOP, войдите в фолдер create_tables, файл createTables.sh
сделайте исполняемым и запустите его. Все
необходимые таблицы в BUS_STOP будут созданы и
заполнены. Скрипт createTables.sh использует файлы,
находящиеся там же, и если не получается - можно
руками, создать таблицы, заглядывая в файл
create_all_tables.dump и заполнить их используя файлы common,
common_2, routes и rt01, rt02, ..., rt34. Пользователям Windows видимо
так и придётся... :-( .
После установки базы данных BUS_STOP файлы choice.php3,
find.php3 и functions.php3 положить, как обычно, под Apache и
запустить choice.php3.
|