Приветствую всех! В данной статье я расскажу про процесс создания собственного школьного электронного журнала.
С чего все началось? Началось всес того, что я купил книгу по PHP/MySQL, поскольку давно увлекался проектами на школьную тематику, те же электронные журналы. После пары прочтенных страниц я сел за проект. Проект получил название АИС «Школьник» (Автоматизированная Информационная Система «Школьник»).
Какова была главная цель проекта? Главной целью проекта стала реализация системы, чтобы ей могли пользоваться бесконечное количество школ и были органы управления, которые могли создавать школы и просматривать их статистику (об этом расскажу ниже).
Первым делом я накидал простенькую шапочку на главную страницу:

И простенькую форму для входа:

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

В разделе «Моя школа» отображались сведения о школе — краткое наименование, полное наименование, почта директора, тип организации (школа/гимназия/лицей), ФИО директора, дата основания организации.
В разделе «Настройка школы» можно было добавить учеников, сотрудников, а также настроить предметы, которые преподаются в школе и классы.
В разделе «Настройка расписания» было все для составления расписания: схемы звонков, схемы периодов (границы четвертей), схемы расписания, нагрузка по преподавателям.
Как были реализованы периоды и звонки на тот момент?
На тот момент можно было создать только одну схему периодов или звонков на школу. Вот как это работало:
<?php
// проверяем на наличие созданной схемы периодов
$res = $conn->query("SHOW TABLES LIKE `{название_школы}_periods`");
if($res->num_rows > 0){
echo "Периоды уже созданы!";
} else{
echo "<a href='#'>Создать схему</a>";
}
?>
С звонками точно также, только вместо {название_школы}_periods - {название_школы}_calls.
Таблица periods:
CREATE TABLE `school_periods`(
"period1_to" DATE NOT NULL,
"period1_from" DATE NOT NULL,
"period2_to" DATE NOT NULL,
"period2_from" DATE NOT NULL,
"period3_to" DATE NOT NULL,
"period3_from" DATE NOT NULL,
"period4_to" DATE NOT NULL,
"period4_from" DATE NOT NULL
)
Да, настолько это было неудобно с серверной части. Я потом пожалел, что сделал так (об этом ниже).
Таблица calls:
CREATE TABLE `school_calls`(
"dayid" INTEGER NOT NULL,
"from" TIME NOT NULL,
"to" TIME NOT NULL
)
Со звонками было все намного проще, однако не было разделений на разные дни (т. е. в понедельник уроки могли начинаться с 8:00, а во вторник с 8:30).
Настройка школы
Выше было сказано, что в разделе «Настройка школы» были пункты: ученики, сотрудники, предметы. В пунктах «Ученики» и «Сотрудники» можно было добавлять персон:

Да, тогда директор самостоятельно задавал логин и пароль каждому учителю. У учеников была такая‑же форма, но при этом добавились пункты «Дата рождения» и «Класс».
Настройка расписания
Для начала нужно составить расписание звонков. Пользователю необходимо было ввести максимальное количество уроков в день. После этого на экране отображалась форма (код ниже), которую можно было заполнить 1 раз без возможности редактирования (тогда я еще не знал про AJAX и старался не использовать JS, не знаю почему, возможно, из‑за того, что я только начал писать проект и не знал о всех тонкостях. А жаль :-) Если что‑то было введено неверно, то можно либо заполнить форму заново, либо сохранить текущую схему и пересоздать её.
<?php
$lessonsAtDay = 5; // количество уроков в день. значение передавалось из формы.
echo "<form>";
foreach($lessonsAtDay as $i){
echo "Урок $i: <input type='time' name='$i-from'>-<input type='time' name='$i-to'>";
}
echo "<br><input type='submit' value='Применить'></form>";
?>

В итоге сама схема звонков выглядела так. Да, дизайн не очень, но вскоре таблицу уменьшили в размерах и поменяли цвет. Формат отображения времени на фото: ЧЧ:ММ:СС, вскоре было изменено на ЧЧ:ММ.
С периодами было все намного хуже, сейчас расскажу почему. Во‑первых, структура таблицы периода — вы ее могли наблюдать выше. Из‑за этого было очень трудно сделать гибкую систему создание периодов (чтобы пользователь мог делать не только четверти, но и семестры или полугодия). Во‑вторых, периоды нельзя было пересоздать! То есть, если вы допустили ошибку при указании даты, вы не сможете её поменять.
Нагрузка была самой легкой из данного раздела.

