douchuo1963 2018-02-27 01:54
浏览 59
已采纳

HasMany对象还是Eloquent:哪个更好?

I have the following controller for blog

public function show($slug)
{
    $post = Blog::where('slugs', '=', $slug)->first();

    $vars['pageTitle'] = Config::get('site.pageTitle') . $post['title'];

    // The breadcrumbs... needs to be repopulated every page
    $vars['breadCrumbs'] = [[
        'url'   => action('SimpleController@index'),
        'title' => 'CovertDEV'
    ],[
        'url'   => action('BlogController@index'),
        'title' => 'Blog'
    ],[
        'url'   => route('blog_post', ['slug' => $slug]),
        'title' => $post['title']
    ]];

    $vars['blog'] = $post;

    // The following line is what the question is about
    $vars['comments'] = $post->Blog_comments->groupBy('comment_id');

    return view('blog', $vars);
}

My model for blogs originally looked like

namespace App;

use Illuminate\Database\Eloquent\Model;

class Blog extends Model
{
    //

    public function tags()
    {
        return $this->belongsToMany('App\Tag');
    }

    public function blog_comments()
    {
        return $this->hasMany('App\Blog_comment');
    }

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

and for blog_comments

namespace App;

use Illuminate\Database\Eloquent\Model;

class Blog_comment extends Model
{
    //

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

