Пишем мини MVC фреймворк на PHP #1

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Привет, хабр! В этой статье я хочу написать о том, как сделать PHP-приложение с помощью схемы разделения данных приложения MVC.

Итак, начнем!

Для работы нам нужна функция под названием autoload. Она избавляет нас от бесконечных require'ов. Мы можем вручную написать скрипт, но эта функция есть у знаменитого пакетного менеджера composer.

После установки инициализируем его в главной папке нашего мини-фреймворка командой composer init. на всех вопросах нажимаем ENTER.

Далее заходим в появившийся файл composer.json. Удаляем все и добавляем это:

{
  "name": "<название/пакета>",
    "autoload": {
        "psr-4": {
            "app\\": "./"
        }
    },
    "require": {}
}

И наконец, выполняем команду composer update. На этом настройка composer завершена.

Теперь, создадим папку core и файл .htaccess. Еще нужно создать папку public и создать в ней файл index.php - точку входа в приложение.

В файл .htaccess нужно вписать следующее:

RewriteEngine on

RewriteRule .* public/index.php

Все, что делает этот файл - переадресовывает любые запросы в index.php.

Потом, в папке core создаем класс Application. Помещаем в него этот код:

<?php
namespace app\core;

class Application
{
	
}

Здесь мы создаем пока что пустой класс и пространством имен app\core.

На этом этапе структура должна выглядеть так:

│ .htaccess
│ composer.json
│ composer.lock

├───core
│ Application.php

├───public
│ index.php

└───vendor

Отлично. Теперь давайте выполним первую задачу: маршрутизацию.

Маршрутизация

В папке core создаем класс Router.php и начнем писать код:

<?php
namespace app\core
  
class Router
{
  protected array $routes = [];
  
  public function get($path, $callback)
  {
  	$this->routes['get'][$path] = $callback;
  }

  public function post($path, $callback)
  {
  	$this->routes['post'][$path] = $callback;
  }
}

Мы создали переменную routes, в котором будут храниться все маршруты в таком формате:

// ['method' => ['path' => callback]]

Теперь нужно создать класс Request.php для получения урлов, методов запроса и так далее:

<?php


namespace app\core;


class Request
{
    public function getPath()
    {
        $path = $_SERVER['REQUEST_URI'] ?? '/';
        $position = strpos($path, '?');

        if ($position === false) return $path;
        return substr($path, 0, $position);
    }

    public function getMethod()
    {
        return strtolower($_SERVER['REQUEST_METHOD']);
    }
}

Тут все просто: метод getPath служит для получения url без GET-параметров, а getMethod просто возвращает HTTP-метод. Модифицируем класс Роутера:

<?php
namespace app\core;
  
class Router
{
  protected array $routes = [];
  public Request $request;
  
  public function __construct()
  {
  	$this->request = new Request();
  }

  
  public function get($path, $callback)
  {
  	$this->routes['get'][$path] = $callback;
  }

  public function post($path, $callback)
  {
  	$this->routes['post'][$path] = $callback;
  }
  
  public function resolve()
  {
        $path = $this->request->getPath();
        $method = $this->request->getMethod();
        $callback = $this->routes[$method][$path] ?? false;

        if ($callback === false) {
            return "404";
        }

       return call_user_func($callback);
  }
}

Тут мы создаем экземпляр Request'а и метод resolve, который возвращает то, что вернул callback.

Возвратимся в класс Application и создаем метод run, который запустит Роутер:

<?php


namespace app\core;


class Application
{
    public Router $router;

    public function __construct($ROOT_DIR)
    {
        $this->router = new Router();
    }

    public function run()
    {
        echo $this->router->resolve();
    }
}

Теперь, можем протестировать текущий функционал. Создадим папку public и в ней файл index.php:

<?php
require dirname(__DIR__) . '/vendor/autoload.php';

use app\core\Application;

$app = new Application();

$app->router->get('/', function () {
    return "Hello, habr!";
});

$app->run();

В этой же папке запустим команду php -S localhost:8080 (или любой другой порт). Зайдем на localhost:8080 в браузере и о чудо! Мы увидим надпись Hello, habr!

Итоги

На этом первая часть подходит к концу. В ней мы задали каркас нашего будущего фреймворка. В следующей части мы реализуем View и Контроллеры

Это моя первая статья на Хабре, поэтому буду рад любой критике. Спасибо за прочтение и удачи!

Исходники

Источник: https://habr.com/ru/post/654983/


Интересные статьи

Интересные статьи

Привет, меня зовут Игорь и я работаю в команде Tarantool. При разработке мне часто требуется быстрое прототипирование приложений с базой данных, например, для тестирования кода или для создания MVP....
Недавно я решил немного привести в порядок несколько своих .NET pet-проектов на GitHub, настроить для них нормальный CI/CD через GitHub Actions и вынести всё в отдельный ...
Если на таких языках программирования, как Java, C# или Ruby выбор основного фреймворка не представляет собой сложности (там всего по одному ведущему фреймворку), то с ph...
Жизнь инженера полна сюрпризов: особенно, когда приходится иметь дело с производительностью. Например, что произойдет, если попытаться запустить этот кусок Java-кода? Выглядит довольно невинн...
Проект ок.tech Data Толк родился как дискуссионная площадка для специалистов, занимающихся обработкой и аналитикой больших данных. Каждый раз мы подчеркиваем, что основная задача наших митапо...