@utkv_n

Можете объяснить почему не работают пути в MVC?

Развернула небольшое mvc приложение на хостинге. Две роли admin и all. Открывается только главная страница. А допусти site.com/add - 404 ошибка. Подскажите в чем может быть проблема ?
Это routes.php:
return [
    //mainController
    
    '' => [
        'controller' => 'main', //главная страница со всеми задачами
        'action' => 'index',
    ],
    
     'add' => [ // добавление задачи
        'controller' => 'main',
        'action' => 'add',
    ],
//admin
    'admin/login' => [ 
        'controller' => 'admin',
        'action' => 'login',
    ],
     'admin/logout' => [ 
        'controller' => 'admin',
        'action' => 'logout',
    ],
    ];

Это acl/main.php:
<?php

return [
    'all' =>[
        'index',
        'add'
    ],
    
    'admin' =>[
        'add'
    ],
];

Это котроллер:
<?php
namespace application\controllers;
use application\core\Controller;
use application\lib\Pagination;
use application\models\Admin;


class MainController extends Controller {
    
    public function indexAction(){
        
        $pagination = new Pagination($this->route, $this->model->postsCount());
    	$vars = [
			'pagination' => $pagination->get(),
			'list' => $this->model->postsList($this->route),
		];
		$this->view->render('Главная страница', $vars);
    }
    
    public function addAction() {
        
    	if (!empty($_POST)) {
			if (!$this->model->addValidate($_POST, 'add')) {
				$this->view->message('error', $this->model->error);
			}
			$id = $this->model->taskAdd($_POST);
			if (!$id) {
				$this->view->message('success', 'Ошибка обработки запроса');
			}
			$this->view->message('success', 'Пост добавлен');
		}
		$this->view->render('Добавить пост');
	}
}

<form action="/add" method="post">
            <div class="form-group">
                <label for="exampleFormControlInput1">Email address:</label>
                <input type="text" class="form-control" name='email' placeholder="name@example.com">
            </div>
            <div class="form-group">
                <label for="exampleFormControlInput2">Имя пользователя:</label>
                <input type="text" class="form-control" name ="name" >
            </div>
            <div class="form-group">
                <label for="message-text" class="col-form-label">Текст задачи:</label>
                <textarea class="form-control" name = "text" ></textarea>
            </div>
            <button type="submit" class="btn btn-primary">Сохранить</button>
        </form>

Класс Router:
<?php

namespace application\core;

use application\core\View;

class Router {

    protected $routes = [];
    protected $params = [];
    
    public function __construct() {
        $arr = require 'application/config/routes.php';
        foreach ($arr as $key => $val) {
            $this->add($key, $val);
        }
    }

    public function add($route, $params) {
        $route = preg_replace('/{([a-z]+):([^\}]+)}/', '(?P<\1>\2)', $route);
        $route = '#^'.$route.'$#';
        $this->routes[$route] = $params;
    }

    public function match() {
        $url = trim($_SERVER['REQUEST_URI'], '/');
        foreach ($this->routes as $route => $params) {
            if (preg_match($route, $url, $matches)) {
                foreach ($matches as $key => $match) {
                    if (is_string($key)) {
                        if (is_numeric($match)) {
                            $match = (int) $match;
                        }
                        $params[$key] = $match;
                    }
                }
                $this->params = $params;
                return true;
            }
        }
        return false;
    }

    public function run(){
        if ($this->match()) {
            $path = 'application\controllers\\'.ucfirst($this->params['controller']).'Controller';
            if (class_exists($path)) {
                $action = $this->params['action'].'Action';
                if (method_exists($path, $action)) {
                    $controller = new $path($this->params);
                    $controller->$action();
                } else {
                    View::errorCode(404);
                }
            } else {
                View::errorCode(404);
            }
        } else {
            View::errorCode(404);
        }
    }

}
  • Вопрос задан
  • 111 просмотров
Решения вопроса 1
ThunderCat
@ThunderCat Куратор тега PHP
{PHP, MySql, HTML, JS, CSS} developer
1) Роутер написан не очень рационально, по идее неплохо бы сначала разобрать урл на составляющие (апп, язык, контроллер, экшн), а затем из этого проверять есть ли совпадения, и если нет - использовать дефолтный прописанный в урл путь как сайт/язык/апликэйшн/контроллер/экшн/парам1/валуе1/... , ну да не суть.

2) Дебаг - одна из ОЧЕНЬ важных составляющих в обучении и развитии программиста.
Важно понимать как и где что-то пошло не так, знать как проверить и быстро вникать в логику происходящего. Например:

public function run(){
        if ($this->match()) {
            $path = 'application\controllers\\'.ucfirst($this->params['controller']).'Controller';
            if (class_exists($path)) {
                $action = $this->params['action'].'Action';
                if (method_exists($path, $action)) {
                    $controller = new $path($this->params);
                    $controller->$action();
                } else {
                    var_dump(['no method',$this->params]);
                    exit();
                    View::errorCode(404);
                }
            } else {
                var_dump(['no class',$this->params]);
                exit();
                View::errorCode(404);
            }
        } else {
            var_dump(['no match',$this->params]);
            exit();
            View::errorCode(404);
        }
    }

И тупо смотрим что к чему...
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
index0h
@index0h
PHP, Golang. https://github.com/index0h
В приведенном коде отсутствует Router. Это как раз тот класс, который по входящему запросу на основании ваших конфигов определяет какой контроллер и какой экшн запускать.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
YCLIENTS Москва
от 200 000 до 350 000 ₽
Ведисофт Екатеринбург
от 25 000 ₽
ИТЦ Аусферр Магнитогорск
от 100 000 до 160 000 ₽