Так получается что мой сайт mzcoding.com 3й раз меняет домен и движок и всегда при запуске нового сайта я обновлял статью по написанию Личного кабинета на PHP! В далеком 2010 это был простой ЛК на PHP 5.0, в 2014 это был ЛК 2.0 где мы обновили версию языка и код и добавили несколько плюшек. И вот настал 3й раз в этой и следующей статье мы напишем полноценный кабинет пользователя с регистрацией, авторизацией и базовым ЛК с модерацией! Разработку мы будем вести с применением PHP7 и Bootstrap 4, а так-же с применением некоторых компонентов symfony.

Первым делом создадим каталог с наименованием lk, далее откроем терминал по адресу данной папки и введем:

composer init

 

У вас должен быть глобально установлен composer, что это такое и как это сделать можно прочесть тут.

Далее composer просит ввести наименование пакета! Я назову его mzcoding/lk. Далее будут еще несколько пунктов описание, автор (можете указать их на свое усмотрение). Опция Minimum Stability Укажите dev. Далее оставляйте значения по умолчанию!

Установка пакета

В конце у вас спросят, хотите ли вы установить какие либо зависимости? Вводим no. В итоге будет создан файл composer.json со следующим содержимым:

{
    "name": "mzcoding/lk",
    "description": "Demo lk",
    "type": "project",
    "license": "mit",
    "authors": [
        {
            "name": "stanislav",
            "email": "mzcoding@gmail.com"
        }
    ],
    "minimum-stability": "dev",
    "require": {}
}

 

Шаг 2 - Настройка зависимостей

Теперь установим необходимые нам в работе библиотеки, первым делом установим http компоненты от symfony. Введем в терминале:

 

composer require symfony/http-foundation

После установки данного пакета, установим еще один, это будет контейнер зависимостей DI. В качестве контейнера будем использовать библиотеку от разработчиков symfony, pimple

Для установки выполним:

 

composer require pimple/pimple

Давайте взглянем на наш файл composer.json. Если все верно в секции require увидим что-то подобное:

"require": {
        "symfony/http-foundation": "^4.2@dev",
        "pimple/pimple": "^3.2@dev"
}

Версии библиотек могут отличаться!

Давайте сразу после секции require, добавим секцию autoload, там мы укажем где composer может искать файлы нашего приложения и автоматически их подключать, для всех этих файлов мы укажем единое пространство имен. Итоговый вариант файла composer.json должен выглядеть следующим образом:

{
    "name": "mzcoding/lk",
    "description": "Demo lk",
    "type": "project",
    "license": "mit",
    "authors": [
        {
            "name": "stanislav",
            "email": "mzcoding@gmail.com"
        }
    ],
    "minimum-stability": "dev",
    "require": {
        "symfony/http-foundation": "^4.2@dev",
        "pimple/pimple": "^3.2@dev"
    },
    "autoload": {
        "psr-4": {
            "App\\": "app/"
        },
        "files": [
            "helpers/helpers.php"
        ]
    }
}

Так-же давайте сразу создадим все необходимые каталоги.

app - Содержит все файлы/каталоги отвечающие за логику нашего приложения.

assets - Список js/css/img файлов.

config - Файлы конфигурации приложения.

helpers - Каталог с файлом helper.php который хранит вспомогательные функции.

 

Шаг 3 - Создаем структуру проекта

Все наши приготовления готовы! Теперь создадим точку входа нашего проекта, в корне проекта создадим файл index.php со следующим содержимым:

 <?php
session_start();
require_once __DIR__ . '/vendor/autoload.php';
$config = include (__DIR__ . '/config/config.php');
define("ROOT_PATH", __DIR__);

 //Отлавливаем все эксеппшены, так-же можно логировать в будущем
try{
    //Initial request
    $request = \Symfony\Component\HttpFoundation\Request::createFromGlobals();
    //DI контейнер
    $container = new Pimple\Container();
    $container['config'] = $config;
    //Request data
    $container['request'] = $request;
    //Sessions
    $container['session'] = $container->factory(function ($c) {
        $session = new \App\Classes\Session();
        return $session;
    });
    //БД
    $container['db'] = function () use(&$config) {
        $host = $config['db']['host'] ?? 'localhost';
        $database = $config['db']['database'] ?? 'postgres';
        $user = $config['db']['user'] ?? 'postgres';
        $password = $config['db']['password'] ?? '';
        $port = $config['db']['port'] ?? '5432';

        $dsn = "pgsql:host=$host;port=$port;dbname=$database;user=$user;password=$password";

        $dbh = new PDO($dsn);
        if($dbh){
            $log =  "Connected to the <strong>$database</strong> database successfully!";
        }
        return $dbh;
    };


    //Инициализируем вход
    (new App\Router($container))->init();
}catch(\App\Exceptions\LkException $e){
    echo $e->getMessage();
}catch (PDOException $e){
     echo $e->getMessage();
}catch(\Exception $e) {
    echo $e->getMessage();
}

