No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Adquiere por un a帽o todos los cursos, escuelas y certificados por un precio especial.

Antes: $249

Currency
$219/a帽o

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Comprar ahora

Termina en:

2D
9H
47M
1S

Exponer un recurso en particular a trav茅s de HTTP GET

7/19
Recursos

Aportes 49

Preguntas 15

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

Les dejo el codigo del Router.

<?php

$matches=[];
if(preg_match('/\/([^\/]+)\/([^\/]+)/',$_SERVER["REQUEST_URI"],$matches))
{
    $_GET['resource_type']=$matches[1];    
    $_GET['resource_id']=$matches[2];
    error_log(print_r($matches,1));
    require 'server.php';
}else if(preg_match('/\/([^\/]+)\/?/',$_SERVER["REQUEST_URI"],$matches))
{
    $_GET['resource_type']=$matches[1];        
    error_log(print_r($matches,1));
    require 'server.php';
}else
{
    error_log('No matches');
    http_response_code(404);
}

?>

Para los que est茅n corriendo en localhost tienen que agregar mas opciones a la condicional
en esta parte :
preg_match(鈥//([^/]+)/([^/]+)/([^/]+)/([^/]+)/鈥

antes del ultimo slash -> /
agregar: /([^/]+)
por cada directorio adicional que tengan

Versi贸n con python

from flask import Flask, jsonify, make_response
from flask_restful import Resource, Api, abort

app = Flask(__name__)
api = Api(app)

BOOKS = {
    '1': {
        'isbn': '744586',
        'title': 'Cien a帽os de soledad',
        'description': 'Lorem insup lol.',
        'autor': 'Gabriel Garcia Marquez'
    },
    '2': {
        'isbn': '7894546',
        'title': 'De animales a dioses',
        'description': 'Lorem insup lol.',
        'autor': 'Yuval Noah Harari'
    }
}

def abort_if_book_doesnt_exits(book_id):
    if book_id not in BOOKS:
        abort(404, message='El libro con id {} no existe'.format(book_id))

class BookList(Resource):
    def get(self):
        return jsonify({'data': BOOKS})

class Book(Resource):
    def get(self, book_id):
            abort_if_book_doesnt_exits(book_id)
            return jsonify({'data': BOOKS[book_id]})

class Authors(Resource):
    pass

class Generes(Resource):
    pass

api.add_resource(BookList, '/books')
api.add_resource(Book, '/books/<book_id>')
api.add_resource(Authors, '/authors')
api.add_resource(Generes, '/generes')

if __name__ == '__main__':
    app.run(debug=True)

Archivo server.php

<?php

// Definimos los recursos disponibles
$allowedResourceType = [
    'books',
    'authors',
    'genres',
];

// Validamos que el recurso este disponible
$resourceType = $_GET['resource_type'];

if ( !in_array($resourceType, $allowedResourceType)) {
    die;
}

// Defino los recursos
$books = [
    1 => [
        'titulo' => 'Lo que el viento se llevo',
        'id_autor' => 2,
        'id_genero' => 2,
    ],
    2 => [
        'titulo' => 'La Iliada',
        'id_autor' => 1,
        'id_genero' => 1,
    ],
    3 => [
        'titulo' => 'La Odisea',
        'id_autor' => 1,
        'id_genero' => 1,
    ],
];

// Se indica al cliente que lo que recibir谩 es un json
header('Content-Type: application/json');

// Levantamos el id del recurso buscado
$resourceId = array_key_exists('resource_id', $_GET) ? $_GET['resource_id']:'';

// Generamos la respuesta asumiendo que el pedido es correcto
switch( strtoupper($_SERVER['REQUEST_METHOD']) ) {
    case 'GET':
         if ( empty( $resourceId ) ){
            echo json_encode( $books );
         }else{
            if( array_key_exists( $resourceId, $books) ){
                echo json_encode( $books[ $resourceId ] );
            }
        }
        break;
    case 'POST':
        break;
    case 'PUT':
        break;
    case 'DELETE':
        break;
}

Consulta:

$curl "http://localhost:8000?resource_type=books&resource_id=1"

Archivo router.php

<?php

$matches=[];
if(preg_match('/\/([^\/]+)\/([^\/]+)/',$_SERVER["REQUEST_URI"],$matches))
{
    $_GET['resource_type']=$matches[1];    
    $_GET['resource_id']=$matches[2];
    error_log(print_r($matches,1));
    require 'server.php';
}elseif(preg_match('/\/([^\/]+)\/?/',$_SERVER["REQUEST_URI"],$matches))
{
    $_GET['resource_type']=$matches[1];        
    error_log(print_r($matches,1));
    require 'server.php';
}else
{
    error_log('No matches');
    http_response_code(404);
}

?>

Consulta:

$ curl http://localhost:8000/books/1

para aquellos que no entendieron la linea:

$resourceId=array_key_exists('resource_id',$_GET)?$_GET['resource_id']:'';

es un operador ternario.
que es igual a escribir esto:

if(array_key_exists(鈥榬esource_id鈥,$_GET))
{
$resourceId=鈥$_GET[鈥榬esource_id];
}else
{
$resourceId=鈥欌;
}

Este video es oro puro.
La conversion a url amigables esta hecha de manera sencilla y precisa.
@beco tiene un curso, aqui en platzi, de expresiones regulares muy bueno, para comprender a fondo las lineas del preg_match

el micr贸fono es muy potente鈥 me distrae como traga saliva al hablar XD

Del carajo esta clase.! Es como hacer una autopsia al c贸digo, as铆 se aprende medicina.! Excelente.

Para escapar el caracter & (Ampersand) en el CMD de windows se utiliza el caracter ^. Por lo que la petici贸n completa quedar铆a de la siguiente manera:

curl http://localhost:8000?resource_type=books^&resource_id=2 | jq

Les dejo el c贸digo del router con comentarios de lo que hace para que no se confundan ni les queden lagunas

<?php
    /* El router nos va a permitir configurar el servidor para
     * poder gestionar las URL de las peticiones. Es decir, podremos
     * pasar de una petici贸n con parametros:
     *      https://example.com/?resource_type=books&resource_id=1
     * a una sin par谩metros y m谩s est茅tica:
     *      https://example.com/book/1
     * para que sea m谩s agradable al usuario final.
     */

    $matches = [];

    // Si la URI coincide con la expresi贸n regular (String que empieza con
    // una diagonal, seguido del tipo de recurso, seguido de otra diagonal,
    // seguido del recurso en particular, y que termine con otra diagonal),
    // entonces se agregan el tipo de recurso y el recurso particular al
    // arreglo de matches.
    if(preg_match('/\/([^\/]+)\/([^\/]+)/', $_SERVER['REQUEST_URI'], $matches)){
        // Creamos una URL con par谩metros cuayos valores se obtendr谩n de lo que
        // la funcion preg_match agreg贸 al arreglo
        $_GET['resource_type'] = $matches[1];
        $_GET['resource_id'] = $matches[2];

        // Si algo falla el error se envia a un correo (supuestamente).
        // Ver documentacion de error_log() y leer la descripcio贸n del
        // par谩metro message_type.
        error_log(print_r($matches, 1));

        // Despues de hacer este an谩lisis, se ejecuta el c贸digo del archivo
        // server.php para continuar con la ejecuci贸n de la API
        require 'server.php';
    }
    // Si la URI coincide con la expresi贸n regular (String que empieza con
    // una diagonal, seguido del tipo de recurso,y que termine con otra 
    // diagonal), entonces se agrega el tipo de recurso arreglo de matches.
    elseif(preg_match('/\/([^\/]+)\/?/', $_SERVER['REQUEST_URI'], $matches)){
        $_GET['resource_type'] = $matches[1];
        error_log(print_r($matches, 1));
        require 'server.php';
    } else{
        // Si nada coincidi贸, agregamos la cadena 'No matches' al error log
        // y devolvemos un error 404
        error_log('No matches');
        http_response_code(404); 
    }
?>

Apuntes:
Basicamente la expresion regular evalua, si despues de la primera barra de la URL, existe cualquier conjunto de caracteres que permita una URL, y luego repite el mismo proceso en caso de que haya un par谩metro despues de una segunda barra, en caso tal de que no haya una segunda barra, solamente capturar谩 lo contenido despues de la primera barra (que seria el parametro y en este caso, el parametro de books.

NOTA: En el caso de usar IIS, debemos crear un archivo .htaccess para la reescritura de URL

La operaci贸n del if en la misma linea se usa con el operador mas conocido como operador ternario.

Ejemplo en c#:

int input = new Random().Next(-5, 5);
string classify;

**If Normal**
if (input >= 0)
{
    classify = "nonnegative";
}
else
{
    classify = "negative";
}

**Operador Ternario**
classify = (input >= 0) ? "nonnegative" : "negative";

Consulta de un recurso en particular:
$ curl "http://localhost:800?resource_type=books&resource_id=1"

Rest propone: http://dominio.com/book/1
$ curl http://localhost:8000/books/1

Yo uso XAMP en windows y no lograba que me sirviera el ejemplo lo que he hecho es lo siguiente.

1.- El archivo router.php lo he llamado index.php para evitar que la url tenga la extensi贸n .php

2鈥- He creado un archivo .htaccess a nivel raiz o al nivel del index.php paque todo pase por ah铆

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]

  1. En lugar de usar preg_match use el m茅todo explode() algo as铆

explode(鈥/鈥, $_SERVER[鈥楻EQUEST_URI鈥橾);

Lo que hace esto es dividir mi URL en array cada que se encuentra un /, recomiendo hacer un var_dump para que veas que posici贸n ocupa books y el id

Bueno eso fue todo

<h3>Exponer un recurso en particular a trav茅s de HTTP GET</h3>

De la siguiente forma hacemos una validaci贸n en una sola l铆nea y tambi茅n estamos obteniendo de la url el id del recurso que se quiere consultar

// Levantamos el ID del recurso buscado
$resourceId = array_key_exists('resource_id', $_GET) ? $_GET['resource_id'] : '';

Y en el caso de las respuestas, tenemos que configurar el switch para que nos de una respuesta cuando venga vac铆o la petici贸n y cuando venga llena

switch (strtoupper($_SERVER['REQUEST_METHOD'])) {
    case 'GET':
        if (empty( $resourceId )) {
            echo json_encode( $books );
        } else {
            if (array_key_exists( $resourceId, $books )) {
                echo  json_encode($books[ $resourceId ]);
            }
        }
        break;

Y en la consola tendremos que escribir la petici贸n as铆:

curl http ://localhost:8000/\?resource_type\=books\&resource_id\=1

Si queremos que la petici贸n con la url sea m谩s corta la configuramos as铆:

<?php

$matches=[];

if(preg_match('/\/([^\/]+)\/([^\/]+)/', $_SERVER["REQUEST_URI"], $matches)) {
    $_GET['resource_type'] = $matches[1];    
    $_GET['resource_id'] = $matches[2];
    
    error_log( print_r($matches, 1) );
    require 'create_api.php';
} else if( preg_match('/\/([^\/]+)\/?/', $_SERVER["REQUEST_URI"], $matches) ) {
    $_GET['resource_type'] = $matches[1];        
    error_log( print_r($matches, 1) );
    require 'create_api.php';
} else {
    error_log('No matches');
    http_response_code(404);
}

Y ahora podemos hacer nuestra petici贸n de la siguiente manera:

curl http ://localhost:8000/books/1

Si tienes problemas con 鈥渏p鈥 y estas en Mac, instala.

brew install jq

Link de donde lo resolv铆

LEs dejo mi codigo en php, para validar ademas de libros autores, generos y libros

<?php
//definimos los recursos disponibles
$allowedResourceTypes = [
    'books',
    'authors',
    'genders'
];
//validamos que el recurso este disponible
$resourceType = $_GET['resource_type'];
if(!in_array($resourceType, $allowedResourceTypes)){
    die;
}
//definos los recursos
$books = [
        0 => [
            'title'=>'Lo que el viento se llevo',
            'id_author' => 1,
            'id_gender'=>1
        ],
        1 => [
            'title'=>'La iliada',
            'id_author' => 0,
            'id_gender'=>0,
        ],
        2 => [
            'title'=>'La riqueza de las naciones',
            'id_author' => 2,
            'id_gender'=>2,
        ],
        3 => [
            'title'=>'El diario de Ana Frank',
            'id_author' => 3,
            'id_gender'=>3,
        ],
        4 => [
            'title'=>'La odisea',
            'id_author' => 0,
            'id_gender'=>0,
        ],
        5 => [
            'title'=>'Teor铆a de los sentimientos morales',
            'id_autor' => 2,
            'id_gender'=>2,
        ]
    ];

    $genders = [
        0 => [
            'id_genders' => 0,
            'genero' => 'poeseia/epopeya',

        ],
        1 => [
            'id_genders' => 1,
            'genero' => 'novela',
            
        ],
        2 => [
            'id_genders' => 2,
            'genero' => 'politica/naturaleza humana',
            
        ],
        3 => [
            'id_genders' => 3,
            'genero' => 'autobiografia',
            
        ]

        ];

    $authors =[
        0 => [
            'id_authors' => 0,
            'athors' => 'Homero',
        ],
        1 => [
            'id_authors' => 1,
            'athors' => 'Margaret Mitchell',
        ],
        2 => [
            'id_authors' => 2,
            'athors' => 'Adam Smith',
        ],
        3=>[
            'id_authors' => 3,
            'athors' => 'Ana frank',
        ],
    ];

    header('Content-Type:application/json');
    //levantamos el id del recurso buscado
    $resourceId = array_key_exists('resource_id',$_GET) ? $_GET['resource_id'] : '' ;

    // Generamos la respuesta asumiendo que el pedido es correcto
    switch(strtoupper($_SERVER['REQUEST_METHOD'])){
        case 'GET':
            //Validar que tipo de recurso es
            switch($resourceType){
                case 'books':
                    if(empty($resourceId)){
                        echo json_encode($books);
                    }{
                        if(array_key_exists($resourceId, $books)){
                            echo json_encode($books[$resourceId]);
                        }
                    }
                break;
                case 'authors':
                    if(empty($resourceId)){
                        echo json_encode($authors);
                    }{
                        if(array_key_exists($resourceId, $authors)){
                            echo json_encode($authors[$resourceId]);
                        }
                    }
                break;
                case 'genders':
                    if(empty($resourceId)){
                        echo json_encode($genders);
                    }{
                        if(array_key_exists($resourceId, $genders)){
                            echo json_encode($genders[$resourceId]);
                        }
                    }
                break;

            }
            
            
            break;
        case 'POST':
            break;
        case 'PUT':
            break;
        case 'DELETE':
            break;
    }```

Les dejo el enlace de postman por si desean consumir los recursos de una forma gr谩fica.

https://www.postman.com/downloads/

y enlace del curso de postman de platzi

https://platzi.com/clases/postman/

aprendi a embellecer la url en php nativo, ya que en frameworks no es necesario pq ya existe esa implementacion por medio de router tambien

Buenas, algun lugar donde pueda entender mas sobre lo que hizo aca , documentacion o o video?

if (preg_match('/\/([^\/]+)\/([^\/]+)/', $_SERVER["REQUEST_URI"], $matches)) {
    $_GET['resource_type'] = $matches[1];
    $_GET['resource_id'] = $matches[2];

    error_log( print_r($matches, 1) );
    require 'server.php'; 
}elseif(preg_match('/\/([^\/]+)\/?/', $_SERVER["REQUEST_URI"], $matches)){
    $_GET['resource_type'] = $matches[1];
    error_log( print_R($matches, 1));

    require('server.php');
}else{

    error_log('No matches');
    http_response( 404 );
}```

Si tienen problemas con ejecutar en consola los pedidos usen postman. Su interface es muy amigable y f谩cil de entender, Platzi tiene curso de Postman

Excelente ejemplo para ir entendiendo los est谩ndares del API RESTFUL

Con lo poco que llevo de curso ya me esta pareciondo muy top.

De verdad aprecio este curso porque te explicar c贸mo construir desde cero un api rest aunque lo explique con php. Te da una idea como construirlo en otro lenguaje desde cero.

Me gusta la forma de explicar del profesor cuando escribe el c贸digo, es muy clara!! Esta super! 馃挜馃挜馃挜

Una forma de hacerlo con python usando Flask

from flask import Flask
import json

app = Flask(__name__)

@app.route('/books/<id>', methods=['GET'])
def books(id):
  books_info = {
    "1":{
      "title":"De animales a dioses",
      "id_author":"1",
      "id_genres":"1",
    },
    "2":{
      "title":"Brujula para el mundo contemporaneo",
      "id_author":"2",
      "id_genres":"2",
    },
  }
  if id in  books_info.keys():
    books_json = json.dumps(books_info[id])
  else:
    books_json = "The book was not found"
  return books_json

@app.route('/')
def index():
  return """
  <h1>Hi, World!</h1>
  <h2>You should go to /book/#id_book </h2>
  """

if __name__ == '__main__':
  app.run(debug=True)

Espero entender m谩s cuando pase al API REST con Laravel. /:

tambien se puede (y es lo que a nosotros los novatos nos funciona mucho) if (isset($_GET['resource_id])){ $id = $_GET['resource_id'] }else{ $id = "" }

Excelente clase ahora entiendo el porqu茅 de esas urls poco amigables, que no sirven para SEO.

preg_match para url amigable

hubiese sido bueno que hubieras dejado el codigo del Route en los marcadores

Por otra parte con laravel ya configura la ruta de un CRUD para que la URL sea midominio.com/book/1 con esta linea en web.php

Route::resource('book','BooksController');

2 dias me demore en esta clase por q no entendia como hace las cosas (estoy trabajando desde xampp en windows por q no lo hago con wsl 2 ? por q no se como hacerlo y no encuentro como ).
tuve que crear un file con este nombre : .htaccess
el cual contiene este codigo (copiar y pegar)

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>
    RewriteEngine On

    # Redirect Trailing Slashes...
    RewriteRule ^(.*)/$ /$1 [L,R=301]

    # Handle Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ router.php [L]
</IfModule>

y luego el router tuve que hacer estas modificaciones , lo copias lo pegas y lo pruebas hasta q entiendas como funciona la expresion regular , la cual es la unica diferencia entre el archivo del profe y este que les dejo.

router.php

<?php

echo '<h2>has leido el router.php </h2>';
$matches = [];

if (preg_match('/\/([^\/]+)\/([^\/]+)\/([^\/]+)/', $_SERVER["REQUEST_URI"], $matches)) {
    
    $_GET['resource_type'] = $matches[2];
    $_GET['resource_id'] = $matches[3];
    if(isset($matches[4])  ){
        $_GET['tercero'] = $matches[4];
    }

    echo $_GET['resource_type'] .' es lo que llego en el resource_type <br>';
    echo $_GET['resource_id'] . ' es lo quellego en el resource_id <br>';
    if(isset($matches[4])){
        echo $_GET['tercero'] . ' es lo que llego de tercero ';
    }


    error_log( print_r($matches, 2) );
    require 'server.php';
} elseif ( preg_match('/\/([^\/]+)\/([^\/]+)?/', $_SERVER["REQUEST_URI"], $matches) ) {
    echo '$matches[2] contiene '. $matches[2] . ' <br>';
    $_GET['resource_type'] = $matches[2];
    error_log( print_r($matches, 3) );

    require 'server.php';
} else {

    error_log('No matches');
    http_response_code( 404 );
}

Gracias por tu curso y con este lenguaje tan 鈥 OMNIPRESENTE!!!
aun q yo pense q js era el nuevo 鈥渢odo鈥 pues me veo en la necesidad de hechar mano de php q mas o menos consco y API REST con php pues genial

no s茅 sino son curso actualizados, pero nunca me salen de forma local. 馃槮
Les juro que hago paso por paso y no que queda.

Por alguna raz贸n, creo de sintaxis, a mi no me funcionaba. Me mostraba error en la variable $matches lo que hice fue escribirla as铆 $_matches en todos los lugares que aparec铆a y funcion贸.

It works!

Me encantaria que lo hagan en otro lenguaje

En Go:

package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
)

var AllowedResources = map[string]bool{
	"books":   true,
	"authors": true,
	"genres":  true,
}

type Book struct {
	Titulo    string `json:"titulo"`
	Id_Autor  int    `json:"id_autor"`
	Id_gereno int    `json:"id_gereno"`
}

var Books = []Book{
	{
		Titulo:    "Lo que el viento se llevo",
		Id_Autor:  2,
		Id_gereno: 2,
	},
	{
		Titulo:    "El se帽or de los anillos",
		Id_Autor:  1,
		Id_gereno: 1,
	},
	{
		Titulo:    "La Odisea",
		Id_Autor:  1,
		Id_gereno: 3,
	},
}

func main() {
	http.Handle("/", http.HandlerFunc(ExampleHandler))
	http.HandleFunc("/books", books)
	http.HandleFunc("/book/", book)

	http.ListenAndServe(":8080", nil)
}

func book(w http.ResponseWriter, r *http.Request) {
	idstr := r.URL.Path[len("/book/"):]
	id, err := strconv.Atoi(idstr)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		fmt.Fprint(w, "<h1>Bad Request</h1>")
		return
	}

	switch r.Method {
	case http.MethodGet:
		getBook(w, r, id)
	case http.MethodDelete:
		w.Write([]byte("DELETE"))
	}
}

func getBook(w http.ResponseWriter, r *http.Request, id int) {
	// Get a single book
	maxBooks := len(Books)

	if id >= maxBooks {
		w.WriteHeader(http.StatusNotFound)
		fmt.Fprint(w, "<h1>Not Found</h1>")
		return
	}

	book := Books[id]
	response, err := json.Marshal(book)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprint(w, "<h1>Internal Server Error</h1>")
		return
	}

	fmt.Fprint(w, string(response))
}

func books(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		getBooks(w, r)
	case "POST":
		postBooks(w, r)
	}
}

func getBooks(w http.ResponseWriter, r *http.Request) {
	respose, err := json.Marshal(Books)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprint(w, "<h1>Internal Server Error</h1>")
		return
	}

	fmt.Fprint(w, string(respose))
}

func postBooks(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("POST"))
}