Здесь было все просто. Я сделал форму с выбором класса, а потом предмета и его преподавателя, который проводится в классе:
// Пример вывода списков предметов и преподавателей
<?php
require "config.php";
if(isset($_POST["group"])){
// вывод предметов
$res = $conn->query("SELECT `lesson` FROM `lessons` WHERE `school` = '$currentschool'"); // currentschool находится в конфиг-файле
echo "<select>";
foreach($res->fetch_assoc() as $lesson){
echo "<option>$lesson</option>";
}
echo "</select>"
$res = $conn->query("SELECT `fullname` FROM `users` WHERE (`role` = 'Учитель' OR `role` = 'Завуч' OR `role` = 'Директор') AND `school` = '$currentschool'"); // currentschool находится в конфиг-файле
echo "<select>";
foreach($res->fetch_assoc() as $teacher){
echo "<option>$teacher</option>";
}
echo "</select>"
}
?>
Таблица, где хранилась вся назначенная нагрузка называлась workload
:
CREATE TABLE `workload`(
"lesson" TEXT NOT NULL,
"teacher" TEXT NOT NULL,
"group" TEXT NOT NULL,
"school" TEXT NOT NULL
)
Во всех таблицах, которые не принадлежат определенной школе (с названием {school}_*
) всегда есть столбец school
. Это сделано в целях того, чтобы у каждой школы отображалась только своя информация (или же со значением названия данной школы)
В данном случае нагрузка была удобной и гибкой, ведь если нужно внести какие-либо изменения в структуру таблицы, то не нужно было лезть во все таблицы, созданные школами.
Время перейти к самому составлению расписания. Его я оттягивал очень долго, ведь этот пункт был самым сложным для меня, но сроки были все меньше и надо было сделать много чего, поэтому я принял решение сделать расписание, но это было не в привычном нам понимании: создал схему, расставил уроки и опубликовал. Каждый преподаватель должен был самостоятельно создавать уроки. Понимаю, что это неудобно, но вот, как это выглядело:


Учтите, что можно было выбрать не любой предмет, а только тот, который ведет преподаватель.
SELECT `lesson` FROM `workload` WHERE `teacher` = 'текущее ФИО' AND `school` = 'текущая школа'

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

Конечно же про AJAX тогда и речи не шло, хотя попытки реализации были. Но из-за маленьких знаний, а точнее, нулевых знаний я не смог реализовать это. В итоге пришлось сделать такие кнопки.
В разделе "Добавить урок" была форма: номер, предмет, день недели.
В разделе "Удалить урок" была такая же форма.
А вот уже в разделе "Публикация" была ссылка которая вела на публикацию схемы. Опубликовать можно было только на одну неделю, и период приходилось выбирать самостоятельно. Автоматического тогда ничего не было.
Все схемы расписания хранились в таблице {название_схемы}_scheme
Журнал
Пример журнала я брал из старой версии Дневника.Ру:

Тогда все‑таки пришлось использовать AJAX, чтобы при каждом изменении не нажимать на кнопку «Сохранить». Это было моим единственным правильным решением на тот момент. Над дизайном тогда нужно было еще работать и работать. Уточню, что редактировать оценки можно было только на странице урока, несмотря на наличие главной страницы:

Выделю минус, что на данной странице не отображались уроки, по которым оценки не выставлены (в том числе и пропуски). 21 сентября я начал готовить журнал к публикации в народ, 1 октября система была уже для всех доступна.
Органы управления
Органы управления могли зарегистрировать школы, которые желали поучаствовать в бета‑тестировании с 15 сентября 2024 года. За 2 дня после открытия доступа было зарегистрировано более 10 школ, что для меня тогда считалось значимым результатом.
У органов управления были функции просмотра статистики школ, заморозки школ (блокировки доступа), удаление и создание школ, изменения пароля от аккаунта директора.
Также, я планировал сделать просмотр журналов школ, но не смог (об этом расскажу ниже).
Главная страница
Я считаю, что на каждом сайте должна быть своя главная страница, которая рассказывала о всех преимуществах. Я решил тоже сделать главную страницу. И была она больше рассчитана под какой‑нибудь детский сайт...

Да и сам сайт выглядел по-детски. Всему вина шрифта Montserrat, который я в будущем сменил на Lato.
Развитие проекта
Еще во время разработки проекта у меня появилась своя аудитория, которая следила за проектом. После выпуска журнала посыпались, как плохие отзывы, так и хорошие, но больше было хороших. Также, обнаружилось большое количество багов, которые я исправлял еще несколько недель. Тогда обновления выходили чуть ли не по 2 раза в день.
В самом первом обновлении я добавил публичный реестр органов, возможность комментирования органов, отправки жалобы на комментарии, а также возможность выхода из аккаунта (да, раньше такого не было и приходилось ждать сутки, чтобы закончилась сессия).
Спустя несколько обновлений, я добавил возможность редактирования оценок со страницы самого журнала:

Все шло хорошо, я добавил вход через Яндекс, Телеграмм, ВК. Но с каждым разом разработка обновлений становилась все хуже и хуже, а причиной этому была структура таблиц в БД, о которых я рассказывал выше. Поэтому, я принял решение полностью переписать проект, но уже не на PHP, который я практически не знал, а на Python с использованием Django, поскольку Python был самым родным языком. Однако, я не знал Django и я в этот же вечер, когда закрыл проект, сел изучать Django.
Итог
С августа разработки системы у журнала появилась своя аудитория, которая активно следит за обновлениями и предлагает свои идеи. Сейчас журнал находится на стадии переписывания на другой язык программирования. Кому интересно, тот может ознакомиться с проектом на PHP на Github.
Автор: timursper