No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Curso Avanzado de PHP

Curso Avanzado de PHP

Héctor Benitez

Héctor Benitez

Implementando el server request handler

17/35
Recursos
  • Debes acostumbrarte a leer código de otras personas o librerías. Detrás de todo hay un programador haciendo algo que podrás entender y modificar.
  • Es muy importante que leas los errores ya que muchas veces te dará pistas muy buenas de lo que está sucediendo.

Aportes 19

Preguntas 2

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.

Es un poco complicado y seguir este video, varias cosas ya estàn deprecadas y se hace muy tedioso la instalaciòn de dependencias de las dependencias.

Interesante, trataré de explicar un poco mejor qué sucedió, la clase DispatcherMiddleware en su método process hace uso de $request, recordemos que nosotros le pasamos este $request en el constructor de Harmony en nuestro index,php, y precisamente ese $request lo maneja Zend (Laminas ahora), entonces, cuando Harmony manda a llamar a process le inyecta ese mismo $request.

Entonces, debido a la convención psr-7, Harmony sabe que si o si $request va a tener llamado un método llamado getAttribute(), esto porque el objeto request trae en sus propiedades una lista de atributos, y estos atributos son añadidos por nuestro router, y esos atributos son los mismos que nosotros específicamos, y getAttribute() es simplemente un getter.

Si miramos más abajo en el código de process, vemos que está la condicional is_array($action) && is_string($action[0]) && is_string($action[1])

Bueno, esta condicion lo que hace es verificar que $action sea un array, y si recuerdas, $action viene de nuestro getAttribute(), por lo que $action va a ser el array que nosotros pasamos en nuestras rutas (Esto por lo que ya te expliqué arriba)

Entonces, pregunta por $action[0], nosotros inicialmente teníamos definido un arreglo con indices asociativos, y al primer indice lo llamamos “controller”, por tanto, cuando Harmony trata de buscar el índice 0 se da cuenta que no existe y manda un error, es por eso que borramos los indices, porque de esa manera PHP al no ver un índice, pone por defecto al índice 0 y así sucesivamente (Como cualquier lenguaje de programación)

Y gracias a las convenciones PSR Harmony sabe que tu a través del índice 0 vas a pasar un controlador y a través del índice 1 tu vas a pasar un método.

Y el error de Jobs fue porque nuestra clase Jobs espera que le inyectemos una dependencia, y eso lo haciamos antes manualmente usando un contenedor que hacía ese trabajo por nosotros, pero ahora estamos usando Harmony, y Harmony se encarga de eso ahora, por lo que debemos indicarle a Harmony qué contenedor de inyección de dependencias debe usar, es por eso que le pasamos ese $container, que si recuerdas más arriba en el código, $container es una instancia de DI\Container y DI (Dependencu Injection) es el paquete que manejamos para inyección de dependencias ^^

Utilizar harmony simplifica realmente las cosas

Para los que tengan un error con el SapiEmitter de zend lo que deben hacer es desinstalarlo
composer remove zendframework/zend-httphandlerrunner
Y luego instalar el de laminas
composer require laminas/laminas-httphandlerrunner

Siento que todo se enredo mucho, creo que era mejor utilizar el fast-router.
Aunque estuvo muy buena la clase de ejemplo de como depurar el codigo

He visto esta clase 3 veces, Ahora todo tiene sentido. 🤯
.
Luego de entender esto entiendo que Laravel no es magia negra ! 🤪
.

Any sufficiently advanced technology is indistinguishable from magic

.
Lo dijo : Arthur C. Clarke

En que momento define la varaible container?

No logro encontrar el detalle, me sale lo siguiente:
Fatal error: Uncaught Error: Class ‘WoohooLabs\Harmony\Middleware\HttpHandlerRunnerMiddleware’ not found in /var/www/html/curso-php-platzi/public/index.php on line 110
( ! ) Error: Class ‘WoohooLabs\Harmony\Middleware\HttpHandlerRunnerMiddleware’ not found in /var/www/html/curso-php-platzi/public/index.php on line 110
Call Stack

<h1>Time Memory Function Location</h1>
1 0.0002 382472 {main}( ) …/index.php:0

<code>
<?php
require_once '../vendor/autoload.php';

session_start();

$dotenv = Dotenv\Dotenv::create(__DIR__ . '/..');
$dotenv->load();

use Illuminate\Database\Capsule\Manager as Capsule;
use Aura\Router\RouterContainer;
use WoohooLabs\Harmony\Harmony;
use WoohooLabs\Harmony\Middleware\DispatcherMiddleware;
use WoohooLabs\Harmony\Middleware\HttpHandlerRunnerMiddleware;
use Zend\Diactoros\Response;
use Zend\HttpHandlerRunner\Emitter\SapiEmitter;

$container = new DI\Container();

$capsule = new Capsule;

$capsule->addConnection([
    'driver'    => 'mysql',
    'host'      => getenv('DB_HOST'),
    'database'  => getenv('DB_NAME'),
    'username'  => getenv('DB_USER'),
    'password'  => getenv('DB_PASS'),
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => '',
]);
$capsule->setAsGlobal();
$capsule->bootEloquent();

$request = Zend\Diactoros\ServerRequestFactory::fromGlobals(
  $_SERVER,
  $_GET,
  $_POST,
  $_COOKIE,
  $_FILES
);

$routerContainer = new RouterContainer();
$map = $routerContainer->getMap();