Давайте разберемся, что мы делаем в данном файле.

Первым делом мы инициализируем сессию, думаю тут все понятно. Далее мы подключаем наши зависимости:

require_once __DIR__ . ‘/vendor/autoload.php';

 

Подтягиваем конфигурацию из файла конфига и устанавливаем глобальную константу на текущий каталог.

Далее мы открываем конструкцию try-catch тем самым отлаживая возникшие выше в коде исключительные ситуации. Обратите внимание в данном примере мы создали свой тип исключений LkException.

В блоке try мы инициализируем (получаем) все запросы (requests), а так-же инициализируем контейнер зависимостей (DI).

Далее мы добавляем в данный контейнер, конфигурацию проекта:

$container['config'] = $config;

Глобальный Request:

$container['request'] = $request;

Экземпляр класса Session (данный класс опишем немного позже)

$container['session'] = $container->factory(function ($c) {
        $session = new \App\Classes\Session();
        return $session;
});

Обратите внимание на конструкцию добавления. Мы используем метод factory нашего контейнера, что позволяет нам получать новый экземпляр объекта данного класса каждый раз при его обращении, что соответственно позволит нам постоянно перегружать сессию при каждом запросе.

Далее мы передаем в наш контейнер подключение к БД (с помощью PDO). В нашем случае мы присваиваем переменной контейнера, анонимную функцию, которая подключается к базе и возвращает объект PDO.

//БД
$container['db'] = function () use(&$config) {
        $host = $config['db']['host'] ?? 'localhost';
        $database = $config['db']['database'] ?? 'postgres';
        $user = $config['db']['user'] ?? 'postgres';
        $password = $config['db']['password'] ?? '';
        $port = $config['db']['port'] ?? '5432';

        $dsn = "pgsql:host=$host;port=$port;dbname=$database;user=$user;password=$password";

        $dbh = new PDO($dsn);
        if($dbh){
            $log =  "Connected to the <strong>$database</strong> database successfully!";
        }
        return $dbh;
};

В качестве примера мы используем БД PostgreSql.

И в завершении мы передаем текущий процесс в другой метод, а именно вызываем метод:

(new App\Router($container))->init();

Тут мы вызываем метод init класса Router предварительно передав наш инициализированный контейнер в конструктор класса.

Что-ж далее нам нужно создать класс Router, который примет управление текущим процессом.

Создадим файл Router.php в каталоге app:

<?php namespace App;
 
 class Router 
 {
     private $controller, $action, $container;
     public function __construct($container)
     {
        $request = $container['request'];

        $this->container = $container;
        $controller = $request->get('c') ?? 'Login';
        $this->controller = ucfirst($controller)."Controller";
        $this->action = $request->get('a') ?? 'index';

     }

     /**
      * Подключаем классы динамически
      */
     public function init()
     {
        $className = 'App\\Controllers\\' . $this->controller;

        if(!class_exists($className)) {
            abort404();
        }
        $objController = new  $className($this->container);
        $objController->{$this->action}();
     }
 }

 

Тут все просто, при каждом запросе мы будем передавать наименование контроллера и метода (action) которые будут вызваны. Допустим мы хотим создать новый контакт, url на форму создания нового контакта может выглядеть следующим образом:

http://localhost:8000/index.php?c=contact&a=create

Система увидев такой код, вызовет метод create() у класса ContactController.php.

Теперь давайте опилим вспомогательный класс сессий, который мы использовали выше! Этот класс просто представляет собой обертку над глобальным массивом сессий. Создадим каталог Classes и добавим туда новый файл Session.php.

<?php
namespace App\Classes;