    public function blogs()
    {
        return $this->belongsTo('App\Blog');
    }

}

I'm retrieving the comments for the post and displaying it on the page. Everything is working perfectly... but then I tried to use my relationship instead... (that changes that line to...)

$vars['comments'] = $post->blog_comments()->get()->groupBy('comment_id');

And that works just as well. My post isn't big, just a simple 'Lorem Ipsum' test text and 7 comments to test the feature so I don't see any difference in load times between the two methods.

Or are they both the same way? The previous way looks better, but I'm not sure if I'm implementing the ORM as intended, if not then which way is better?

But I'm new to Laravel (this is my first framework) so I don't know... which way is better/faster/more efficient? Maybe there's an even better/more efficient way to accomplish this that I don't know of yet.

Sorry if this seems obvious. I want to get this out of the way before continuing on the project... don't want to be redoing everything after finding out a better way to tie pieces of information together.

Thanks in advance!

My Database Dump Is

CREATE TABLE `blog_comments` (
  `id` int(10) UNSIGNED NOT NULL,
  `user_id` int(10) UNSIGNED NOT NULL,
  `blog_id` int(10) UNSIGNED NOT NULL,
  `comment_id` int(11) NOT NULL DEFAULT '0',
  `comment` text COLLATE utf8mb4_unicode_ci NOT NULL,
  `likes` int(11) NOT NULL DEFAULT '0',
  `deleted_at` timestamp NULL DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `blog_comments`
--

INSERT INTO `blog_comments` (`id`, `user_id`, `blog_id`, `comment_id`, `comment`, `likes`, `deleted_at`, `created_at`, `updated_at`) VALUES
(1, 1, 2, 0, 'Interesting post. Very well structured and good points throughout! One question though, Enim blandit volutpat maecenas volutpat blandit aliquam etiam erat velit?', 0, NULL, '2018-02-24 20:31:45', '2018-02-24 20:31:45'),
(2, 2, 2, 1, 'Thank you, very interesting question. Unique point of view. Semper viverra nam libero justo. Sit amet commodo nulla facilisi. Blandit massa enim nec dui nunc. Eget velit aliquet sagittis id consectetur purus ut faucibus.', 0, NULL, '2018-02-25 02:26:32', '2018-02-25 02:26:32'),
(3, 1, 2, 1, 'Indeed! I can now finally lorem ipsum by myself all the way commodo nulla facilisi!', 0, NULL, '2018-02-25 04:36:18', '2018-02-25 04:36:18'),
(4, 2, 2, 0, 'Weird, I thought I had more information posted. Must have being moderated out of existence then.', 0, NULL, '2018-02-25 09:18:58', '2018-02-25 09:18:58'),
(5, 1, 2, 4, 'Sorry about that, you had quite a few needless stuff in there. Had to tweak your post a bit. Otherwise, everything is lorem ipsum!', 0, NULL, '2018-02-25 12:53:18', '2018-02-25 12:53:18'),
(6, 2, 2, 3, 'Glad that it works for you!', 0, NULL, '2018-02-26 05:35:46', '2018-02-26 05:35:46'),
(7, 1, 2, 6, 'Thank you, feels good!', 0, NULL, '2018-02-25 07:08:33', '2018-02-25 07:08:33');

--
-- Indexes for dumped tables
--

--
-- Indexes for table `blog_comments`
--
ALTER TABLE `blog_comments`
  ADD PRIMARY KEY (`id`),
  ADD KEY `blog_comments_user_id_index` (`user_id`),
  ADD KEY `blog_comments_blog_id_index` (`blog_id`);

I need the outcome array to look the following:

Array
(
    [comment_id] => Array
        (
            [0] => Array
                (
                    [id] => 1
                    [user_id] => 1
                    [blog_id] => 2
                    [comment_id] => 0
                    [comment] => Interesting post. Very well structured and good points throughout! One question though, Enim blandit volutpat maecenas volutpat blandit aliquam etiam erat velit?
                    [likes] => 0
                    [deleted_at] => 
                    [created_at] => 2018-02-24 14:31:45
                    [updated_at] => 2018-02-24 14:31:45
                )

            [1] => Array
                (
                    [id] => 4
                    [user_id] => 2
                    [blog_id] => 2
                    [comment_id] => 0
                    [comment] => Weird, I thought I had more information posted. Must have being moderated out of existence then.
                    [likes] => 0
                    [deleted_at] => 
                    [created_at] => 2018-02-25 03:18:58
                    [updated_at] => 2018-02-25 03:18:58
                )
        )
)

comment_id is the same thing as parent_id... I originally named it comment_id now I don't feel like changing it.

Any comment with comment_id of 0 are parent comments, any comment with comment_if of any number, they are a child of that comment.

Might have caused some confusion. Sorry about that.

I just want to know what is the most efficient way of generating this kind of an array. I've went through 3 or 4 methods and now I'm wondering if I missed something.

  • 写回答

1条回答 默认 最新

  • douqi3913 2018-02-27 02:13
    关注

    I think this is a not so clean but I believe a more efficient solution than depending on Collection's groupBy

    $post = Blog::with(['blog_comments' => function($query) {
        $query->groupBy('comment_id');
    }])->where('slugs', $slug)->first();
    
    $vars['comments'] = $post->blog_comments;
    

    Although if you do not expect thousands of comments, your current implementation is okay.

    Using this is more efficient because you're giving the groupBy workload to the database manager rather than to php itself (when using Collection's groupBy).

    You may also declare another relationship that will suit your grouping needs.

    // Blog.php
    public function groupedBlogComments()
    {
        return $this->hasMany(BlogComment::class)
                    ->groupBy('comment_id');
    
        // I think this can be `return $this->blogComments()
        //                                  ->groupBy('comment_id');
    }
    
    // you can still have this, if ever you do not want grouped comments
    public function blogComments()
    {
        return $this->hasMany(BlogComment::class);
    }
    
    // Controller
    $vars['comments'] = $post->groupedBlogComments;
    

    Or even better, define a scope in your BlogComment model, and use that anywhere.

    // BlogComment.php
    public function scopeGroupByCommentId($query)
    {
        return $query->groupBy('comment_id');
    }
    
    // You can eager load your relationships and use the scope.
    $post = Blog::with(['blog_comments' => function($query) {
        $query->groupByCommentId();
    }])->where('slugs', $slug)->first();
    
    $vars['comments'] = $post->blog_comments;
    

    If there are any mistakes, please don't hesitate to correct me.

    I hope I got your point.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误