Mi c贸digo en Python con FastAPI

yo recuerdo que tambi茅n se ten铆a que modificar algunas configuraciones en apache para poder tener url amigables

ESTE CURSO ES TEORICO Y PRACTICO

clase de implementaci贸n de URLs amigables!, ni me pregunten c贸mo lo hubiera hecho yo (shame on me), hubiera buscado cosas como: verificaci贸n de mod_rewrite de Apache, inclusi贸n de .htaccess, par de l铆neas en este archivo, luego otras para que coincidiera con los par谩metros correspondientes con los recursos a consultar 鈥 qu茅 va!, pero qu茅 bueno que estamos aqu铆 aprendiendo y actualiz谩ndonos! 馃馃槉馃榿

Pagina donde se ense帽a todo sobre expresiones regulares, esta en ingles:

https://www.regular-expressions.info/tutorial.html

隆Excelente!, ver el uso de las expresiones regulares.

gracias 馃槂

TIP; para no estar cerrando y abriendo la consola cada vez que empiezan el server, pueden usar ctrl (o command en MAC) + C. El server se cerrar谩 y luego lo pueden iniciar de nuevo.

Excelente

Vale, lo que hace el router es hacer match con una cadena tipo /algo/otracosa y asigna los valores a la variable $_GET, y por 煤ltimo delega toda la informaci贸n al server.php