Pull to refresh

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

Reading time3 min
Views8.7K

Привет, хабр! В этой статье я хочу написать о том, как сделать 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 и Контроллеры

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

Tags:
Hubs:
Total votes 12: ↑6 and ↓60
Comments29

Articles