- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
您好,我遇到了一些 Laravel Eloquent 关系的实际问题,我只能猜测是由区分大小写的关系引起的,我希望这里有人可以提供帮助!
以下是我遇到问题的模型:
class DeliveryManifestLines extends Eloquent
{
protected $table = 'manifests';
public function sapDelivery()
{
return $this->hasOne('Delivery', 'DocNum', 'sap_delivery');
}
}
class Delivery extends Eloquent
{
protected $connection = 'sap';
protected $table = 'ODLN';
protected $primaryKey = 'DocNum';
public function deliveryManifest() {
return $this->belongsTo('DeliveryManifest', 'DocNum', 'sap_delivery');
}
public function address()
{
return $this->hasOne('Address', 'Address', 'ShipToCode')->where('CardCode', $this->CardCode)->where('AdresType', 'S');
}
public function geolocation()
{
return $this->hasOne('GeoLocation', 'Address', 'ShipToCode')->where('CardCode', $this->CardCode)->where('AdresType', 'S')->where('Lat', '>', 0)->where('Lng', '>', 0);
}
}
class Address extends Eloquent
{
protected $connection = 'sap';
protected $table = 'CRD1';
protected $primaryKey = 'Address';
public function delivery() {
return $this->belongsTo('Delivery', 'Address', 'ShipToCode');
}
}
这是我的 Controller 中的代码,它应该从数据库中获取上述一些模型。
$deliveries = DeliveryManifestLines::with('sapDelivery')->where('manifest_date', $date))->get();
foreach ($deliveries as $delivery) {
$delivery->sapDelivery->load('address');
}
我正在使用“->load('address)
”行,因为无论我尝试什么,我都无法获得与“sapDelivery.address
”一起工作的急切加载>"
在 99% 的情况下,地址从数据库成功加载,但我遇到过一个问题,我认为这是由区分大小写引起的。
使用 Laravel DebugBar 我可以看到我的应用程序正在执行以下查询:
SELECT * FROM [CRD1] WHERE [CardCode] = 'P437' AND [AdresType] = 'S' AND [CRD1].[Address] IN ('The Pizza Factory (topping)')
当我在这种情况下转储 $delivery->sapDelivery
的内容时,地址关系为 NULL,但是,当我将 SQL 语句粘贴到我的数据库控制台并手动执行时,我得到了预期的结果行返回。
我能看到的这个地址与其他数千个正在工作的地址之间的唯一区别是地址字段之间存在大小写差异:
在 CRD1 表中,受影响/预期行的地址字段是“The Pizza Factory (Topping)”,但 Eloquent 关系是使用 AND [CRD1].[Address] IN ('The Pizza Factory (topping)')尝试找到它 我知道默认情况下 SQL 是不区分大小写的,但我想不出这一行与其他行的行为不同的任何其他原因。
是否有人对可能导致此问题的原因有任何其他想法并提出任何可能的解决方案或确认我的区分大小写理论是罪魁祸首。
非常感谢!
最佳答案
因此,在过去几个月很少考虑这个问题之后,我今天重新审视了这个问题,并在 laravel.io 上找到了一些非常有用的代码。由遇到与我相同的问题的人提出。
我在 MattApril 的解决方案的基础上提供了一种我能想到的最简单的方法来提供一种在 laravel 中提供不区分大小写的关系的方法。
要实现这一点,您需要添加一些新类,这些类利用 strtolower() 函数创建小写键,这允许关系中使用的 isset() 函数找到不同大小写但匹配的键:
ModelCI.php (app\Models\Eloquent\ModelCI.php)
<?php
namespace App\Models\Eloquent;
use App\Models\Eloquent\Relations\BelongsToCI;
use App\Models\Eloquent\Relations\HasManyCI;
use App\Models\Eloquent\Relations\HasOneCI;
use Illuminate\Database\Eloquent\Model;
abstract class ModelCI extends Model
{
/**
* Define a one-to-many relationship.
*
* @param string $related
* @param string $foreignKey
* @param string $localKey
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function hasManyCI($related, $foreignKey = null, $localKey = null)
{
$foreignKey = $foreignKey ?: $this->getForeignKey();
$instance = new $related();
$localKey = $localKey ?: $this->getKeyName();
return new HasManyCI($instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey);
}
/**
* Define a one-to-one relationship.
*
* @param string $related
* @param string $foreignKey
* @param string $localKey
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function hasOneCI($related, $foreignKey = null, $localKey = null)
{
$foreignKey = $foreignKey ?: $this->getForeignKey();
$instance = new $related;
$localKey = $localKey ?: $this->getKeyName();
return new HasOneCI($instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey);
}
/**
* Define an inverse one-to-one or many relationship.
*
* @param string $related
* @param string $foreignKey
* @param string $otherKey
* @param string $relation
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function belongsToCI($related, $foreignKey = null, $otherKey = null, $relation = null)
{
// If no relation name was given, we will use this debug backtrace to extract
// the calling method's name and use that as the relationship name as most
// of the time this will be what we desire to use for the relationships.
if (is_null($relation))
{
list(, $caller) = debug_backtrace(false, 2);
$relation = $caller['function'];
}
// If no foreign key was supplied, we can use a backtrace to guess the proper
// foreign key name by using the name of the relationship function, which
// when combined with an "_id" should conventionally match the columns.
if (is_null($foreignKey))
{
$foreignKey = snake_case($relation).'_id';
}
$instance = new $related;
// Once we have the foreign key names, we'll just create a new Eloquent query
// for the related models and returns the relationship instance which will
// actually be responsible for retrieving and hydrating every relations.
$query = $instance->newQuery();
$otherKey = $otherKey ?: $instance->getKeyName();
return new BelongsToCI($query, $this, $foreignKey, $otherKey, $relation);
}
}
BelongsToCI.php (app\Models\Eloquent\Relations\BelongsToCI.php)
<?php namespace App\Models\Eloquent\Relations;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Query\Expression;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class BelongsToCI extends BelongsTo {
/**
* Match the eagerly loaded results to their parents.
*
* @param array $models
* @param \Illuminate\Database\Eloquent\Collection $results
* @param string $relation
* @return array
*/
public function match(array $models, Collection $results, $relation)
{
$foreign = $this->foreignKey;
$other = $this->otherKey;
// First we will get to build a dictionary of the child models by their primary
// key of the relationship, then we can easily match the children back onto
// the parents using that dictionary and the primary key of the children.
$dictionary = array();
foreach ($results as $result)
{
$dictionary[strtolower($result->getAttribute($other))] = $result;
}
// Once we have the dictionary constructed, we can loop through all the parents
// and match back onto their children using these keys of the dictionary and
// the primary key of the children to map them onto the correct instances.
foreach ($models as $model)
{
if (isset($dictionary[strtolower($model->$foreign)]))
{
$model->setRelation($relation, $dictionary[strtolower($model->$foreign)]);
}
}
return $models;
}
}
HasManyCI.php (app\Models\Eloquent\Relations\HasManyCI.php)
<?php namespace App\Models\Eloquent\Relations;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Relations\HasMany;
class HasManyCI extends HasMany {
/**
* Build model dictionary keyed by the relation's foreign key.
*
* @param \Illuminate\Database\Eloquent\Collection $results
* @return array
*/
protected function buildDictionary(Collection $results)
{
$dictionary = array();
$foreign = $this->getPlainForeignKey();
// First we will create a dictionary of models keyed by the foreign key of the
// relationship as this will allow us to quickly access all of the related
// models without having to do nested looping which will be quite slow.
foreach ($results as $result)
{
$dictionary[strtolower($result->{$foreign})][] = $result;
}
return $dictionary;
}
/**
* Match the eagerly loaded results to their many parents.
*
* @param array $models
* @param \Illuminate\Database\Eloquent\Collection $results
* @param string $relation
* @param string $type
* @return array
*/
protected function matchOneOrMany(array $models, Collection $results, $relation, $type)
{
$dictionary = $this->buildDictionary($results);
// Once we have the dictionary we can simply spin through the parent models to
// link them up with their children using the keyed dictionary to make the
// matching very convenient and easy work. Then we'll just return them.
foreach ($models as $model)
{
$key = strtolower( $model->getAttribute($this->localKey) );
if (isset($dictionary[$key]))
{
$value = $this->getRelationValue($dictionary, $key, $type);
$model->setRelation($relation, $value);
}
}
return $models;
}
}
HasOneCI.php (app\Models\Eloquent\Relations\HasOneCI.php)
<?php namespace App\Models\Eloquent\Relations;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Relations\HasOne;
class HasOneCI extends HasOne {
/**
* Match the eagerly loaded results to their many parents.
*
* @param array $models
* @param \Illuminate\Database\Eloquent\Collection $results
* @param string $relation
* @param string $type
* @return array
*/
protected function matchOneOrMany(array $models, Collection $results, $relation, $type)
{
$dictionary = $this->buildDictionary($results);
// Once we have the dictionary we can simply spin through the parent models to
// link them up with their children using the keyed dictionary to make the
// matching very convenient and easy work. Then we'll just return them.
foreach ($models as $model)
{
$key = strtolower($model->getAttribute($this->localKey));
if (isset($dictionary[$key]))
{
$value = $this->getRelationValue($dictionary, $key, $type);
$model->setRelation($relation, $value);
}
}
return $models;
}
/**
* Build model dictionary keyed by the relation's foreign key.
*
* @param \Illuminate\Database\Eloquent\Collection $results
* @return array
*/
protected function buildDictionary(Collection $results)
{
$dictionary = array();
$foreign = strtolower($this->getPlainForeignKey());
// First we will create a dictionary of models keyed by the foreign key of the
// relationship as this will allow us to quickly access all of the related
// models without having to do nested looping which will be quite slow.
foreach ($results as $result)
{
$dictionary[$result->{$foreign}][] = $result;
}
return $dictionary;
}
}
要使用新类,您必须这样定义关系:
$this->belongsToCI('Model');
或
$this->hasManyCI('Model');
或
$this->hasOneCI('Model');
关于php - Laravel Eloquent 区分大小写的关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35288365/
不确定是否可能,但只是想知道 CSS 中是否有一种方法来区分两种浏览器,即 IE6 和 IE8,因为我有一个我需要应用的样式,但 IE6 和 IE8 的值需要不同,即 ul.sf-menu li li
我正在为 C 库编写 C++ 抽象。 C 库有几个用于标识远程资源的 ID 的类型定义: typedef int color_id; typedef int smell_id; typedef int
有谁知道当以编程方式遍历 Word 文档时,您可以判断一个段落是否构成目录的一部分(或者实际上,构成字段一部分的任何其他内容)。 我提出这个问题的原因是我有一个 VB 程序,它应该从文档中提取前几段实
假设我的数据集包含三列:id(标识)、case(字符)和 value(数字)。这是我的数据集: tdata <- data.frame(id=c(1,1,1,1,2,2,2,2,3,3,3,3,4,4
我在解释 gcc (4.8.2) 警告和错误时遇到问题。更准确地说,很难分辨一个问题在哪里结束,另一个问题从哪里开始。我只能通过控制台访问构建机器,因此不能选择使用 IDE。 我真的需要能够快速区分个
我想创建一个泛型类型,它只从类定义中选择修饰的方法。 function test(ctor: any, methodName: any) {} class A { @test publ
是否有规范的 base-R 方法来确定函数参数是否是对象名称而不是文字/表达式? 虽然通常不鼓励使用 NSE,但偶尔会有人有一个好主意并想使用它。 data.frame 是我认为“方便”的最简单用例:
我已经实现了 didSelectRowAtIndexPath 和accessoryButtonTappedForRowWithIndexPath 似乎永远不会触发。但是,didSelectRowAtI
我需要确定数据框中的哪些列是小数,哪些是字符串。 使用 df.dtypes 为两种列类型提供“对象”: import pandas as pd import decimal data = {'dec1
有没有办法在 Vim 中区分隐藏缓冲区和事件缓冲区? 我需要确定窗口中的缓冲区是否处于事件状态,以便可以切换它。 尝试了 bufloaded、bufexists 和 buflisted,但它们对于事件
在 JavaScript 中区分事件的最佳方法是什么。 实际上有两点我感兴趣。第一点是事件中是否有类似 id 的东西(这对于调试目的非常有用)。另一点是有更好的方法来区分 mousedown 和 mo
我有一个 php 页面,里面有多个表单。 "> "> " value=""> " value=""> 这些表单是通过循环遍历 MySQL 上的所有数据而生成的。每个表单和输入都
Pony 有一个未参数化的异常值。 不幸的是,我经常有一些代码想要抛出不同类型的异常,并且我需要知道它们是什么,以便正确处理它们——例如,简单地说,当停止程序时,向用户提供以下信息很重要正确的错误消息
出于对所有神圣事物的热爱,您如何区分预定义的 .NET 异常类中的不同“异常风格”? 例如,一段代码可能会抛出 XmlException在以下条件下: 文档的根元素为NULL 文档中的字符无效 文档太
正如您在下面看到的,我创建了一个 JComboBox,其中“选项”数组中的元素作为列表中的选项。 当选择列表中的特定项目时,我想显示 JLabels“一个”或“两个”。例如。选择选项一显示“一”,选择
我有一个表,其中包含四列用户名、产品名称、产品价格和一个名为 item_paid 的 boolean 列。相同的产品名称可以作为重复条目插入到表中。但是有没有办法区分一行和重复行?或者我应该创建一个名
是否可以使用反射来区分仅 getter 属性和表达式主体属性? class MyClass { DateTime GetterOnly { get; } DateTime Expres
我即将为一个学校项目制作一个小程序,该程序应该能够识别通过 MIDI 钢琴输入演奏的和弦(这只是其中的一部分)。 目前为止,每次按下和每次释放 MIDI 键盘上的某个键,我都会得到一个 ShortMe
我正在使用“自动”反序列化器从 Kafka 消费 Avro 序列化消息,例如: props.put( ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFI
我需要从两个表中检索数据。第一个是事件列表,第二个是 field 列表。 我在两个表中都有一个同名的字段:events.venue(这是一个 ID),venues.venue 是地点的名称,比如“bl
我是一名优秀的程序员,十分优秀!