Laravel 5

Fichier Json

Avatar de WilliamMaquin
WilliamMaquin

Bonjour la commu !

Je suis un débutant ++ sur Laravel et je suis en train d'essayer de build un site internet.

Voilà ma question, je souhaiterais charger un fichier json dans un controller et charger la description d'un objet avec son nom. Je vous explique :

Le fichier json (une partie)

"data": {
"1001": {
"name": "Bottes de vitesse",
"description": "<groupLimit>Limité à 1 paire de bottes.</groupLimit><br><br><unique>Propriété passive UNIQUE - Déplacements améliorés :</unique> +25 vitesse de déplacement",
"colloq": ";Boots of Speed;bottes de vitesse",
"plaintext": "Augmente légèrement la vitesse de déplacement.",
"into": [
"3006",
"3047",
"3020",
"3158",
"3111",
"3117",
"3009",
"3173",
"4001"
],
"image": {
"full": "1001.png",
"sprite": "item0.png",
"group": "item",
"x": 0,
"y": 0,
"w": 48,
"h": 48
},
"gold": {
"base": 300,
"purchasable": true,
"total": 300,
"sell": 210
},
"tags": [
"Boots"
],
"maps": {
"10": true,
"11": true,
"12": true
}
"stats": {
"FlatMovementSpeedMod": 25
}
}

Je voudrais par exemple écrire dans mon fichier blade description:Bottes de vitesse et que celui ci me renvoie : Limité à 1 paire de bottes. Propriété passive UNIQUE - Déplacements améliorés : +25 vitesse de déplacement. Ou encore image-full:Bottes de vitesse et qu'il me retourne : 1001.png

Voilà, je sais que la syntaxe d'exemple que je vous ai donné n'est pas la bonne, comme je vous ai dit je débute et je n'y connais pas grand chose encore. Je ne sais même pas si ceci est réalisable.

Merci de l'attention que vous y porterez.

Posté il y a 1 an
Avatar de bestmomo
bestmomo

Salut,

Pour utiliser des infos en json avec php classiquement on transforme avec json_decode() pour obtenir une stdClass ou un tableau.

Une bonne idée quand on utilise Laravel est de transformer les données en collection :

$maCollection = collect(json_decode($json, true))

Ensuite toutes les méthodes des collections deviennent disponibles...

Posté il y a 1 an
Avatar de WilliamMaquin
WilliamMaquin

Merci de ta réponse, cependant, ca ne résoud pas mon problème je n'y comprends rien x)

Posté il y a 1 an
Avatar de bestmomo
bestmomo

Les collections sont très puissantes et permettent une approche déclarative du code, dans le cas de ton fichier JSON je suppose qu'il se compose en gros ainsi avec des références numériques et des informations par référence :

$json = '{
    "data": {
        "1001": {
            "name": "Bottes de vitesse",
            "description": "<groupLimit>Limité à 1 paire de bottes.</groupLimit><br><br><unique>Propriété passive UNIQUE - Déplacements améliorés :</unique> +25 vitesse de déplacement",
            "image": {
                "full": "1001.png",
                "sprite": "item0.png",
                "group": "item",
                "x": 0,
                "y": 0,
                "w": 48,
                "h": 48
            }
        },
        "1002": {
            "name": "Bottes de promenade",
            "description": "<groupLimit>Limité à 2 paires de bottes.</groupLimit><br><br><unique>Propriété passive UNIQUE - Déplacements améliorés :</unique> +25 vitesse de déplacement",
            "image": {
                "full": "1002.png",
                "sprite": "item0.png",
                "group": "item",
                "x": 0,
                "y": 0,
                "w": 48,
                "h": 48
            }
        }
    }
}';

Si je pars de ce fichier et que je veux récupérer les informations à partir d'un nom spécifique par exemple Bottes de vitesse. Je vais écrire ce genre de code :

$name = 'Bottes de vitesse';

$article = collect(json_decode($json, true)['data'])
    ->first(function ($value, $key) use($name) {
        return $value['name'] == $name;
    });

dd($article);

Je transforme le JSON en collection et je fais une recherche avec la fonction first. A la sortie j'ai un tableau avec les renseignements :

array:3 [▼
  "name" => "Bottes de vitesse"
  "description" => "<groupLimit>Limité à 1 paire de bottes.</groupLimit><br><br><unique>Propriété passive UNIQUE - Déplacements améliorés :</unique> +25 vitesse de déplacement"
  "image" => array:7 [▼
    "full" => "1001.png"
    "sprite" => "item0.png"
    "group" => "item"
    "x" => 0
    "y" => 0
    "w" => 48
    "h" => 48
  ]
]

Je peux envoyer ce tableau dans une vue Blade :

return view('mavue', compact('article'));

Dans la vue :

<p>Nom : {{ $article['name']}}</p>
<p>Description : {!! $article['description'] !!}</p>
<p>Image : {{ $article['image']['full'] }}</p>

Ce qui donne en visuel :

Nom : Bottes de vitesse
Description : Limité à 1 paire de bottes.
Propriété passive UNIQUE - Déplacements améliorés : +25 vitesse de déplacement
Image : 1001.png
Posté il y a 1 an
Avatar de WilliamMaquin
WilliamMaquin

Ce que tu viens de me donner m'aide beaucoup en effet, seulement je dois le faire pour un peu près 1000 objets si tu veut le fichier complet se trouve ici. Donc avec la technique que tu m'as donné, je vais devoir créer un nombre incalculable de variables en sachant qu'il faut que je le fasse avec les items.

Il n'est pas possible de créer un input dans la variable $name et charger le fichier json en entier pour qu'au final dans la vue ca rende :

 <p>  Nom : {{ 'Bottes de vitesse'->['name'] }}</p>
