2017-07-24 1 views
1

Ich habe das schon seit einiger Zeit versucht herauszufinden. Im Grunde habe ich 2 Modelle 'Rezept', 'Zutat' und einen Controller 'RezeptController'. Ich benutze Postman, um meine API zu testen. Als ich zu meinem get Weg zu gehen, den RecipeController @ getRecipe verwendet, ist der Rückgabewert gemäß dem Bild unten:Laravel API APP viele-viele Beziehung, wie bestimmte Informationen in JSON zurückgegeben werden?

Return for Get Route

Wenn ich der Rückgabewert der Route planen, um in dem Format der unten will Bild, wie erreiche ich das? Damit meine ich, dass ich nicht nach den Rezepten sehen möchte: die Spalte created_at, die Spalte updated_at und für die Zutaten: die Pivot-Informationsspalte, nur die Spalteninformationen für Name und Menge.

Return Value Format I Want

Rezeptmodell:

<?php 

namespace App; 

use Illuminate\Database\Eloquent\Model; 

class Recipe extends Model 
{ 
    protected $fillable = ['name', 'description']; 

    public function ingredients() 
    { 
     return $this->belongsToMany(Ingredient::class, 
     'ingredient_recipes')->select(array('name', 'amount')); 
    } 
} 

Ingredient Modell:

<?php 

namespace App; 

use Illuminate\Database\Eloquent\Model; 

class Ingredient extends Model 
{ 
    protected $fillable = ['name', 'amount']; 
} 

RecipeController

<?php 

namespace App\Http\Controllers; 


use App\Ingredient; 
use App\Recipe; 
use Illuminate\Http\Request; 

class RecipeController extends Controller { 

public function postRecipe(Request $request) 
{ 
    $recipe = new Recipe(); 
    $recipe->name = $request->input('name'); 
    $recipe->description = $request->input('description'); 
    $recipe->save(); 

    $array_ingredients = $request->input('ingredients'); 
    foreach ($array_ingredients as $array_ingredient) { 
     $ingredient = new Ingredient(); 
     $ingredient->name = $array_ingredient['ingredient_name']; 
     $ingredient->amount = $array_ingredient['ingredient_amount']; 
     $ingredient->save(); 
     $recipe->ingredients()->attach($ingredient->id); 
    } 

    return response()->json(['recipe' => $recipe . $ingredient], 201); 
} 

public function getRecipe() 
{ 
    $recipes = Recipe::all(); 
    foreach ($recipes as $recipe) { 
     $recipe = $recipe->ingredients; 
    } 
    $response = [ 
     'recipes' => $recipes 
    ]; 
    return response()->json($response, 200); 
} 

API Routes:

Route::post('/recipe', '[email protected]')->name('get_recipe'); 
Route::get('/recipe', '[email protected]')->name('post_recipe'); 

Danke Jungs!

Antwort

0

Ich denke, Ihre beste Lösung ist Transformer. Ihre aktuelle Implementierung mit, was würde ich empfehlen, ist in der Schleife nur das benötigte Feld zu holen, das heißt:

foreach ($recipes as $recipe) { 
    $recipe = $recipe->ingredients->only(['ingredient_name', 'ingredient_amount']); 
} 

Während die oben funktionieren könnte, aber es gibt ein Problem mit Ihrer aktuellen Implementierung, weil es Tonnen von Iteration wird/Wenn ich die Datenbank abfragen möchte, würde ich empfehlen, stattdessen die Relation zu laden. Aber für diese Frage brauchen Sie nur Transformer.

Install Transformator mit Composer Dann können Sie ein Verzeichnis mit dem Namen Transformers unter dem app Verzeichnis erstellen.

Erstellen Sie dann eine Klasse namens RecipesTransformer und initialisieren mit:

use App\Transformers\RecipesTransformer; 
...... 
public function getRecipe() 
{ 
    return $this->collection(Recipe::all(), new RecipesTransformer); 
    //or if you need to get one 
    return $this->item(Recipe::first(), new RecipesTransformer); 
} 

Sie können auf ein gutes Tutorial beziehen like this:

namespace App\Transformers; 

use App\Recipe; 

use League\Fractal\TransformerAbstract; 

class RecipesTransformer extends TransformerAbstract 
{ 
    public function transform(Recipe $recipe) 
    { 
     return [ 
      'name' => $recipe->name, 
      'description' => $recipe->description, 
      'ingredients' => 
       $recipe->ingredients->get(['ingredient_name', 'ingredient_amount'])->toArray() 
     ]; 
    } 
} 

Dann Sie diesen Transformator in Ihrem Controller-Methode wie folgt verwenden können für mehr Inspiration, oder gehen Sie einfach zu Fractal's page für Details.

aktualisieren

Um seit dem Beispiel arbeiten Fractal Kollektion, gab ich würde funktionieren, wenn Sie Dingo API in Ihrem Projekt haben, können Sie es manuell erstellen auf diese Weise:

public function getRecipe() 
{ 
    $fractal = app()->make('League\Fractal\Manager'); 
    $resource = new \League\Fractal\Resource\Collection(Recipe::all(), new RecipesTransformer); 

    return response()->json(
     $fractal->createData($resource)->toArray()); 
} 

In Wenn Sie ein Objekt anstelle einer Sammlung erstellen möchten, können Sie stattdessen new \League\Fractal\Resource\Item verwenden. Ich würde empfehlen, dass Sie entweder Dingo API installiert haben oder Sie können this simple tutorial folgen, um sauberer ohne unnötige Wiederholung behandelt zu haben

+0

Hey Omisakin, Danke für die Antwort. Ich habe Liga/Fraktal benötigt, habe die Klasse erstellt und die 'return $ this-> Sammlung implementiert (Recipe :: all(), new RecipesTransformer); 'in meine Steuerung @getRecipe. Das Problem, das ich jetzt bekomme, ist: 'Methode [Sammlung] existiert nicht. ". Die Methode 'Sammlung' wurde nicht im Rezept-Controller gefunden. –

+0

Ich fügte ein Update zu der Antwort @JohnBiggs –

+0

Thx wieder für die Antwort Omisakin. Ich werde in die Dingo API schauen, aber jetzt habe ich das Update auf meinem Controller implementiert und erhalte nun 'array_key_exists(): Das erste Argument sollte entweder eine Zeichenkette oder eine Ganzzahl sein.' ". Wie löse ich das? –

Verwandte Themen