class Session
{
   public function has($key) : bool
   {
       if(isset($_SESSION[$key])) {
           return true;
       }

       return false;
   }
   public function put($key, $value)
   {
       $_SESSION[$key] = $value;
   }
   public function get($key)
   {
       if($this->has($key)) {
           return $_SESSION[$key];
       }

       return null;
   }
   public function forget($key): bool
   {
       if($this->has($key)) {
           unset($_SESSION[$key]);
           return session_destroy();
       }
       return false;
   }
}

 

Шаг 4: Контроллеры и модели

Теперь добавим дамп таблицы для пользователей которые будут регистрироваться/авторизовываться!

DROP TABLE IF EXISTS `city`;

CREATE TABLE `city` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `region_id` int(11) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



# Dump of table country
# ------------------------------------------------------------

DROP TABLE IF EXISTS `country`;

CREATE TABLE `country` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



# Dump of table region
# ------------------------------------------------------------

DROP TABLE IF EXISTS `region`;

CREATE TABLE `region` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `country_id` int(11) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



# Dump of table users
# ------------------------------------------------------------

DROP TABLE IF EXISTS `users`;

CREATE TABLE `users` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(191) DEFAULT NULL,
  `surname` varchar(191) DEFAULT NULL,
  `email` varchar(191) NOT NULL DEFAULT '',
  `phone` varchar(191) DEFAULT NULL,
  `address` varchar(191) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  

Теперь давайте опишем систему аутентификации! Начнем с модели Создадим в каталоге Models базовую модель Model.php:

<?php
namespace App\Models;


class Model
{
   protected $db, $table;
   public function __construct(\PDO $db)
   {
       $this->db = $db;
   }

    /**
     * Вывод любых данных
     * @return array
     */
    public function getData()
    {

        $query = $this->db->query("SELECT * from {$this->table}");

        return $query->fetchAll();
    }
    public function getItem(int $id)
    {
        $query = $this->db->query("SELECT * from {$this->table} 
                                            WHERE id = $id");
        return $query->fetchObject();
    }

    /**
     *  Добавление любых данных
     * @param array $params
     * @return bool|object
     */
    public function insertData(array $params)
    {
        $values = [];
        $out = "";
        $i = 0;
        foreach($params as $key => $value) {
            $values[] = $value;
            $out .=  ($i) ? ",?" : "?"; $i++;
        }

        $sqlPrepare = "INSERT INTO users(".implode(",",
                array_keys($params)).")
                             VALUES($out)";

        $statement = $this->db->prepare($sqlPrepare);
        $status = $statement->execute($values);

        if($status) {
            $id = $this->db->lastInsertId();
            return $this->getItem($id);
        }
        return $status;
    }
}

Думаю здесь все понятно из комментариев, мы просто описываем базовые методы для всех моделей!

Давайте начнем с пользователей и создадим модель Users:

<?php
namespace App\Models;

class User extends Model
{
   protected $table = "users";
   public function IsRefreshStatus($user): bool
   {
      $id = (int)$user->id;
      $status = $user->status;
      $sql = "SELECT status FROM users WHERE id = $id";
      $query = $this->db->query($sql);
      $r = $query->fetchObject();

       if((bool)$r->status !== $status) {
           $user->status = (bool)$r->status;
           return true;
       }

       return false;
   }
   public function IsRefreshAdmin($user): bool
   {
       $id = (int)$user->id;
       $isAdmin = (bool)$user->isadmin;

       $sql = "SELECT isadmin FROM users WHERE id = $id";
       $query = $this->db->query($sql);
       $r = $query->fetchObject();

       if((bool)$r->isadmin !== $isAdmin) {
           return true;
       }

       return false;
   }

    /**
     * @return array
     */
   public function getUsersForFalseStatus()
   {
       $sql = "SELECT * FROM users WHERE status = false";
       $query = $this->db->query($sql);
      return $query->fetchAll();

   }
   public function login($email, $password)
   {
       $sql = "SELECT * FROM users WHERE email = '".$email."' 
               AND password = '".$password."'";
       $query = $this->db->query($sql);
       $result = $query->fetchObject();

       return $result ?? null;
   }

   public function status(int $id, bool $status) //: void - for php 7.1 or higher
   {
       $sql = "UPDATE users SET status=? WHERE id=?";
       $stmt = $this->db->prepare($sql);
       $stmt->execute([$status, $id]);
   }
}

Когда у нас описана модель мы можем приступить к логики приложения и сделать систему регистрации/авторизации пользователей!

Первым делом как и с моделями мы создадим базовый контроллер, для этого добавим каталог Controllers и добавим в него файл BaseController.php:

<?php 
 namespace App\Controllers;

