laravel 4 关系 - 如何显示用户投票记录的前 5 名排名

标签 laravel laravel-4 eloquent relationship

我正在创建一个新闻源系统,你很容易猜到,这超出了我的技能。
请善待我,让我走上正轨,或者提供一些我可以继续做的事情。

我有几百个事件(模型名称是 Event1,表“事件”)
我还有一个数据透视表,用户可以在其中分配任何事件的重要性(值 0、1、2、3)

数据透视表user_attitudes(Model Userattitude)的相关列是id , item_type , item_id , importance , attitude , creator_id一个例子三记录是:

456 - 事件 - 678 - 2 - 4

457 - 事件 - 690 - 3 - 15

458 - 事件 - 690 - 1 - 4

459 - 参与者 - 45 - 1 - 4

简单英语:事件#690 的总聚合重要性为“4”,而事件#678 的总聚合重要性为“2”。
因此,在我的排名中,#690 事件应该被列为第一。

只是为了查看更大的图片:用户 #4 还将参与者 #45 评为重要性 = 1。

该表为许多模型提供服务 - 上面的例子包括两个 - 只是为了更好地展示我所拥有的东西。

我需要的:

  • 我希望打印前 5 个事件(以及后来的其他模型)的排名。我希望能够使用两种计算总分的方法:
  • 通过计算实际值 (0,1,2,3)
  • 通过将任何大于 0 的值计为 1 点。
  • 我想生成按此条件过滤事件的 View :
  • 至少有一个用户将重要性设置为“0”(我需要它将事件标记为不可信)
  • 个尚未评级的事件
  • 与上述相反 - 至少有一个用户评价的事件
  • 事件按对其赋予任何重要性的用户数量列出
  • 这很容易,但我仍然不知道如何实现。与上述 #2 相同的过滤器,但 与特定用户决策 相关:
  • 列出用户尚未评级的 5 或 10 个事件(随机或最新)
    也许这样的事情会是一个答案:

  • $q->where('creator_id', '=', Auth::user()->id);
    相关代码:
    由于我并没有真正掌握合并的关系,我可能无法展示提供帮助所需的一切 - 在评论中要求更多代码。

    楷模:

    Event1(表“事件”):
    public function importances()
    {
        return $this->morphMany('Userattitude', 'item');
    }
    
    public function user_importance($user)
    {
        return $this->morphMany('Userattitude', 'item')->where('creator_id', ($user ? $user->id : NULL))->first();
    }
    

    用户:(表 'users' - 标准用户表)
    public function importances()
    {
        return $this->hasMany('Userattitude', 'creator_id');
    }
    

    在模型 Userattitude (不同于User,表名'user_attitudes')
    public function events()
    {
        return $this->morphTo('item')->where('item_type', 'event');
    }
    
    
    
    public function event()
    
        {
            return $this->belongsTo ('Event1', 'item_id');
        }
    

    回复@lucas 的问题:

    问题 1。

    表名“项目”让我感到困惑,因为在我的项目中,“项目”是事件(模型 Event1)、参与者(模型实体)和其他对象。
    在我掌握你提供的知识之前,我们可以坚持我的名字吗?
    它还包含名为 态度 的列,用于将特定项目列入黑名单。
    例如,“实体”类型的项目(多个事件的可能参与者)可以由用户进行两轮投票:
    - 由用户设置的重要性(我们现在正在这样做,可用的值为0、1、2、3)
    - 通过 态度 用户朝向(可能的值 (-1, 0, 1)
    这样的解决方案允许我计算每个项目的业力。例如 -1 x 3 = -3(可能的最坏业力值),而 1 x 2 = 2(中等正业力)。

    因此,我无法使用 用户 方法进行查询。对我来说还是太困惑了,抱歉。我们偏离了我最初的心理形象。
    考虑这个查询:
    $events = Event1::has('users', '<', 1)->get();
    

    如果在 Event1 我声明
        public function users()
    {
        return $this->morphToMany('User', 'item', null, null, 'creator_id');
    }
    

    注意:user是标准的 users表,存放用户名、密码和邮箱

    我收到此错误:
    [2014-12-28 05:02:48] production.ERROR: FATAL DATABASE ERROR: 500 = SQLSTATE[42S02]: Base table or view not found: 1146 Table 'niepoz_niepozwalam.items' doesn't exist (SQL: select * from `Events` where (select count(*) from `users` inner join `items` on `users`.`id` = `items`.`creator_id` where `items`.`item_id` = `Events`.`id` and `items`.`item_type` = Event1) >= 1) [] []
    

    如果我将方法定义更改为
        public function users()
    {
        return $this->morphToMany('Userattitude', 'item', null, null, 'creator_id');
    }
    

    注意:Userattitude 是我存储用户判断的模型(表名是'user_attitudes')。该表包含“重要性”和“态度”列。

    我犯了同样的错误。

    如果我将方法更改为
        public function users()
    {
        return $this->morphToMany('User', 'Userattitudes', null, null, 'creator_id');
    }
    

    我明白了:

    [2014-12-28 05:08:28] production.ERROR: FATAL DATABASE ERROR: 500 = SQLSTATE[42S22]: Column not found: 1054 Unknown column 'user_attitudes.Userattitudes_id' in 'where clause' (SQL: select * from Events where (select count(*) from users inner join user_attitudes on users .id = user_attitudes .creator_id where user_attitudes .Userattitudes_id = Events .id and user_attitudes) [1] = Event >

    可能的解决方案:
    名为“items”的“user_attitudes”表别名。
    我可以创建一个具有所需名称的 View 。
    我做到了,但现在查询没有结果。

    问题 2

    我应该将creator_id 重命名为user_id - 还是保留两列并在其中保留重复的信息? creator_id 遵循约定,我用它来创建记录......如何解决这个难题?

    问题 3。

    据我了解,如果我想获得与用户相关的前 5 项事件列表,
    我需要在代码中添加另一行,将搜索范围缩小到由特定登录用户创建的记录:
    Auth::user()->id)
    

    代码如下所示:
    都具有重要性 0
    $events = Event1::whereHas('users', function($q){
    $q->where('importance', 0);
    $q->where('creator_id', '=', Auth::user()->id);
    

    })->get();

    对?

    问题 5:

    好的,我现在可以输出这样的查询:
    $rank_entities = Entity::leftJoin('user_attitudes', function($q){
                    $q->on('entity_id', '=', 'entities.id');
                    $q->where('item_type', '=', 'entity');
                })
                ->selectRaw('entities.*, SUM(user_attitudes.importance) AS importance')
                ->groupBy('entities.id')
                ->orderBy('importance', 'desc')
                ->take(6)
                ->get(); 
    

    在 foreach 循环中,我可以使用以下代码显示总重要性计数:
    {{$e->importance or '-'}}
    

    但是我如何显示替代查询的计数:来自另一列的值的总和,命名态度,可以在这个 SEPARATE 查询中计算:

    换句话说,在我的 @foreach 循环中,我需要同时显示 $e->importance 和计算出的 SUM(user_attitudes.attitude) AS karma ,现在可以通过以下查询接收:
    $rank_entities = Entity::leftJoin('userattitudes', function($q){
                    $q->on('entity_id', '=', 'entities.id');
                    $q->where('item_type', '=', 'entity');
                })
                ->selectRaw('entities.*, SUM(userattitudes.karma) AS karma')
                ->groupBy('entities.id')
                ->orderBy('karma', 'desc')
                ->take(5)
                ->get(); 
    

    我的解决方案是在“实体”表中创建一些额外的列:
    - karma_negative
    - karma_positive
    每次有人投票时存储/更新投票总数。

    最佳答案

    首先,让我们谈谈设置。我不完全确定你的工作方式和是否有效,但我在我的测试实例上创建了它并且它有效,所以我建议你相应地改变你的:

    数据库

    事件

    这是一个简单的(你可能已经有了这样的

  • id(主键)
  • 名称(或类似名称)

  • 用户

    我不确定在你的例子中是否是 Userattitude但我不这么认为...
  • id(主键)
  • 电子邮件 (?)

  • 项目

    这是重要的一点。数据透视表。名称可以不同,但​​为了简单起见并遵循约定,它应该是多态关系的复数(在您的情况下 item => items )
  • id(实际上甚至没有必要,但我把它留在了那里)
  • item_type
  • item_id
  • 重要性
  • creator_id(考虑将其更改为 user_id 。这将简化关系声明)


  • 楷模

    我认为您必须阅读 docs再次。你宣布了​​几个奇怪的关系。这是我如何做到的:

    事件1

    默认情况下,Laravel 使用类名( get_class($object) )作为 ..._type 的值数据库中的列。要更改您需要定义 $morphClass在你的模型中。
    class Event1 extends Eloquent {
    
        protected $table = 'events';
        protected $morphClass = 'event';
    
        public function users()
        {
            return $this->morphToMany('User', 'item', null, null, 'creator_id');
        }
    }
    

    用户
    class User extends Eloquent implements UserInterface, RemindableInterface {
    
        // ... default laravel stuff ...
    
        public function events(){
            return $this->morphedByMany('Event1', 'item', null, null, 'creator_id');
        }
    }
    

    查询

    好了,现在我们可以开始了。第一个附加信息。我尽可能使用 Eloquent 关系。在所有查询中 join()使用关系会变慢,因为某些事情(例如计数或计算最大值)必须在查询后在 PHP 中完成。 MySQL 在这些方面做得很好(也是性能方面的)。

    总值(value)前 5 名
    $events = Event1::leftJoin('items', function($q){
                        $q->on('item_id', '=', 'events.id');
                        $q->where('item_type', '=', 'event');
                    })
                    ->selectRaw('events.*, SUM(items.importance) AS importance')
                    ->groupBy('events.id')
                    ->orderBy('importance', 'desc')
                    ->take(5)
                    ->get();
    

    票数超过 0 的前 5 名
    $events = Event1::leftJoin('items', function($q){
                        $q->on('item_id', '=', 'events.id');
                        $q->where('item_type', '=', 'event');
                        $q->where('importance', '>', 0);
                    })
                    ->selectRaw('events.*, COUNT(items.id) AS importance')
                    ->groupBy('events.id')
                    ->orderBy('importance', 'desc')
                    ->take(5)
                    ->get();
    

    都具有重要性 0
    $events = Event1::whereHas('users', function($q){
        $q->where('importance', 0);
    })->get();
    

    所有没有任何投票
    $events = Event1::has('users', '<', 1)->get();
    

    全部获得 1+ 票
    $events = Event1::has('users')->get();
    

    全部按票数排序
    $events = Event1::leftJoin('items', function($q){
                        $q->on('item_id', '=', 'events.id');
                        $q->where('item_type', '=', 'event');
                    })
                    ->selectRaw('events.*, COUNT(items.id) AS count')
                    ->groupBy('events.id')
                    ->orderBy('count', 'desc')
                    ->get();
    

    最新 5 无票

    如果您使用 Eloquents 时间戳 created_at :
    $events = Event1::has('users', '<', 1)->latest()->take(5)->get();
    

    如果您不是(按最大 ID 排序):
    $events = Event1::has('users', '<', 1)->latest('id')->take(5)->get();
    

    无票随机5
    $events = Event1::has('users', '<', 1)->orderByRaw('RAND()')->take(5)->get();
    

    我没有故意对查询添加任何解释。如果您想了解更多有关特定内容或需要帮助的信息,请发表评论

    关于laravel 4 关系 - 如何显示用户投票记录的前 5 名排名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27653323/

    相关文章:

    many-to-many - 多选编辑表单选定值

    php - laravel 获取日期时间错误

    php - Laravel 通过遍历数组进行路由

    mysql - 无法在现有表上添加外键

    laravel - Laravel中的高级whereNotNull语句

    php - 获取关注者的帖子 laravel

    mysql - Laravel LastInsertId 与 UUID PK

    php - Laravel 5.2 更改数据库列名引用

    php - Laravel Eloquent 问题获取数据库数据

    php - Laravel 中的 Id 命名约定