$map->get('index', '/curso-php-platzi/', [
    'controller' => 'App\Controllers\IndexController',
    'action' => 'indexAction'
]);

$map->get('indexJobs', '/curso-php-platzi/jobs', [
    'controller' => 'App\Controllers\JobsController',
    'action' => 'indexAction'
]);
$map->get('deleteJobs', '/curso-php-platzi/jobs/delete', [
    'controller' => 'App\Controllers\JobsController',
    'action' => 'deleteAction'
]);

$map->get('addJobs', '/curso-php-platzi/jobs/add', [
    'controller' => 'App\Controllers\JobsController',
    'action' => 'getAddJobAction'
]);

$map->post('saveJobs', '/curso-php-platzi/jobs/add', [
    'controller' => 'App\Controllers\JobsController',
    'action' => 'getAddJobAction'
]);

$map->get('addUsers', '/curso-php-platzi/users/add', [
    'controller' => 'App\Controllers\UsersController',
    'action' => 'getAddUserAction'
]);

$map->post('saveUsers', '/curso-php-platzi/users/add', [
    'controller' => 'App\Controllers\UsersController',
    'action' => 'getAddUserAction'
]);

$map->get('loginForm', '/curso-php-platzi/login', [
    'controller' => 'App\Controllers\AuthController',
    'action' => 'getLogin'
]);

$map->get('logout', '/curso-php-platzi/logout', [
    'controller' => 'App\Controllers\AuthController',
    'action' => 'getLogout',
]);

$map->post('auth', '/curso-php-platzi/auth', [
    'controller' => 'App\Controllers\AuthController',
    'action' => 'postLogin'
]);

$map->get('admin', '/curso-php-platzi/admin', [
    'controller' => 'App\Controllers\AdminController',
    'action' => 'getIndex',
    'auth' => true
]);


$matcher = $routerContainer->getMatcher();
$route = $matcher->match($request);

if (!$route) {
    echo 'No route';
}else{
    $harmony = new Harmony($request, new Response());
    $harmony
        ->addMiddleware(new HttpHandlerRunnerMiddleware(new SapiEmitter()))
        ->addMiddleware(new Middlewares\AuraRouter($routerContainer))
        ->addMiddleware(new AuthenticationMiddleware())
        ->addMiddleware(new DispatcherMiddleware($container, 'request-handler'));
    $harmony();
}

Alguien? no puedo avanzar con el curso debido a mi error, alguien me puede ayudar?

Y si en vez de usar un arreglo para definir el controlador y la acción usas closure, como se hace para que el Container pueda inyectar?.

Fatal error: Uncaught Zend\HttpHandlerRunner\Exception\EmitterException: Output has been emitted previously; cannot emit response in C:\xampp\htdocs\curso-php\vendor\zendframework\zend-httphandlerrunner\src\Exception\EmitterException.php:23 Stack trace: #0 C:\xampp\htdocs\curso-php\vendor\zendframework\zend-httphandlerrunner\src\Emitter\SapiEmitterTrait.php(39): Zend\HttpHandlerRunner\Exception\EmitterException::forOutputSent() #1 C:\xampp\htdocs\curso-php\vendor\zendframework\zend-httphandlerrunner\src\Emitter\SapiEmitter.php(26): Zend\HttpHandlerRunner\Emitter\SapiEmitter->assertNoPreviousOutput() #2 C:\xampp\htdocs\curso-php\vendor\woohoolabs\harmony\src\Middleware\HttpHandlerRunnerMiddleware.php(36): Zend\HttpHandlerRunner\Emitter\SapiEmitter->emit(Object(Zend\Diactoros\Response\HtmlResponse)) #3 C:\xampp\htdocs\curso-php\vendor\woohoolabs\harmony\src\Harmony.php(128): WoohooLabs\Harmony\Middleware\HttpHandlerRunnerMiddleware->process(Object(Zend\Diactoros\ServerRequest), Object(WoohooLabs\Harmony\Harmony)) #4 C:\xamp in C:\xampp\htdocs\curso-php\vendor\zendframework\zend-httphandlerrunner\src\Exception\EmitterException.php on line 23

Tuve un error en el aura-router y para arreglarlo lo cambie por el que recomendaba harmony

Y si quiero utilizar 2 o mas funciones dentro de mi Controller, como deberia hacer? Como seria el ‘action’? Porque siempre utiliza una funcion en cada Controller.

Debes acostumbrarte a leer código de otras personas o librerías. Detrás de todo hay un programador haciendo algo que podrás entender y modificar.

Es muy importante que leas los errores ya que muchas veces te dará pistas muy buenas de lo que está sucediendo.

Debes acostumbrarte a leer código de otras personas o librerías. Detrás de todo hay un programador haciendo algo que podrás entender y modificar

Es muy importante que leas los errores ya que muchas veces te dará pistas muy buenas de lo que está sucediendo

Para la prueba, no he implementado el response con Twig, por lo que me arrojaba un Fatal error indicando que debía ser un return de tipo Interface, por lo que he utilizado el ejemplo básico de FastRouteMiddleware en AuraRouter para el controlador, de la siguiente manera:

use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;

public function indexAction(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
{
	$users = [
		"Steve",
		"Arnie",
		$this->jobService->getJobs()['user']
	];

	$response->getBody()->write(json_encode($users));

	return $response;
}```

Y que hay con la autenticación, seguro ahora lo crearemos un middleware para el auth y las rutas protegidas.