2013-11-28 3 views
1

내 서버 API 응답에 관련 모델의 ID가 필요한 클라이언트 응용 프로그램을 작성 중입니다.Laravel 4 관계 맺기가 매우 어리 석다

필자의 예에서는 Post 모델과 Tag 모델이라는 두 가지 모델이 있습니다. 그들 사이의 관계는 다 대다이므로, 피벗 테이블이 필요합니다. 이 훨씬 이와 같은 응답을 반환합니다

class PostsController extends \BaseController { 

    public function index() 
    { 
     $posts = Post::all(); 

     return Response::json([ 'posts' => $posts->toArray() ]); 
    } 

} 

:

class Post extends Eloquent { 

    protected $fillable = [ 'title', 'body' ]; 

    public function tags() 
    { 
     return $this->hasMany('Tag'); 
    } 

} 

class Tag extends Eloquent { 

    protected $fillable = [ 'title' ]; 

    public function posts() 
    { 
     return $this->belongsToMany('Post'); 
    } 

} 

나는이 같은 /api/posts 노선에 설정된 resourcefull 컨트롤러를 가지고 내가 '무엇

{ 
    "posts": [ 
     { 
      "title": "Laravel is awesome", 
      "body": "Lorem Ipsum..." 
     }, 
     { 
      "title": "Did I mention how awesome Laravel is?", 
      "body": "Lorem Ipsum..." 
     } 
    ] 
} 

찾는 방법은 다음과 같이 관련 태그 모델의 ID를 다음과 같이 응답에 포함시키는 쉬운 방법입니다.

{ 
    "posts": [ 
     { 
      "title": "Laravel is awesome", 
      "body": "Lorem Ipsum...", 
      "tags": [ 1, 2, 3 ] 
     }, 
     { 
      "title": "Did I mention how awesome Laravel is?", 
      "body": "Lorem Ipsum...", 
      "tags": [ 1, 2, 4 ] 
     } 
    ] 
} 

답변

1

를 원하는 것처럼 작동 할 수 있습니다

/** 
* Set additional attributes as hidden on the current Model 
* 
* @return instanceof Model 
*/ 
public function addHidden($attribute) 
{ 
    $hidden = $this->getHidden(); 

    array_push($hidden, $attribute); 

    $this->setHidden($hidden); 

    // Make method chainable 
    return $this; 
} 

/** 
* Convert appended collections into a list of attributes 
* 
* @param object  $data  Model OR Collection 
* @param string|array $levels  Levels to iterate over 
* @param string  $attribute The attribute we want to get listified 
* @param boolean  $hideOrigin Hide the original relationship data from the result set 
* @return Model 
*/ 
public function listAttributes($data, $levels, $attribute = 'id', $hideOrigin = true) 
{ 

    // Set some defaults on first call of this function (because this function is recursive) 
    if (! is_array($levels)) 
     $levels = explode('.', $levels); 

    if ($data instanceof Illuminate\Database\Eloquent\Collection) // Collection of Model objects 
    { 
     // We are dealing with an array here, so iterate over its contents and use recursion to look deeper: 
     foreach ($data as $row) 
     { 
      $this->listAttributes($row, $levels, $attribute, $hideOrigin); 
     } 
    } 
    else 
    { 
     // Fetch the name of the current level we are looking at 
     $curLevel = array_shift($levels); 

     if (is_object($data->{$curLevel})) 
     { 
      if (! empty($levels)) 
      { 
       // We are traversing the right section, but are not at the level of the list yet... Let's use recursion to look deeper: 
       $this->listAttributes($data->{$curLevel}, $levels, $attribute, $hideOrigin); 
      } 
      else 
      { 
       // Hide the appended collection itself from the result set, if the user didn't request it 
       if ($hideOrigin) 
        $data->addHidden($curLevel); 

       // Convert Collection to Eloquent lists() 
       if (is_array($attribute)) // Use specific attributes as key and value 
        $data->{$curLevel . '_' . $attribute[0]} = $data->{$curLevel}->lists($attribute[0], $attribute[1]); 
       else // Use specific attribute as value (= numeric keys) 
        $data->{$curLevel . '_' . $attribute} = $data->{$curLevel}->lists($attribute); 
      } 
     } 
    } 

    return $data; 
} 

다음과 같이 모델/컬렉션 개체에서 사용할 수 있습니다.

또한 중첩 된 관계 지원

{ 
    "posts": [ 
     { 
      "title": "Laravel is awesome", 
      "body": "Lorem Ipsum...", 
      "tags_id": [ 1, 2, 3 ] 
     }, 
     { 
      "title": "Did I mention how awesome Laravel is?", 
      "body": "Lorem Ipsum...", 
      "tags_id": [ 1, 2, 4 ] 
     } 
    ] 
} 

:

$ 데이터가 이제 다음 객체 저장소를 포함

// Fetch posts data 
$data = Post::with('comments', 'comments.tags')->get(); // or use ->first() 

// Convert relationship data to list of id's 
$data->listAttributes($data, 'comments.tags'); 
2

모델에 다음 코드를 추가/BASEMODEL이 가장 우아한 해결책이 아니라 당신이 (안 테스트 코드)

public function index() 
{ 
    $posts = Post::all(); 

    $postsArray = array(); 

    foreach ($posts as $post) 
    { 
     $postArray = $post->toArray(); 

     $postArray['tags'] = array_values($post->tags->lists('id')); 

     $postsArray[] = $postArray; 
    } 

    return Response::json([ 'posts' => $postsArray]); 
} 
0

웅변 관계가 필터링 또는 수정할 수있는 컬렉션 개체를 반환을 말해봐 당신은 이드의 배열만을 필요로합니다 :

$posts->pluck('id'); 

$posts->pluck('id')->toArray();