 use App\Exceptions\LkException;

 class BaseController
 {
     protected $di;
     public function __construct($di)
     {
         //Уточняем что пришел именно нужный нам объект
         if($di instanceof \Pimple\Container) {
             $this->di = $di;
         }else{
             abort404();
         }

     }
     /**
      * @return array
      */
     protected function getConfig(): array
     {
         if($this->di) {
             return $this->di['config'];
         }
         $config = include(ROOT_PATH . '/config/config.php');
         return $config;
     }

     /**
      * Генерация views и параметров
      * @param $file_name
      * @param array $params
      * @throws LkException
      */
     protected function view($file_name, array $params = [])
     {
         $ext = ".phtml";
         $path = __DIR__ . "/../Views/";
         if(!file_exists($path . $file_name.$ext)) {
             throw new LKException( "View file not found" );
         }

         ob_start();
         if($params) {
             extract($params);
         }
         $template = include($path . $file_name . $ext);
         echo $template;
         ob_get_contents();
         ob_end_flush();
     }
 } 

Конструктор данного контроллера принимает все пришедшие зависимости (например данные формы и любые другие данные сервера или пользовательского ввода)

Метод getConfig() возвращает наш файл конфигурации, а метод view() отвечает за вывод файлов представления и передачу параметров в них.

Далее давайте добавим файлы контроллеров отвечающих за регистрацию и авторизацию пользователей!

Добавим еще один контроллер RegisterController.php:

<?php 
namespace App\Controllers;

use App\Models\User;
use Symfony\Component\HttpFoundation\Request;

 class RegisterController extends BaseController 
 {
     /**
      * Выводим форму регистрации
      * @throws \App\Exceptions\LkException
      */
    public function index()
    {
        $countries = (new \App\Models\Country($this->di['db']))
                    ->getData();
        $regions = (new \App\Models\Region($this->di['db']))
            ->getData();
        $cities = (new \App\Models\City($this->di['db']))
            ->getData();

        $params = [
            'countries' => $countries,
            'regions'   => $regions,
            'cities'    => $citites,
            'config'    => $this->getConfig()
        ];

        return $this->view('register',$params);
    }

     /**
      * Обработчик регистрации
      */
    public function register()
    {
      // dump($this->di['request']->server->get('REQUEST_METHOD'));
       $requestMethod =  $this->di['request']->server->get('REQUEST_METHOD');
       if($requestMethod != 'POST') {
           abort404();
       }
        $data = $this->di['request']->request->all();
       /**
         ТУТ МОЖЕТ БЫТЬ ВАЛИДАЦИЯ ДАННЫХ
        * П.С: Я ее опускаю
        */

        if(isset($data['password_confirmation'])) {
            unset($data['password_confirmation']);
        }

       $data['password'] = _hpswd($data['password']);

       if(is_array($data)) {
         $db = $this->di['db'];
         $objUser = new User($db);
         if($objUser = $objUser->insertData($data)) {

             $this->di['session']->put('user', $objUser);
             return redirect($this->getConfig()['url'] .'/?c=login');
         }

         dump('Error insert database');

       }

    }
 }

Теперь посмотрим как будет выглядеть представление, по факту это просто форма регистрации register.phtml:

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="/favicon.ico">

    <title>Регистрация на сайте</title>

    <!-- Bootstrap core CSS -->
    <link href="<?=$config['url']?>/assets/bootstrap.min.css" rel="stylesheet">

    <!-- Custom styles for this template -->
    <link href="<?=$config['url']?>/assets/signin.css" rel="stylesheet">
    <link href="<?=$config['url']?>/assets/main.css" rel="stylesheet">

</head>

<body>
<form method="post" action="<?=$config['url']?>/?c=register&a=register">
    <img class="mb-4" src="https://getbootstrap.com/assets/brand/bootstrap-solid.svg" alt="" width="72" height="72">
    <br><h1 class="h3 mb-3 font-weight-normal">Зарегистрируйтесь пожалуйста</h1>
    <p><em>Уже есть аккаунт? <a href="<?=$config['url']?>/?c=login">Войти</a></em></p>
    <p style="font-weight:bold;">Основные данные</p>
    <div class="container">

        <div class="item">
            <label for="inputName" class="sr-only">Имя*</label>
            <input type="text" id="inputName" name="name" class="form-control" placeholder="Имя" required autofocus><br>
            <label for="inputSurname" class="sr-only">Фамилия</label>
            <input type="text" id="inputSurname" class="form-control" name="surname" placeholder="Фамилия" required autofocus><br>
        </div>
        <div class="item">

