我有两个表 magazines,其中一个字段是 product_code,另一个表是 issues。他们有 belongsToMany 关系。
杂志型号:
public function issues()
{
return $this->hasMany('App\Issue');
}
问题模型:
public function magazine()
{
return $this->belongsTo('App\Magazine');
}
目前,我有一个查询,可以获取按杂志 ID 分组并按上一期日期排序的期刊集合。
$issues = Issue::orderBy('date', 'desc')->get()->groupBy('magazine_id');
我的查询结果是这样的:
Collection {#431 ▼
#items: array:23 [▼
103 => Collection {#206 ▼
#items: array:52 [▶]
}
106 => Collection {#216 ▶}
124 => Collection {#452 ▶}
112 => Collection {#451 ▶}
115 => Collection {#450 ▶}
123 => Collection {#449 ▶}
107 => Collection {#448 ▶}
113 => Collection {#447 ▶}
117 => Collection {#446 ▶}
109 => Collection {#445 ▶}
110 => Collection {#444 ▶}
121 => Collection {#443 ▶}
120 => Collection {#442 ▶}
114 => Collection {#441 ▶}
116 => Collection {#440 ▶}
118 => Collection {#439 ▶}
126 => Collection {#438 ▶}
125 => Collection {#437 ▶}
119 => Collection {#436 ▶}
122 => Collection {#435 ▶}
105 => Collection {#434 ▶}
111 => Collection {#433 ▶}
104 => Collection {#432 ▶}
]
}
所以,因为我有 24 本杂志,数组中有 24 个 issues 集合,issues 的每个 collection 属于一个杂志。集合按每个集合的最新问题的日期排序,每个集合中的问题也按日期排序。因此,数组中的第一个集合将是 issues 表中最新一期的集合,第二个集合将是同一表中第二个最新一期的集合,依此类推。
因为我将获得一组用户订阅,其中包含 产品代码,如下所示:
$productCodes = ['aa1', 'bb2', 'cc3'];
我需要扩展此查询并根据我将获得的 $productCodes 数组进一步对集合进行排序。我需要检查表 magazines 中的 productCodes 数组中的代码,其中我有 product_code 字段。按 magazine 分组的问题集合,然后应该排序,以便第一个集合是它们所属的 magazine 具有相同 product_code 作为数组 productCodes 中的代码,其中,第一个将是其集合按日期具有最新问题的代码。然后其余的集合应该按日期排序。如何进行此类查询?
更新
我已经尝试在答案中使用@Paul Spiegel 建议的代码,现在我得到了一系列集合,其中包含杂志期的集合。每个杂志集合中的问题按日期排序,与 $productCodes 数组中具有相同 product_code 的杂志集合位于数组的开头,但数组杂志合集的数量仍未按每本杂志合集的最新一期日期排序。
最佳答案
首先:除了使用 Collection::groupBy(),你还可以使用关系:
$magazines = Magazine::with(['issues' => function($query) {
$query->orderBy('date', 'desc');
}]);
这将为您提供一系列杂志,其中包括数组中的相关问题。 issues 数组按 date desc 排序。
现在您可以使用具有不同条件的两个查询拆分结果:
$baseQuery = Magazine::with(['issues' => function($query) {
$query->orderBy('date', 'desc');
}]);
$query1 = clone $baseQuery;
$query2 = clone $baseQuery;
$query1->whereIn('product_code', $productCodes);
$query2->whereNotIn('product_code', $productCodes);
$query1 将从数组中返回所有带有 product_code 的杂志。 $query2 将返回所有其他杂志。
您现在有两种方法可以合并这两个结果:
1) 使用Eloquent::unionAll()
$unionQuery = $query1->unionAll($query2);
$magazines = $unionQuery->get();
2) 使用Collection::merge()
$magazines1 = $query1->get();
$magazines2 = $query2->get();
$magazines = $magazines1->merge($magazines2);
在这两种情况下,您将获得相同的结果:杂志合集。 $productCodes 数组中带有 product_code 的杂志首先排序。每个 Magazine 对象都包含一个数组 issues 以及相关的 Issue 对象。
如果你想摆脱 Magazine 对象并且真的需要结果看起来像你的问题,你仍然可以这样做:
$issues = $magazines->keyBy('id')->pluck('issue');
但可能没有必要。
更新
如果您确实需要按最新的Issue 对Magazine 集合的两个部分进行排序。我看不到不使用JOIN 或排序的任何方式在带有闭包的 PHP 中。使用连接对杂志进行排序也需要聚合。所以我会切换回您原来的查询,用连接扩展它并将它分成两部分,如上所示:
$baseQuery = Issue::join('magazines', 'magazines.id', '=', 'issues.magazine_id');
$baseQuery->orderBy('issues.date', 'desc');
$baseQuery->select('issues.*');
$query1 = clone $baseQuery;
$query2 = clone $baseQuery;
$query1->whereIn('magazines.product_code', $productCodes);
$query2->whereNotIn('magazines.product_code', $productCodes);
然后
$issues1 = $query1->get()->groupBy('magazine_id');
$issues2 = $query2->get()->groupBy('magazine_id');
$issues = $issues1->union($issues2);
或
$issues = $query1->unionAll($query2)->get()->groupBy('optionGroupId');
关于php - Laravel - 通过关系对象的属性对集合数组进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40418308/
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代
我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby数组,我们在StackOverflow上找到一
尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub
我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]
我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我正在使用puppet为ruby程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss