【问题标题】:Laravel 4 Eloquent get ids of relationsLaravel 4 Eloquent 获取关系 ID
【发布时间】:2013-12-14 19:30:51
【问题描述】:

我正在构建一个客户端应用程序,它需要在我的服务器 API 响应中包含相关模型的 ID。

在我的示例中,我有两个模型,一个 Post 模型和一个 Tag 模型。它们之间的关系是多对多的,所以需要一个数据透视表。

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 路由上设置了一个资源丰富的控制器,如下所示:

class PostsController extends \BaseController {

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

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

}

这将返回一个很像这样的响应:

{
    "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 ]
        }
    ]
}

【问题讨论】:

    标签: php laravel-4 eloquent


    【解决方案1】:

    Eloquent 关系返回一个你可以过滤甚至修改的集合对象,比如如果你只需要一个 id 的数组,你可以这样做:

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

    【讨论】:

      【解决方案2】:

      将以下代码添加到您的模型/基础模型中:

      /**
       * 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;
      }
      

      您可以像这样在模型/集合对象上使用它:

      // Fetch posts data
      $data = Post::with('tags')->get(); // or use ->first()
      
      // Convert relationship data to list of id's
      $data->listAttributes($data, 'tags');
      

      $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');
      

      【讨论】:

        【解决方案3】:

        这不是最优雅的解决方案,但它可能会像你想要的那样工作(代码未经测试)

        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]);
        }
        

        【讨论】:

          【解决方案4】:

          我认为您需要使用 $appends 属性。看看这里的文档http://laravel.com/docs/eloquent#converting-to-arrays-or-json

          这个问题也很重要,因为他遇到了与您相同的问题(请参阅已接受答案的编辑)。

          Add a custom attribute to a Laravel / Eloquent model on load?

          【讨论】:

          • 有什么方法可以为所有关系做到这一点吗?
          • 我还需要能够获取 ids
          猜你喜欢
          • 2015-01-01
          • 2020-11-26
          • 2021-04-05
          • 2017-01-14
          • 1970-01-01
          • 2017-01-12
          • 2017-05-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多