            <label for="inputPhone" class="sr-only">Телефон</label>
            <input type="text" id="inputPhone" class="form-control" name="phone" placeholder="+7(918)000-00-00" required autofocus><br>
            <label for="inputEmail" class="sr-only">Email адрес</label>
            <input type="email" id="inputEmail" class="form-control" name="email" placeholder="Email адрес" required autofocus>
        </div>
    </div>

    <p style="font-weight:bold;">Адрес</p>
    <div class="container">

        <div class="item">
            <label for="inputCountry" class="sr-only">Страна</label>
            <select class="form-control" name="country_id">
                <option value="0" id="inputCountry">Выбрать страну</option>
                <?php foreach($countries as $country): ?>
                    <option value="<?=$country['id']?>"><?=$country['name']?></option>
                <?php endforeach; ?>
            </select><br>
            <label for="inputRegion" class="sr-only">Регион</label>
            <select class="form-control" name="region_id">
                <option value="0" id="inputRegion">Выбрать регион</option>
                <?php foreach($regions as $region): ?>
                    <option value="<?=$region['id']?>"><?=$region['name']?></option>
                <?php endforeach; ?>
            </select>
        </div>

        <div class="item">
            <label for="inputCity" class="sr-only">Город</label>
            <select class="form-control" name="city_id">
                <option value="0" id="inputCity">Выбрать город</option>
                <?php foreach($cities as $city): ?>
                    <option value="<?=$city['id']?>"><?=$city['name']?></option>
                <?php endforeach; ?>
            </select>
        </div>
    </div>


    <p style="font-weight:bold;">Пароль</p>
    <div class="container">

        <div class="item">

    <label for="inputPassword" class="sr-only">Пароль</label>
    <input type="password" id="inputPassword" class="form-control" name="password" placeholder="Пароль" required>
        </div><div class="item">
    <label for="inputPassword" class="sr-only">Повторите Пароль</label>
    <input type="password" id="inputPassword" class="form-control" name="password_confirmation" placeholder="Повторите Пароль" required>
        </div>
    </div>
    <p>Подписаться на новости: <input type="checkbox" name="is_news_subscribe" value="1"> </p>
    <button class="btn btn-lg btn-primary btn-block" type="submit">Регистрация на сайте</button>
    <p class="mt-5 mb-3 text-muted">&copy; 2017-2018</p>
</form>
</body>
</html>

И следом добавим контроллер авторизации LoginController.php

 

<?php
 namespace App\Controllers;

 use App\Models\User;

 class LoginController extends BaseController
 {
     public function index()
     {
        $config = $this->getConfig();
        $user = $this->di['session']->get('user') ?? null;
        if($user) {
            return redirect($config['url'] .'/?c=account');
        }

        $params = [
            'config' => $config
        ];
        return $this->view('login', $params);
     }
     public function login()
     {
         $requestMethod =  $this->di['request']->server->get('REQUEST_METHOD');
         if($requestMethod != 'POST') {
             abort404();
         }
         $data = $this->di['request']->request->all();
         $email = $data['email'];
         $password = _hpswd($data['password']);

         $objUser = new User($this->di['db']);
         if($objUser = $objUser->login($email, $password)) {

             $this->di['session']->put('user', $objUser);
             return redirect($this->getConfig()['url'] .'/?c=login');
         }

         dump('Error: login incorrect');
     }
 }

Форма входа будет выглядеть следующим образом login.phtml:

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="/favicon.ico">

    <title>Авторизация на сайте</title>

    <!-- Bootstrap core CSS -->
    <link href="<?=$config['url']?>/assets/bootstrap.min.css" rel="stylesheet">

    <!-- Custom styles for this template -->
    <link href="<?=$config['url']?>/assets/signin.css" rel="stylesheet">
</head>

<body class="text-center">
<form class="form-signin" action="<?=$config['url']?>/?c=login&a=login" method="post">
    <img class="mb-4" src="https://getbootstrap.com/assets/brand/bootstrap-solid.svg" alt="" width="72" height="72">
    <h1 class="h3 mb-3 font-weight-normal">Пожалуйста, войдите</h1>
    <p><em>Нет аккаунта? <a href="<?=$config['url']?>/?c=register">Регистрация</a></em></p>

