laravel 4 relations - 如何显示用户投票的前5名排名

时间:2014-12-26 05:56:50

标签: laravel laravel-4 eloquent relationship

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

我有几百个活动(型号名称为Event1,table' events') 我还有一个数据透视表,用户可以在其中分配任何事件的重要性(值0,1,2,3)

数据透视表user_attitudes(Model Userattitude)的相关列是 iditem_typeitem_idimportanceattitudecreator_id 示例三记录是:

456 - 事件 - 678 - 2 - 4

457 - 事件 - 690 - 3 - 15

458 - 事件 - 690 - 1 - 4

459 - 参与者 - 45 - 1 - 4

普通英语:事件#690的总重要性为#4;' 4'事件#678为' 2'。 因此,在我的排名中,事件#690应该列为第一。

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

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

我需要什么:

  1. 我希望打印前5个事件(以及后来的其他模型)的排名。我希望能够使用两种计算总分的方法:

    • 通过计算实际值(0,1,2,3)
    • 将任何高于0的值计算为1点。
  2. 我想生成按此条件过滤事件的视图:

    • 至少有一位用户将重要性设置为' 0' 0 (我需要它将事件标记为不值得信任)
    • 尚未评级的活动
    • 上述事件的反向 - 由至少一个用户评定的事件
    • 按指定任何重要性的用户数列出的事件
  3. 这很容易,但我仍然不知道如何实现它。与上述#2相同的过滤器,但与特定用户决策相关

    • 列出尚未被用户评分的5或10个事件(随机或最新) 也许这样的事情就是答案:

    $ q->其中(' creator_id',' =',Auth :: user() - > id);

  4. 相关代码: 由于我没有真正掌握合并的关系,我可能无法展示提供帮助所需的一切 - 在评论中要求更多代码。

    型号:

    活动1(表'活动'):

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

    用户:(表'用户' - 标准用户表)

    public function importances()
    {
        return $this->hasMany('Userattitude', 'creator_id');
    }
    

    在模型 Userattitude (与用户,表格名称' user_attitudes'不同)

    public function events()
    {
        return $this->morphTo('item')->where('item_type', 'event');
    }
    
    
    
    public function event()
    
        {
            return $this->belongsTo ('Event1', 'item_id');
        }
    

    回答@lucas的问题回答:

    问题1。

    表名'项目'让我感到困惑,因为在我的项目' items'是事件(模型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');
    }
    

    注意:用户是标准的用户表,其中存储了用户名,密码和电子邮件

    我收到此错误:

    [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是模型(表名是&#39; user_attitudes&#39;),其中我存储用户判断。此表包含列&#39; important&#39;和#39;态度&#39;。

    我得到了同样的错误。

    如果我将方法更改为

        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]:找不到列:1054未知列&#39; user_attitudes.Userattitudes_id&#39;在&#39; where子句&#39; (SQL:从Events中选择*其中(从users user_attitudes选择users内部加入id的计数(*)。user_attitudes = creator_iduser_attitudes其中Userattitudes_idEvents = iduser_attitudesUserattitudes_typeAuth::user()->id) = Event1)&gt; = 1)[ ] []

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

    问题2

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

    问题3。

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

    $events = Event1::whereHas('users', function($q){
    $q->where('importance', 0);
    $q->where('creator_id', '=', Auth::user()->id);
    

    代码如下所示: 所有重要性0

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

    }) - &GT;得到();

    正确?

    问题5:

    好的,我现在可以输出这样的查询:

    {{$e->importance or '-'}}
    

    并且在foreach循环中,我可以使用以下代码显示总重要性计数:

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

    但是如何显示替代查询的计数:来自另一列的值的SUM,名为attitude,可以在此SEPARATE查询中计算:

    换句话说,在我的@foreach循环中,我需要显示$ e-&gt;重要性和计算出的 SUM(user_attitudes.attitude)AS业力,现在可以用此接收查询:

    {{1}}

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

2 个答案:

答案 0 :(得分:1)

首先,我们来谈谈设置。我不完全确定如何以及如果你的工作,但我在我的测试实例上创建它并且它有效,所以我建议你相应地更改你的:

数据库

事件

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

  • 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');
    }
}


查询

好了,现在我们可以开始了。第一个附加信息。我尽可能使用了雄辩的关系。在所有查询中,join()使用关系会更慢,因为在查询之后必须在PHP中完成某些事情(如计算或计算最大值)。而MySQL在这些方面做得相当不错(也是表现明智的)。

总价值前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();

排名前5位的投票数超过0

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

如果你不是(按最大身份排序):

$events = Event1::has('users', '<', 1)->latest('id')->take(5)->get();

随机5无票

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

我没有故意在查询中添加任何解释。如果您想了解更多有关特定事项或需要帮助的信息,请撰写评论

答案 1 :(得分:0)

问题4:已解决!(归功于@lukasgeiter)

如果您希望显示项目的排名并将结果限制为数据透视表中定义的特定标记,则这是解决方案:

$ events = Event1(表名=&#39;事件&#39;)

例如,标签将 war :在表格中定义 eventtags

事件性质定义为

id =&#39; 1&#39;是名字=&#39;战争&#39; id =&#39; 2&#39;是姓名=&#39;冲突&#39; 数据透视表,分配多个标记 event_eventtags 他们被定义为id =&#39; 4&#39;

event_eventtags 的示例记录:

id - event_id - eventtag_id

1 - 45 - 1

2 - 45 - 2

普通英语:Event1#45被标记为战争(#1)和冲突(#2)

现在,为了打印10个战争的列表,您应该以这种方式定义查询:

$events= Entity::join('event_eventtags', function($q){
         $q->on('entity_id', '=', 'entities.id');
         $q->where('entitycapacitytypes_id', '=', 1);
     })->leftJoin('user_attitudes', function($q){
         $q->on('item_id', '=', 'entities.id');
         $q->where('item_type', '=', 'entity');
    })
    ->selectRaw('entities.*, SUM(user_attitudes.importance) AS importance')
    ->groupBy('entities.id')
    ->orderBy('importance', 'desc')
    ->take(10)
    ->get();

user_attitudes是原始问题中描述的投票系统的一部分。您可以删除它并通过其他方法对事件进行排序。