Всем привет! Возможно мой вопрос туповат, но я не могу понять, как реализовано в laravel/symfony/yii такая штука, что когда делаешь объект какого-то класса, то можно не передавать ему параметры. А в самом классе конструктор может быть с параметрами. Так же самое и с методами.
Я подумал использовать ReflectionClass и его метод newInstanceWithoutConstructor, но тогда конструктор вообще не будет учитываться.
Как объявлять объект класса не учитывая параметры конструктора?
Скорее всего у меня неправильно реализована логика роутинга.
Вот мой класс Route.php
<?php
namespace Core;
use Core\Request;
class Route
{
const FILE_ROUTES = BASE_DIR . "/config/routes.php";
const DIR_SRC = BASE_DIR . "/App";
private $routes;
private $url;
private $method;
private $params;
public function __construct(string $url, string $method)
{
$this->url = $url;
$this->method = $method;
}
private function load()
{
if ( file_exists(self::FILE_ROUTES) ){
$this->routes = require self::FILE_ROUTES;
}else{
throw new \Exception('Routes not found');
}
}
private function existUrl(): ?array
{
$url = trim($this->url, '/');
foreach($this->routes as $route){
$route['url'] = rtrim($route['url'], "/");
$regExp = "#^{$route['url']}$#";
if ( preg_match($regExp, $url, $matches) and $route['method'] === $this->method ){
$this->params = array_slice($matches,1);
return $route;
}
}
return Null;
}
public function run()
{
$this->load();
$route = $this->existUrl();
if ( !is_null($route) ){
$pathController = self::DIR_SRC . "/Controller/" . $route['controller'];
if (!file_exists($pathController)){
throw new \Exception("File {$route['controller']} is not found");
}else{
require_once $pathController;
}
$path = trim("App\Controller\\".$route['controller'], ".php");
if ( !class_exists($path) ){
throw new \Exception("Class {$route['controller']} is not found");
}
$action = $route['action'];
if ( !method_exists($path, $action) ){
throw new \Exception("Method $action in class {$route['controller']} is not found");
}
$method = strtolower($route['method']);
$this->$method($path, $route, $action);
}
}
public function get(string $path, array $route, string $action)
{
$request = new Request();
foreach ($this->params as $key => $value) {
preg_match("/\d+/", $value, $match);
if(!empty($match)){
$id = intval($match[0]);
}
if (is_string($value)) {
$request->name = $value;
}
if (is_int($id)){
$request->id = $id;
}
}
$args = [$request, ...$this->params];
$controller = new $path;
$controller($route);
// $test = new \ReflectionClass($path);
// // var_dump($reflection->getConstructor());
// $controller = $test->newInstanceWithoutConstructor();
// // $controller = $test->newInstance();
// // $controller($route);
// // var_dump($reflection);
// $reflection = new \ReflectionMethod($controller, $action);
// $reflection->invoke($controller, $args);
call_user_func_array([$controller, $action], $args);
}
public function post(string $path, array $route, string $action)
{
$request = new Request();
foreach ($_REQUEST as $key => $value) {
$value = htmlspecialchars(trim($value), ENT_QUOTES);
$request->$key = $value;
}
$args = [$request, ...$this->params];
$controller = new $path($route);
call_user_func_array([$controller, $action], $args);
}
}
И вот как я его вызываю:
Файл index.php
use Core\Route;
spl_autoload_register(function ($class) {
$path = str_replace("\\", "/", "$class.php");
if(file_exists($path)){
require $path;
}
});
$url = $_SERVER['REQUEST_URI'];
$method = $_SERVER['REQUEST_METHOD'];
$route = new Route($url, $method);
$route->run();
То есть я беру из _SERVER нужные данные дляя того, чтобы проверить если рут найден, если найден, то вызываю соотвествующий ему метод (GET | POST), и делаю объект контроллера, который соотвествует этому руту и вызываю метод для этого рута.
А вот как у меня выглядит IndexController
<?php
namespace App\Controller;
use Core\Controller;
use Core\Request;
use App\Entity\Action;
use App\Repository\ActionRepository;
class IndexController extends Controller
{
private $actionRepository;
public function __construct(ActionRepository $actionRepository)
{
$this->actionRepository = $actionRepository;
var_dump("expression");
}
public function index()
{
$action = new Action();
$action->prenumeAction = "Test";
$action->nrTelefonAction = "123213";
var_dump($this->actionRepository);
$data = [
'title' => "Title"
];
return $this->render("home.index", $data);
}
}
Как видно в этом IndexController у меня конструктор принимает параметр, а в Route я делаю экземпляр класса без этого параметра. И происходит ошибка соответсвенно. Как добиться такого, чтоб можно было делать объект класса без параметра?