# Documentación Marvel API
Puntos principales:
## IndexController:
```php=
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class IndexController extends Controller
{
/* Alojamos los datos de la conexión fuera de las funciones.*/
var $url = 'https://gateway.marvel.com:443/v1/public/';
public function index($offset=0) {
$url = $this->url .'characters?offset='. $offset.'&';
$result = json_decode($this->makeRequest($url));
if(!isset($result->data)) {
abort(404);
}
$total = $result->data->total;
$result = $result->data->results;
return view('index', ['result'=>$result, 'offset'=>$offset, 'total'=>$total]);
}
Credenciales de acceso a la API de marvel
public function generateURL($url) {
$public_key = 'ec8a1fb650d39076b1e3ce57e88fe2a9';
$private_key = 'fe05b324befc6b4d39b5611424a45581295269d6';
$ts= time();
$hash = md5($ts.$private_key.$public_key);
return $url . 'apikey='. $public_key. '&ts='.$ts.'&hash='.$hash;
}
Request a la api de marvel
public function makeRequest($url) {
$curl = curl_init();
$data_url = $this->generateURL($url);
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => $data_url
]);
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
/*Función que muestra un personaje individual*/
public function show($id)
{
$url = $this->url . 'characters/' . $id . '?'; // URL para obtener detalles de un personaje específico
$characterData = json_decode($this->makeRequest($url));
// Verifica si se obtuvo la información del personaje
if (!isset($characterData->data) || !isset($characterData->data->results[0])) {
return redirect()->route('index')->with('error', 'Detalles del personaje no encontrados');
}
$character = $characterData->data->results[0];
return view('show', compact('character'));
}
/*Función que se encarga de la búsqueda y filtrado de personajes*/
public function filterCharacters(Request $request)
{
$nameFilter = $request->input('name');
$letterFilter = $request->input('filter');
$url = $this->url . 'characters?';
if ($nameFilter) {
$url .= 'nameStartsWith=' . $nameFilter . '&';
}
if ($letterFilter) {
$url .= 'nameStartsWith=' . $letterFilter . '&';
}
$result = json_decode($this->makeRequest($url));
if (!isset($result->data)) {
abort(404);
}
$characters = $result->data->results;
return view('filtered-characters', compact('characters'));
}
}
```
## Plantilla del header
```php=
<!DOCTYPE html>
<html lang="en">
<style>
.header-container {
background-color: rgba(255, 255, 255, 0.5);
}
</style>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css2?family=Rajdhani&display=swap" rel="stylesheet">
<link rel="stylesheet" href="{{asset('css/index.css')}}">
<title>ChupiMarvel</title>
</head>
<body>
<div class="container header-container">
<div class="show">
<a href="{{route('index')}}">
<img
src="https://designconceitual.com.br/wp-content/uploads/2016/07/Marvel_Studios_logo.svg_.png"
style="width: 250px;margin:0 auto;padding: 10px 10px 10px 10px"
alt="">
</a>
</div>
```
## Index (página principal)
```php=
@include('layouts.header')
<style>
body {
/* La imagen del background viene dada por una URL porque soy un mal programador.*/
background-image: url('https://external-preview.redd.it/x_BaPYAxk2f_G9g52hcWIThT0hoanye9zcjJJweFZkg.jpg?width=640&crop=smart&auto=webp&s=849263ee6ecbc498e87da055cad359206cc77190');
background-size: cover;
background-repeat: no-repeat;
background-attachment: fixed;
color: #fff;
margin: 0;
padding: 0;
box-sizing: border-box;
}
.main-container {
margin: 2%;
}
.card {
background-color: rgba(0, 0, 0, 0.7);
color: #fff;
margin-bottom: 15px;
}
form {
color:black;
}
</style>
<div class="main-container">
<div class="show">
<h1 style="color:black;"> LISTA DE PERSONAJES </h1>
/* El form es la parte con más chicha del index, ya que se encarga de la búsqueda de personajes haciendo consultas a la Api porque, de nuevo, soy mal programador.*/
</div>
<form action="{{ route('filterCharacters') }}" method="GET" class="form-group" style="width: 80%; margin: 0 auto;">
<label for="name">Buscar por nombre:</label>
<input type="text" name="name" class="form-control" style="width: 80%;" placeholder="Busca tu personaje..." value="{{ request('name') }}">
<label for="filter">Filtrar por letra:</label>
<select name="filter" class="form-control">
<option value="" {{ request('filter') === '' ? 'selected' : '' }}>Sin filtro</option>
@foreach(range('A', 'Z') as $letter)
<option value="{{ $letter }}" {{ request('filter') === $letter ? 'selected' : '' }}>{{ $letter }}</option>
@endforeach
</select>
¿Sabes por qué he puesto el botón de búsqueda y filtrado en el mismo? Exacto.
<button type="submit" class="btn btn-light btn-sm" style="margin: 5px;">Filtrar y buscar</button>
</form>
<div class="show">
<div class="row">
@foreach ($result as $r)
<div class='col-md-3'>
<div class='card d-flex flex-column'>
<img src="{{ $r->thumbnail->path.'.'.$r->thumbnail->extension }}" class="card-img-top" alt="{{ $r->name }}">
<div class='card-body'>
<h4 class='card-title'>{{ $r->name }}</h4>
<a href="{{ route('character.show', $r->id) }}" class="btn btn-danger btn-sm">Ver más</a>
</div>
</div>
</div>
@endforeach
</div>
</div>
Botones de paginación. No funcionan muy bien, no sé si por el código en sí o porque la API no me da suficiente recursos para paginar. Avisado estás.
<div class="buttons">
@if($offset != 0)
<a href="{{ route('index', $offset - 20) }}" class="btn btn-light">Anterior</a>
@endif
@if($total >= $offset + 20)
<a href="{{ route('index', $offset + 20) }}" class="btn btn-light" style="margin:2%;">Próximo</a>
@endif
</div>
</div>
</body>
</html>
```
## Show (página de personajes individuales)
```php=
@include('layouts.header')
<style>
body {
margin: 2%;
position: relative;
}
.background-container::before {
content: "";
background: url('https://external-preview.redd.it/x_BaPYAxk2f_G9g52hcWIThT0hoanye9zcjJJweFZkg.jpg?width=640&crop=smart&auto=webp&s=849263ee6ecbc498e87da055cad359206cc77190') center center;
background-size: cover;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: -1;
opacity: 0.5;
}
.main-container {
height: 100vh; /* Ajustar la altura al 100% de la ventana */
display: flex;
justify-content: center;
align-items: center;
}
.show {
color: #fff;
margin-bottom: 2%;
}
.card {
background-color: rgba(0, 0, 0, 0.7);
color: #fff;
height: 100%; /* Ocupar el 100% de la altura del contenedor */
display: flex;
flex-direction: column;
justify-content: space-between; /* Ajustar el espacio entre elementos */
}
.comic-list {
list-style-type: none;
padding: 0;
}
</style>
<div class="background-container">
<div class="main-container">
<div class='col-md-6'>
<div class='card'>
<img src="{{ $character->thumbnail->path.'.'.$character->thumbnail->extension }}" class="card-img-top" alt="{{ $character->name }}">
<div class='card-body'>
<h4 class='card-title'>{{ $character->name }}</h4> /* Simplemente consultamos los datos de la API. */
<p class="card-text">{{ $character->description }}</p>
<p class="card-text"><strong>Número de cómics:</strong> {{ $character->comics->available }}</p>
<strong>Cómics:</strong>
<ul class="comic-list">
@foreach ($character->comics->items as $comic)
<li>{{ $comic->name }}</li>
@endforeach
</ul>
<a href="{{ route('index') }}" class="btn btn-danger btn-sm">Volver a la Lista</a>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
```
## Vista de filtrado:
```php=
@include('layouts.header')
<style>
body {
background-image: url('https://external-preview.redd.it/x_BaPYAxk2f_G9g52hcWIThT0hoanye9zcjJJweFZkg.jpg?width=640&crop=smart&auto=webp&s=849263ee6ecbc498e87da055cad359206cc77190');
background-size: cover;
background-repeat: no-repeat;
background-attachment: fixed;
color: #fff;
margin: 0;
padding: 0;
box-sizing: border-box;
}
.main-container {
margin: 2%;
}
.card {
background-color: rgba(0, 0, 0, 0.7);
color: #fff;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
margin-bottom: 15px;
padding: 15px;
}
.filtered-cards-container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.filtered-card-wrapper {
width: 23%;
margin-bottom: 20px;
}
.btn-ver-mas {
margin-top: 10px;
}
</style>
<div class="background-container">
<div class="main-container">
<h1 class="show">Resultados del Filtro</h1>
<div class="filtered-cards-container">
@foreach ($characters as $character)
<div class='filtered-card-wrapper'>
<div class='card'>
<img src="{{ $character->thumbnail->path.'.'.$character->thumbnail->extension }}" class="card-img-top" alt="{{ $character->name }}">
<div class='card-body'>
<h4 class='card-title'>{{ $character->name }}</h4>
</div>
<a href="{{ route('character.show', $character->id) }}" class="btn btn-danger btn-sm btn-ver-mas">Ver más</a>
</div>
</div>
@endforeach
</div>
</div>
</div>
</body>
</html>
```
## WEB (rutas)
```php=
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\IndexController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "web" middleware group. Make something great!
|
*/
/* Solo hay 3 rutas, la del index, la del show y la de filtrado. */
Route::get('/index', [IndexController::class, 'index'])->name('index');
Route::get('/filter-characters', [IndexController::class, 'filterCharacters'])->name('filterCharacters');
Route::get('/personajes/{id}', [IndexController::class, 'show'])->name('character.show');
```