$_POST всегда пустой, хотя в file_get_contents('php://input') есть данные

72
25 октября 2021, 00:40

Пытаюсь отправить данные формы при помощи fetchAPI. Вот форма:

const regUserBtn = document.getElementById('regUser'); 
regUserBtn.addEventListener('click', function(event) { 
  event.preventDefault(); 
  var formData = getRegFormData(regForm); 
  try { 
    let response = fetch('/index/registerUser', { 
        method: 'POST', 
        mode: 'cors', 
        cache: 'no-cache', 
        credentials: 'same-origin', 
        headers: { 
          'Content-Type': 'application/json', 
        }, 
        redirect: 'follow', 
        referrer: 'no-referrer', 
        body: formData, 
      }) 
      .then(response => response.json()); 
 
    console.log(response); 
  } catch (error) { 
    console.error('Ошибка:', error); 
  } 
}); 
 
function getRegFormData(regForm) { 
  var formData = new FormData(); 
  formData.append('email', regForm.email.value); 
  formData.append('firstName', regForm.firstName.value); 
  formData.append('secondName', regForm.secondName.value); 
  formData.append('password', regForm.password.value); 
 
  return formData; 
}
<div id="signup-tab-content" class="active"> 
  <form class="auth-form" id="regForm"  method="post" name="auth-form"> 
    <input type="email" required="" autocomplete="on" class="input" id="user_email" placeholder="Эл. адрес" name="email"> 
    <input type="text" required autocomplete="on" class="input" id="first-name" placeholder="Имя" name="firstName"> 
    <input type="text" class="input" autocomplete="on" id="second-name" placeholder="Фамилия" name="secondName"> 
    <input type="password" required class="input" id="password" autocomplete="off" placeholder="Пароль" name="password"> 
 
    <input id="regUser" type="submit" class="button" value="Регистрация"> 
  </form> 
  <!--.login-form--> 
</div> 
<!--.signup-tab-content-->

А вот так я пытаюсь принять данные на сервере indexController.php:

class IndexController extends Controller
{
    public function register()
    {
        $requestPost = filter_input_array(INPUT_POST);
        return var_dump(file_get_contents('php://input')); exit;
        die(json_encode($validetedData));
    }
}

При попытке взаимодействия переменная $requestPost всегда пустая, чтобы я не делал. file_get_contents('php://input') возвращает массив post, но через него нельзя фото загружать, а мне нужна эта функциональность.

Если я сделаю вот так:

$apiRequestArray = json_decode(trim(file_get_contents('php://input')), true);
$requestPost = filter_var_array($apiRequestArray);
return $requestPost;

То в ответ js не получит ничего переменная response.json() будет пустая

если die(json_encode([$requestPost])); то тоже, post-запрос зависнет, как pending. Не понимаю, в чем дело, не работает return из функции, хотя var_dump возвращает данные, их видно на вкладке network.

P.S возможно, все дело в моем самописном роутере, выглядит он вот так:

App.php

class App extends \app\core\Base
{
    public function dispatch()
    {
     $this->setController();
    $this->setMethod();
    $this->setParams();
    if (class_exists($this->controller)) {
        $controllerObject = new $this->controller();
        if (method_exists($controllerObject, $this->method)) {
            call_user_func_array([$controllerObject, $this->method], $this->params);
            } else {
                $this->respondNotFound();
            }
        } else {
            $this->respondNotFound();
        }
    }
    /**
     * Parse the url into an array so we can access the indexes as a
     * controller, method and optional params.
     *
     * @return array
     */
    private function parseUrl()
    {
        $requestUri = rtrim(filter_input_array(INPUT_SERVER)['REQUEST_URI']);
        if (isset($requestUri) && !empty($requestUri)) {
            return explode('/', str_replace('.php', '', $requestUri));
        }
    }
    /**
     * Set the controller using the first index of the url.
     */
    private function setController()
    {
        array_shift($this->url);
        if (empty($this->url[0])) {
            $this->url[0] = 'index';
        }
        $path = str_replace('\\', '/', ROOT . '/dummyAdmin/app/controllers/' . $this->url[0] . 'Controller.php');
        if (file_exists($path)) {
            $this->controller = 'app\\controllers\\' . $this->url[0] . 'Controller';
            unset($this->url[0]);
        }
        else if (!file_exists($path) && !empty($this->url[0])) {
            $this->respondNotFound();
        }
        require_once $path;
    }
    /**
    * Set the method using the second index of the url.
    */
    private function setMethod()
    {
        if (isset($this->url[1]) && method_exists($this->controller, $this->url[1])) {
            $this->method = $this->url[1];
            unset($this->url[1]);
        }
    }
    /**
    * Set the params to pass to the controller method.
    *
    * Params equal the remaining values in the url array rebased.
    *
    * Additionally, we pass the $_POST super global for any optional
    * POST data
    */
    private function setParams()
    {
        $postRequest = filter_input_array(INPUT_POST);
        $this->params = $this->url ? [array_values($this->url), $postRequest] : [$postRequest];
    }
}

И потом в index.php

require __DIR__ . '/vendor/autoload.php';
use app\core\App;
$app = new App();
$app->dispatch();

Если дело в нем, то как это можно исправить? или он совсем никуда не годится и лучше совсем от него избавится и заменить на что то другое?

Answer 1
  1. В JavaScript'е надо убрать заголовок 'Content-Type': 'application/json', т.к. он не соответствует передаваемому Content-Type. А Content-Type: form/multipart подставится автоматически.
  2. Чтобы вернуть ответ нужно использовать функции вывода (echo и т.д.), т.е. либо прописывать echo в конце контроллера, либо в роутере echo call_user_func_array(...)
READ ALSO
Бросать исключение или возвращать коды ошибок/успеха? Является ли исключением то, что метод не может выполнить свою задачу?

Бросать исключение или возвращать коды ошибок/успеха? Является ли исключением то, что метод не может выполнить свою задачу?

Исключения являются для меня самой непонятной темой в программировании(пока что)Даже прочтение кучи информации не помогло мне получить...

104
Executors. Как прекращать работу потоков?

Executors. Как прекращать работу потоков?

Я делаю некий таймерПри его запуске выполняется какая-то последовательность действий, после чего поток должен закрыться и не грузить дальнейшую...

308
Есть ли преимущества в использовании числа вместо типа bool в Posgresql?

Есть ли преимущества в использовании числа вместо типа bool в Posgresql?

Несколько раз встречал в таблицах базы, относящейся к веб-приложению на Java, столбцы, играющие роль флага, но имеющие не привычный тип bool, а smallint...

76