<p> Description {{!! 'Bottes de vitesse'->['description'] !!}}</p>
<p>Image : {{'Bottes de vitesse'->['image']['full'] }}</p>

Et que celui ci rende la même vue que celle que tu m'as donné au dessus.

Posté il y a 1 an
Avatar de bestmomo
bestmomo

Si tu accèdes à une API pour récupérer les données et sélectionner un produit pour afficher ses caractéristiques alors je ne vois pas l'intérêt de passer par Laravel et une vue, autant partir sur du SPA.

Posté il y a 1 an
Avatar de WilliamMaquin
WilliamMaquin

Je ne sais pas ce qu'est que le SPA, je souhaite faire des guides avec ce json et malheureusement je devrais les utiliser plusieurs fois dans plusieurs pages différentes. Je n'utilise pas d'api j'ai juste les fichiers json pour me permettre d'effectuer ce que je veux..

En fait ce sont des guides sur league of legends et le json appartiens au client même du jeu.

Posté il y a 1 an
Avatar de bestmomo
bestmomo

Côté Javascript tu es plutôt classique jQuery ou alors approches plus modernes Vue ou React ?

Posté il y a 1 an
Avatar de WilliamMaquin
WilliamMaquin

Je ne sais pas je n'utilise que trs peu le js d'habitude ou alors je prends des scripts tout faits sur internet :/

Posté il y a 1 an
Avatar de bestmomo
bestmomo

La tendance actuelle est plutôt d'en utiliser de plus en plus justement pour rendre les application réactives.

Posté il y a 1 an
Avatar de WilliamMaquin
WilliamMaquin

Dac mais en quoi ca résoudrais mon problème ? xD

Posté il y a 1 an
Avatar de bestmomo
bestmomo

Parce que tu pourrais avoir une liste déroulante avec tous les noms et clic pour faire apparaître les éléments, avec un peu d'ajax pour faire tourner le truc.

Posté il y a 1 an
Avatar de WilliamMaquin
WilliamMaquin

Intégrer ceci dans laravel c'est faisable ?

Posté il y a 1 an
Avatar de bestmomo
bestmomo

On peut tout faire avec Laravel ;)

Posté il y a 1 an
Avatar de WilliamMaquin
WilliamMaquin

Dac mais comment x)

Posté il y a 1 an
Avatar de bestmomo
bestmomo

En gros on commence par envoyer une page avec la liste déroulante remplie avec les noms. Ensuite un clic sur un nom envoie une requête Ajax à Laravel qui renvoie les informations pour raffraichir la partie de la page concernée.

Avec SPA (Single Page Application) c'est tout le JSON qu'on envoie et en local Javascript gère l'affichage, ça évite les va et vient avec le serveur.

Posté il y a 1 an
Avatar de WilliamMaquin
WilliamMaquin

Oui fin c'est du chinois pour moi ca j'ai aucune idée de comment faire ca x)

Posté il y a 1 an
Avatar de bestmomo
bestmomo

Oui je complèterai ma réponse...

Posté il y a 1 an
Avatar de bestmomo
bestmomo

Pour l'exemple je pars d'une installation toute fraîche de Laravel...

En partant du principe qu'on a le fichier JSON en public/json/data.json. On change dans config/filesystems.php pour faciliter l'accès :

'disks' => [
    'local' => [
        'driver' => 'local',
        'root' => public_path(),
    ],

Dans les routes (routes/web.php) :

Route::get('/', 'HomeController@index')->name('home');
Route::get('infos/{id}', 'HomeController@infos');

Le contrôleur (HomeController) :

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

class HomeController extends Controller
{
    public function index()
    {
        $names = $this->getData()->pluck('name');
        return view('home', compact('names'));
    }

    public function infos($id)
    {
        $values = $this->getData()->forPage($id + 1, 1)->first();
        return view('values', compact('values'));
    }

    protected function getData()
    {
        $data = Storage::get('json/data.json');
        return collect(json_decode($data, true)['data']);
    }
}

La vue home modifiée :

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">Recherche par nom</div>
                <div class="card-body">
                    <form>
                        <div class="form-group">
                            <select id="names" class="custom-select">
                                <option selected>Choisissez un nom</option>
                                @foreach($names as $name)
                                    <option value="{{ $loop->index }}">{{ $name }}</option>
                                @endforeach
                            </select>
                        </div>
                    </form>
                    <div id="infos"></div>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

@section('scripts')

<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>

<script>
    $(function(){
        $('#names').change(function() {
            $.get('{{ url('infos') }}/'+ $(this).val(), function(data) {
                $('#infos').html(data);
            });
        });
    })
</script>

@endsection

Et une nouvelle vue values :

<p>Nom : {{ $values['name']}}</p>
<p>Description : {!! $values['description'] !!}</p>
<p>Image : {{ $values['image']['full'] }}</p>

Ca fonctionne de façon très simple mais ça serait bien plus efficace avec une approche SPA. Si je trouve du temps je développerai cet aspect.

Edit : j'ai écrit un petit article sur le sujet.

Posté il y a 1 an
Avatar de WilliamMaquin
WilliamMaquin

Bravo pour le site ! Je le connaissais mais je ne savais pas que c'était toi qui l'avait fait ! J'ai un souci avec ton code cependant, j'ai utilisé la deuxime manière que tu as démontré sur ton site et à l'adresse /vueversion il n'y a rien.

Je ne sais pas d'ou ca peut provenir j'ai peut être pas placé le json au bon endroit. Comme je n'avais pas de folder json j'en ai crée un dans ressources/assets/js/components/json/ puisque le app.js est dans /components/ je ne sais pas si le problème viens de là..

Posté il y a 1 an

Vous ne pouvez pas répondre à ce sujet.