Как я могу обработать URL-маршрут с 3 сегментами? - PullRequest
1 голос
/ 30 января 2020

Я очень плохо объясняю вещи. В основном я пытаюсь научиться разрабатывать MVC с нуля без каких-либо рамок.

Я хочу создать панель администратора и хочу, чтобы в URL-адресе были категории, которые выглядели бы примерно так: localhost/admin/core/settings

На данный момент MVC настроен прямо сейчас, это то, что я получаю, localhost/admin/settings.

Я немного запутался, как бы я это сделал Я считаю, что конечный результат макета кода будет выглядеть следующим образом: Controllers/Admin/Core.php Что касается кода, я не слишком уверен.

index. php:

<?php
    require_once('../app/bootstrap.php');

    // Init Core Library
    $init   =   new Core;

Core . php:

<?php
    /*
     * App Core Class
     * Creates URL & loads core controller
     * URL FORMAT - /controller/method/params
     */

    class Core {
        protected $currentController    =   'Pages';
        protected $currentMethod        =   'index';
        protected $params               =   [];

        public function __construct(){
            //print_r($this->getUrl());

            $url    =   $this->getUrl();

            // Look in controllers for first value
            if(file_exists('../app/controllers/' . ucwords($url[0]).'.php')){
                // If exists, set as controller
                $this->currentController    =   ucwords($url[0]);
                // Unset 0 Index
                unset($url[0]);
            }

            // Require the controller
            require_once '../app/controllers/'. $this->currentController . '.php';

            // Instantiate controller class
            $this->currentController    =   new $this->currentController;

            // Check for second part of url
            if(isset($url[1])){
                // Check to see if method exists in controller
                if(method_exists($this->currentController, $url[1])){
                    $this->currentMethod    =   $url[1];
                    // Unset 1 index
                    unset($url[1]);
                }
            }

            // Get params
            $this->params   =   $url ? array_values($url) : [];

            // Call a callback with array of params
            call_user_func_array([$this->currentController, $this->currentMethod], $this->params);
        }

        public function getUrl(){
            if(isset($_GET['url'])){
                $url    =   rtrim($_GET['url'], '/');
                $url    =   filter_var($url, FILTER_SANITIZE_URL);
                $url    =   explode('/', $url);
                return $url;
            }
        }
    }

1 Ответ

0 голосов
/ 30 января 2020

Для вашего решения вам потребуется обработать маршрутизацию. Лучше всего было бы создать простой класс маршрутизатора, который обрабатывает URI-маршрутизацию, запросы и строки запросов.

Таким образом, вы можете взять полный URI - admin/core/settings и вызвать соответствующий контроллер и метод, вместо того, чтобы разбивать его на куски и обрабатывать его так, как вы это делали.

Предлагаемое решение не является окончательным и наиболее идеальным, но оно должно соответствовать. Существуют лучшие подходы, использующие пространства имен PHP, которые автоматически загружают файлы.

При условии, что вы добавили в .htaccess директивы для передачи URI:

<IfModule mod_rewrite.c>
    RewriteEngine On
    Options +FollowSymLinks -Indexes

    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f 
    RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>

Создайте класс Router, который будет обрабатывать маршруты и инициировать классы и вызывать методы:

class Router {

    public $routes = [];

    public function __construct( $routes = [] ) {
        $this->routes = $routes;
    }


    public function load( $route ) {

        if ( in_array( $route, $this->routes ) ) {
            if ( file_exists( $this->routes[ $route ]['file'] ) ) {
                require_once $this->routes[ $route ]['file'];
                $class = new $this->routes[$route]['class'];
                call_user_func( array( $class, $this->routes[ $route ]['method'] ) );
            }
        }

    }


}

Затем после запроса bootstrap. php вы можете выбрать маршрут:

<?php

 require_once('../app/bootstrap.php'); //require in boostrap.php router class, you could call it there 

В bootstrap. php:

 require_once('Router.php'); //require the Router class 

 //define the routes 
 $routes = [
    '/admin/core/settings' => [
       'file'   => 'Controllers/Admin/Core.php',
       'class'  => 'Core',
       'method' => 'Settings' //i.e. that you method Settings to open the settings for the admin
    ] //if you are not using namespaces
 ];
 $uri = $_SERVER['REQUEST_URI'];  //take the URI 
 $router = new Router($routes); //instantiate the Router class 
 $router->load($uri); //handle the given uri 

Тогда в классе Core у вас должен быть метод Settings:

class  Core {


    public function __construct() {

    //you could parse all requests here and pass it to the object's property to be used in other methods of the class 
    }

    public function Settings() {
        //add your code
        //handle the requests, retrieve the data via model, render the view, pass the data to the view, etc
    }
}

Я бы порекомендовал хотя бы рассмотреть использование пространств имен и механизм автозагрузки. См. composer .org документы для этого и прочитайте php. net о spl_autoload, spl_autoload_register и проверьте также php -fig.

Composer будет обрабатывать автозагрузку классов, поэтому вместо постоянного использования require файлы будут загружаться автоматически, если все пространства имен верны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...