    <label for="inputEmail" class="sr-only">Email </label>
    <input type="email" id="inputEmail" class="form-control"
           placeholder="Email адрес" name="email" required autofocus>
    <label for="inputPassword" class="sr-only">Пароль</label>
    <input type="password" id="inputPassword"
           name="password" class="form-control" placeholder="Пароль" required>
    <div class="checkbox mb-3">
        <label>
            <input type="checkbox" value="remember-me" value="1"> Запомнить меня
        </label>
    </div>
    <button class="btn btn-lg btn-primary btn-block" type="submit">Авторизация на сайте</button>
    <p class="mt-5 mb-3 text-muted">&copy; 2017-2018</p>
</form>
</body>
</html>

Далее сразу-же создадим и опишем контроллер отвечающий за вывод ЛК AccountController.php.

<?php
namespace App\Controllers;

use App\Models\User;

class AccountController extends BaseController
{
   public function index()
   {
       $config = $this->getConfig();

       $user = $this->di['session']->get('user') ?? null;
       if(!$user) {
           return redirect($config['url'] .'/?c=login');
       }
       //Обновляем сессионные данные
       $objUser = new User($this->di['db']);
       if($objUser->IsRefreshAdmin($user)) {
           $this->di['session']->forget('user');
           return redirect($config['url'] .'/?c=login');
       }
       if($objUser->IsRefreshStatus($user)) {
           return redirect($config['url'] .'/?c=account');
       }

       $params = [
           'config' => $config,
           'user'    => $user,
           //треш
           'country' => dbhelper('country', $this->di['db'], $user->country_id),
           'region'  => dbhelper('region', $this->di['db'], $user->region_id),
           'city'    => dbhelper('city', $this->di['db'], $user->city_id),
       ];
       return $this->view('account', $params);
   }
   public function logout()
   {
       $config = $this->getConfig();
       $this->di['session']->forget('user');
       return redirect($config['url'] .'/?c=login');
   }

}

И так-же посмотрим на въюху account.php:

<?php if($user->isadmin): ?><a href="?c=admin">В админку</a>&nbsp;<?php endif; ?>
<a href="<?=$config['url']?>/?c=account&a=logout">Выход</a>
<?php if(!$user->status): ?>
<h1 style="color:red;">Ваш аккаунт на модерации</h1>
<?php else: ?>
    <h1 style="color:green;">Ваш аккаунт активен</h1>
<br>
<table width="100%">
    <tr>
        <td>Имя Фамилия</td>
        <td><?=$user->name?>  <?=$user->surname?></td>
    </tr>
    <tr>
        <td>E-mail</td>
        <td><?=$user->email?> </td>
    </tr>
    <tr>
        <td>Телефон</td>
        <td><?=$user->phone?></td>
    </tr>
    <tr>
        <td>Адрес</td>
        <td><?=$user->address?></td>
    </tr>

    <tr>
        <td>Страна/Регион/Город</td>
        <td><?=$country->name?>/<?=$region->name?>/<?=$city->name?> </td>
    </tr>
</table>
<?php endif; ?>

 

Шаг 5 - Заключительный

Если вы будете внимательны, то увидите, что мы используем глобальные функции (так называемые хелперы) по типу _hpswd или dbhelper, давайте опишем файл helpers.php

 

<?php
function abort404()
{
    echo "Страница не найдена";
    die;
}
function dump($data)
{
     echo "<pre>";
       print_r($data);
     echo "</pre>";
     die;
}

/**
 * Редирект
 * @param $url
 * @param bool $permanent
 */
if(!function_exists('redirect')) {
    function redirect($url, $permanent = false)
    {
        if (headers_sent() === false) {
            header('Location: ' . $url, true, ($permanent === true) ? 301 : 302);
        }

        exit();
    }
}
function _hpswd($pswd)
{
    return hash("sha256", $pswd);
}
function dbhelper($type, $db, int $id)
{
    $obj = new \App\Models\Country($db);
    switch($type) {
        case 'region':
             $obj = new \App\Models\Region($db);
            break;
        case  'city':
            $obj = new \App\Models\City($db);
            break;
    }

    return $obj->getItem($id);
}

Модели стран, регионов и городов, а так-же логику администратора вы можете описать сами или найти в репозитории проекта.

Ссылка на репозиторий: https://gitlab.com/mzcoding/base-lk

Все вопросы пишите в комментариях




Поддержать автора