Как реализовать в данном случае модель MVC PHP

99
16 января 2021, 01:00

Есть код:

<?php
session_start();
if($_SESSION['hgi4gfus83br6G7kihk'])
  {
?>
<!DOCTYPE HTML>
<html>
<?php include_once('blocks/bootstrap_header.php'); ?>

    <body>
<?php include_once('blocks/menu.php'); ?>
      <?php
      session_start();
      if ($_SESSION['hgi4gfus83br6G7kihk'])
      {
        include_once ('function.php');
        $db = new Database;
        $scan = new Scan;
        if (isset($_POST['submit']))
        {
            unset($_POST['submit']);
            $db->update('offices', $_POST, 'id_office = ' . $_GET['id']);
            header("Location: info.php?city=" . $_GET['city'] . "&id=" . $_GET['id']);
        }
        if (isset($_GET['city']) && isset($_GET['id']) && isset($_GET['edit']))
        {
            echo '<form name="office" method="post">';
            echo '<table class="table">';
            foreach($db->select('offices', '*', '', "city_office='" . $_GET['city'] . "' AND " . "id_office=" . $_GET['id']) as $key => $value)
            {
                foreach($value as $key2 => $value2)
                {
                    echo '<tr>';
                    echo '<td>' . $key2 . '</td><td><input type="text" name="' . $key2 . '" value="' . $value2 . '"></td>';
                    echo '</tr>';
                }
            }
            echo '<tr>';
            echo '<td><input type="submit" name="submit" value="Записать"></td>';
            echo '</tr>';
            echo '</table>';
            echo '</form>';
        }
        elseif (isset($_GET['city']))
        {
            if (isset($_GET['id']))
            {
                echo '<table class="table">';
                echo '<tr>';
                echo '<th scope="col">Адрес</th>';
                echo '<th scope="col">Код</th>';
                echo '<th scope="col">Ноутбук</th>';
                //echo '<th scope="col">Teamviewer</th>';
                echo '<th scope="col">Mikrotik</th>';
                echo '<th scope="col">IP адрес</th>';
                echo '<th scope="col">VNCFA</th>';
                echo '<th scope="col">VNCVO</th>';
                echo '<th scope="col">VNCA</th>';
                echo '<th scope="col">Телефон</th>';
                echo '</tr>';
                foreach($db->select('offices', '*', '', "city_office='" . $_GET['city'] . "' AND " . "id_office=" . $_GET['id']) as $value)
                {
                    echo '<td>' . '<a class="first" href="http://' . substr_replace($value['ip_office'], 10, -1) . ':5901" target="_blank">' . $value['type_street_office'] . ' ' . $value['street_office'] . ' ' . 'дом' . ' ' . $value['house_office'] . '</a></td>';
                    echo '<td>' . $value['code_office'] . '</td>';
                    echo '<td>' . $value['pwd_notebook_office'] . '</td>';
                    //echo '<td>' . $value['pwd_teamviewer_office'] . '</td>';
                    echo '<td>' . $value['pwd_mikrotik_office'] . '</td>';
                    echo '<td>' . '<a href="http://' . $value['ip_office'] . '" target="_blank">' . $value['ip_office'] . '</a></td>';
                    echo '<td>' . $value['pwd_vnc_full_acces_office'] . '</td>';
                    echo '<td>' . $value['pwd_vnc_view_only_office'] . '</td>';
                    echo '<td>' . $value['pwd_vnc_administrator_office'] . '</td>';
                    echo '<td>' . $value['telephone_office'] . '</td>';
                    echo '<a class="btn btn-primary" href="info.php?city=' . $_GET['city'] . '&id=' . $_GET['id'] . '&edit=true" role="button">Изменить</a>';
                }
              echo "</table>";
            if(isset($_POST['add'])){
              unset($_POST['add']);
              $db->insert('logs_offices', $_POST);
            }

            echo '<form class="form-inline" method="post">';
            echo '<div class="form-group mb-2">';
              echo '<input type="hidden" value="' . $_GET['id'] . '" name="id_office_log_office">';
              echo '<input class="form-control" type="text" name="text_log_office">';
              echo '<button type="submit" class="btn btn-primary" name="add" >Добавить комментарий</button>';
            echo '</div>';
            echo '</form>';
            echo '<table class="table">';
            echo '<thead>';
            echo '<tr>';
                echo '<th scope="col">Коментарий</th>';
                echo '<th scope="col">Время</th>';
            echo '</tr>';
            echo '</thead>';
            echo '<tbody>';
            foreach ($db->select('offices, logs_offices', '*', '', 'id_office="' . $_GET['id'] . '" AND id_office_log_office=' . $_GET['id'], 'datetime_log_office DESC') as $val)
            {
              echo '<tr>';
              echo '<td>' . $val['text_log_office'] .  '</td>';
              echo '<td>' . $val['datetime_log_office'] .  '</td>';
              echo '</tr>';
            }
            echo '</tbody>';
            echo '</table>';
            }
            else
            {
                echo '<table class="table">';
                echo '<tr>';
            echo '<th scope="col">Номер отделения</th>';
                echo '<th scope="col">Адрес</th>';
                echo '<th scope="col">Телефон</th>';
                echo '</tr>';
                foreach($db->select('offices', '*', '', "city_office='" . $_GET['city'] . "'") as $value)
                {
                    echo '<tr>';
              echo '<td>' . $value['number_office'] . '</td>';
                    echo '<td>' . '<a class="first" href="info.php?city=' . $value['city_office'] . '&id=' . $value['id_office'] . '">' . $value['type_street_office'] . ' ' . $value['street_office'] . ' ' . 'дом' . ' ' . $value['house_office'] . '</a></td>';
                    echo '<td>' . $value['telephone_office'] . '</td>';
                    echo '</tr>';
                }
                echo "</table>";
            }
        }
        else
        {
            echo '<table class="table">';
            echo '<tr>';
            echo '<th scope="col">Город</th>';
            echo '</tr>';
            foreach($db->select('offices', '*', '', '', 'city_office') as $value)
            {
                echo '<tr>';
                echo '<td><a href="info.php?city=' . $value['city_office'] . '">' . $value['city_office'] . '</a></td>';
                echo '</tr>';
            }
            echo "</table>";
        }
      }
      else
      {
        header("Location: index.php");
        exit;
      }
      ?>
    </body>
</html>
<?php
}
else
{
  header("Location: index.php");
}
?>

