【问题标题】:Laravel Eloquent ORM for Social Network用于社交网络的 Laravel Eloquent ORM
【发布时间】:2014-03-24 09:12:30
【问题描述】:

我的状态帖子有以下数据库设置。对于每个帖子,用户可以点赞帖子、评论帖子,甚至可以在原帖中被作者标记。

我正在尝试设置我的 Resourceful 控制器“发布”以通过 JSON 对象带回所有数据,但我无法正确找到评论、喜欢或标记用户名。如果有区别,我将使用 Sentry 2 进行身份验证。

这是数据库设置:

    CREATE TABLE Users (
        id INT NOT NULL AUTO_INCREMENT,
        first_name VARCHAR(30),
        last_name VARCHAR(30),
        many more...
    );

    CREATE TABLE Posts (
        postID INT NOT NULL AUTO_INCREMENT,
        caption VARCHAR(200), 
        description VARCHAR(200), 
        fromID INT(10) UNSIGNED NOT NULL,
        toID INT(10) UNSIGNED NOT NULL,
        icon VARCHAR(200),
        link VARCHAR(200),
        message TEXT,
        storyType INT,
        type ENUM ('LINK', 'PHOTO', 'STATUSUPDATE', 'VIDEO' ),
        createdTime DATE,
        PRIMARY KEY (postID),
        FOREIGN KEY (fromID) REFERENCES users (id),
        FOREIGN KEY (toID) REFERENCES users (id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

    CREATE TABLE Likes (
        likeID INT NOT NULL AUTO_INCREMENT,
        fromID INT(10) UNSIGNED NOT NULL,
        postID INT NOT NULL,
        createdDate DATE,
        PRIMARY KEY (likeID),
        FOREIGN KEY (fromID) REFERENCES users (id),
        FOREIGN KEY (postID) REFERENCES Posts (postID)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

    CREATE TABLE Comments (
        commentID INT NOT NULL AUTO_INCREMENT,
        fromID INT(10) UNSIGNED NOT NULL,
        postID INT NOT NULL,
        comment TEXT,
        createdDate DATE,
        PRIMARY KEY (commentID),
        FOREIGN KEY (fromID) REFERENCES users (id),
        FOREIGN KEY (postID) REFERENCES Posts (postID)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;


    CREATE TABLE Tags (
        tagID INT NOT NULL AUTO_INCREMENT,
        userID INT(10) UNSIGNED NOT NULL,
        postID INT NOT NULL,
        PRIMARY KEY (tagID),
        FOREIGN KEY (userID) REFERENCES users (id),
        FOREIGN KEY (postID) REFERENCES Posts (postID)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

我的 Post Controller,我只有一个简单的页面,可以显示所有内容。我不想遍历视图文件中的任何内容,我只想带回 json 完整对象。

class PostController extends BaseController {

    public function show($id)
    {
    $post = Post::with(array('comments', 'from', 'tags', 'likes'))->find($id);
    return View::make('samplepage')->with('data', $post);
    }
}

我的帖子模型:

class Post extends Eloquent {

    protected $table = 'Posts';
    protected $primaryKey = 'postID';

    public function comments() 
    {
       return $this->hasMany('Comment','postID');
     }

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

     public function likes() 
     {
       return $this->hasMany('Like','postID');
     }


    public function from() 
    {
        return $this->belongsTo('User', 'fromID')->select(array('id', 'first_name', 'last_name'));
    }

    public function users() 
    {
        return $this->belongsTo('User', 'fromID');
    }

}

评论模型: 类注释扩展 Eloquent {

    protected $table = 'Comments';
    protected $primaryKey = 'commentID';

     public function post() {
       return $this->belongsTo('Post','fromID');
     }

     public function user() {
        return $this->belongsTo('User', 'fromID')->select(array('id', 'first_name', 'last_name'));
    }
}

标签型号: 类标签扩展 Eloquent {

    protected $table = 'Tags';
    protected $primaryKey = 'tagID';

}

我什至在我的用户模型中设置了以下内容,但这没有任何区别。 用户模型:

public function posts() {
   return $this->hasMany('Post','id');
 }

public function comments() {
 return $this->hasMany('Comment','id');
}

这个设置一切正常,当我用下面的代码点击 posts/2 时,我得到了下面的对象。 $post = Post::with(array('cmets', 'from', 'tags', 'likes'))->find($id); return View::make('samplepage')->with('data', $post);

{
   postID: "2",
   toID: "8",
   comments: [
      {
         commentID: "2",
         comment: "second comment",
         fromID: "1",
         postID: "2",
         createdDate: "2014-02-15"
      }
   ],
   from: {
      id: "4",
      first_name: Paul,
      last_name: Davis
   },
   tags: [
      {
         tagID: "1",
         userID: "2",
         postID: "2"
      },
      {
         tagID: "2",
         userID: "3",
         postID: "2"
      }
   ],
   likes: [
      {
         likeID: "1",
         fromID: "2",
         postID: "2",
         createdDate: "2013-01-04"
      },
      {
         likeID: "2",
         fromID: "3",
         postID: "2",
         createdDate: "2013-02-05"
      }
   ]
}

但我想要的是以下内容,对于每个标签,like 和 comment 以连接名字和姓氏并将它们与对象一起返回。

{
   postID: "2",
   toID: "4",
   comments: [
      {
         commentID: "2",
         comment: "second comment",
         fromID: "1",
         from: {
              "name": "Jason Terry", 
              "id": "721286625"
            }, 
         postID: "2",
         createdDate: "2014-02-15"
      }
   ],
   from: {
      id: "4",
      first_name: Paul,
      last_name: Davis
   },
   tags: [
      {
         tagID: "1",
         userID: "2",
         from: {
              "name": "David Lee", 
              "id": "721286625"
            },
         postID: "2"
      },
      {
         tagID: "2",
         userID: "3",
         from: {
              "name": "Paul Pierce", 
              "id": "721286625"
            },
         postID: "2"
      }
   ],
   likes: [
      {
         likeID: "1",
         fromID: "2",
         from: {
              "name": "David Lee", 
              "id": "721286625"
            },
         postID: "2",
         createdDate: "2013-01-04"
      },
      {
         likeID: "2",
         fromID: "3",
         from: {
              "name": "Al Davis", 
              "id": "721286625"
            },
         postID: "2",
         createdDate: "2013-02-05"
      }
   ]
}

我已经搜索 Stackoverflow、无数 Laravel 博客、官方文档 2 周了,我似乎无法解决这个问题。非常感谢任何帮助。

更新: 在下面托尼的回答中,我添加了

$post = Post::with(array('comments.users', 'from', 'tags.users', 'likes.users'))->find($id);  

然后我添加了

public function users() 
{ return $this->belongsTo('User', 'fromID')->select(array('id', 'first_name', 'last_name')); 
} 

到 cmets、tags 和 likes 模型。现在这个对象工作得很好。

但我的调试器显示如下

select `id`, `first_name`, `last_name` from `users` where `users`.`id` in ('1')

select `id`, `first_name`, `last_name` from `users` where `users`.`id` in ('4')

select `id`, `first_name`, `last_name` from `users` where `users`.`id` in ('2', '3')

select `id`, `first_name`, `last_name` from `users` where `users`.`id` in ('2', '3')

简而言之,它在我的用户表上运行 4 个查询。这不是多余的吗?不应该是对users表进行1次查询,而不是对原始post用户进行1次查询,对cmets用户进行1次查询,对tags用户进行1次查询,对like用户进行1次查询吗?

【问题讨论】:

    标签: orm laravel laravel-4 eloquent


    【解决方案1】:

    您似乎想使用嵌套关系。

    $post = Post::with('comments.from', 'from', 'tags.from', 'likes.from')->find($id);
    

    您还需要将“来自”关系编码到每个模型中。

    获取您的串联名称;您的用户模型中需要以下内容

    protected $appends = array('name');
    protected $hidden = array('first_name', 'last_name');  //this is optional
    
    public function getNameAttribute()
    {
        return $this->attributes['first_name'] . ' ' . $this->attributes['last_name'];
    }
    

    【讨论】:

    • 嗨,托尼,我添加了 $post = Post::with(array('cmets.users', 'from', 'tags', 'likes'))->find($id);仅使用 cmets 进行测试。然后我添加了 public function users() { return $this->belongsTo('User', 'fromID')->select(array('id', 'first_name', 'last_name')); } 到 cmets 模型。而且这个物体效果很好。但我的调试器显示以下 select id, first_name, last_name from users where users.id in ('1') select id, first_name, last_name from @ 987654332@ where users.id in ('4') 对 users 表进行 2 db 调用不是多余的吗?
    • 我不应该使用 cmets 模型获得以下 2 cmets:select id, first_name, last_name from users where users.id in ('1', '3') 所以效果很好。
    • @user1011713 如果您不介意,请使用此信息编辑您的原始帖子,使其更易于阅读。我不确定你在问什么。
    • @user1011713 鉴于嵌套关系的性质,我认为不可能减少这些查询。当在表(帖子)上执行 get() 以检索多个帖子及其关系时,急切加载的好处最为明显,而不是在执行 find() 时。
    【解决方案2】:

    这是一个很小的旧帖子,但你也可以这样做,

    public function from() 
        {
            return $this->belongsTo('User', 'fromID')
                        ->select(array('id',DB::raw("CONCAT(firstname,' ', lastname) as name")));
        }
    

    【讨论】:

      猜你喜欢
      • 2010-11-17
      • 1970-01-01
      • 2011-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多