Этот код выполняет следующую задачу. После авторизации я попадаю на некую страницу в которой вижу список городов. Кликнув по городу, я вижу список филиалов, кликнув по филиалу, я вижу данные по этому филиалу. Сейчас задался целью сменить дизайн и подвязать к сетке bootstrap, но написанный мной ранее код оказался ужасным. Проблему усугубляет еще и тот факт, что я никак не могу понять принципы MVC и применять их. Из-за этого такая каша получается. Каким образом его можно структурировать согласно шаблона проектирования MVC? Заранее спасибо за любую помощь. Если сможете на пальцах объяснить мне, как именно на данном примере этот паттерн применяется, то вообще цены Вам не будет :)

Answer 1

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

Да, какие-то примитивные вещи можно подхватить на лету, посмотрев пару видео в интернете и задав пару вопросов на форуме. Да, по началу привыкаешь, что все просто: надо поработать с БД? Опа, вот видео. Надо поработать с ХТМЛ? Опа, вот туториал. Надо поработать с MVC? Опа...

Но надо понимать, что просто будет только в начале. И есть темы, которые невозможно "объяснить на пальцах". Просто физически не хватит места в ограниченном по размеру ответе. В частности потому, что есть такое правило: чтобы понять ответ, надо уже знать его большую часть.

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

  • Единая точка входа (когда к скриптам идет обращение не к каждому по отдельности напрямую, а все запросы обрабатываются единым скриптом)
  • Роутер (скрипт который по запросу определяет, какой контроллер будет его обрабатывать)
  • Контроллер (код, который принимает запрос и перенаправляет его в модель)
  • Модель (которая реализует собственно логику приложения, я писал об этом здесь)
  • View (компонент, который отвечает за вывод ХТМЛ)

Все это вместе будет составлять довольно немаленький фреймфорк. И в рамках ответа на Стак оверфлоу просто невозможно рассказать, как сделать MVC фреймворк.

Поэтому MVC мы пока отложим в сторону и разберем более понятную концепцию - отделение бизнес-логики от представления.

Основная проблема этого кода в том, что в нем перемешана работа с БД и вывод данных. Вот для начала надо разделить их

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

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

Отдельным пунктом надо в ужасе выкинуть на свалку класс Database и для начала научиться работать с PDO через подготовленные выражения.

После того как сделаешь это, сможешь двигаться дальше по долгой дороге в сторону MVC

Answer 2

MVC - про то как разграничить архитектуру приложения.

На вашем примере у вас один жирный файл и это плохо, а почему? потому что человеку, который будет смотреть на ваш код придётся потратить около часа для дебага и понимании того, как это работает, зачем ему дебажить ваш код, когда можно сразу сделать понятно для всех, чтобы при прочтении названия функции или переменной было понятно, что она делает. Другой пример как уже написали выше html не хранят в выполняемой логике это плохая практика. Ещё пример, когда придётся добавить новую возможность в ваш код (например нужно получать ещё информацию из стороннего сервиса и отображать её ниже), сколько у вас займёт это время? а сколько бы заняло если будет понятно, какой бизнес объект за что отвечает и у кого какая зона ответственности, чтобы дальнейшая поддержка кода не съедала всё больше и больше времени, а наоборот экономила.

Итак, про MVC, как же правильно построить начальную архитектуру.

Обозначим, что

M - Model отвечает у нас за всю выполняемую бизнес-логику, будь то запрос в БД, сортировка списка, хранение данных в сессии, работа с данными из $_GET $_POST.

V - View отвечает за отображение html.

C - Controller отвечает за управление всего этого в том числе вызов бизнес-логики и передача данных во view

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

модели в - app/models/

контроллеры в - app/controllers/

вьюшки в - app/views/

Я постарался объяснить своё виденье MVC, возможно у более опытных будут вопросы, но я попытался не трогать принципы проектирования и описать всё понятным языком для новичка.

READ ALSO
laravel 5.8 data base query Builder

laravel 5.8 data base query Builder

Есть поле дата формата Y-m-d пример заполниной таблицы ID Date 1 2019-05-19 2 2019-05-30 3 2019-05-22 4 2019-06-03

118
Передача значения поля БД в backgroundImage div&#39;a в js функции

Передача значения поля БД в backgroundImage div'a в js функции

У меня имеется большое поле (div), в котором находятся 12 div меньшего размераПри нажатии на кнопку, вызывается функция js, которая чистит большое...

107
Как выбрать нужное поле из базы данных?

Как выбрать нужное поле из базы данных?

Логика такая: Пользователь проходит тест на стороне клиента, в результате прохождения которого зарабатывает "score"В конце, с помощью AJAX запроса...

101
Не работает форма обратной связи на beget

Не работает форма обратной связи на beget

Не работает форма обратной связи (не приходят сообщения на почту), хотя сообщения на локальном сервере отправляетКод в форме html:

92