- 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/
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求提供代码的问题必须表现出对所解决问题的最低限度理解。包括尝试过的解决方案、为什么它们不起作用,以及预
出于某种原因,右栏中的精选文章忽略了“#elementtext”和“#elementtext:hover”属性。仅显示“p.element”和“img.element”。 有什么想法吗? 谢谢 - 塔
我有两个值,每个值都来自不同的枚举。我想检查这两者的允许组合,如果没有找到则执行默认操作。我能以某种方式对这两个值进行切换/大小写吗?我想避免使用多个 if/else 语句或遵循位掩码模式的枚举,只是
我需要 where 但 not 大小写。例如,我想找到没有名字“莎士比亚”的戏剧: _.where(listOfPlays, {author: !"Shakespeare", year: 1611})
我想实现一个 parking 场应用所以有一个带5个或更多 parking 位的车库当司机 parking 时,车库中的下一个空闲位置应该分配给他。 所以我有一个带 5 个或更多插槽的 table 上
我想使用 Erlang 来确定传递给函数的变量是否可以被数字整除。我考虑过使用 case 来执行此操作,但是我找不到解决方案。 case 是适合这项工作的工具吗? 示例:将数字传递给函数 f()。如果
我在 phpmyadmin 中创建了一个表,其列名如 first_name、last_name。当我使用命令显示表中的列名时,它会将它们显示为 first_name。 我想显示我的列名称,如 Firs
使用 Swift 4,如何使用这些规则格式化字符串: 如果单词超过 3 个字母,则首字母大写,否则大写 包含像 St-Michel 这样的连字符的 Pascal 大小写单词 我这里有初稿,但我一直在思
这个问题在这里已经有了答案: Why can't the switch statement be applied to strings? (23 个回答) 关闭 8 年前。 大家好 所以我正在尝试对
在 MVC 操作中,我如何访问使用多个同名值提交的“表单数据”中的值? 我做了什么:int、decimal、string 类型的值工作完美。 问题:每个变体都有一个复选框,所以当我尝试获取它时,它只显
while(1) { char buff[1000]; printf("Enter the word: "); fgets(buff, 1000
我有一个 Dllmain,它在线程附加到此 DLL 时分配线程本地存储。代码如下: BOOL APIENTRY DllMain(HMODULE hModule,
我有一个变量名,比如“WARD_VS_VITAL_SIGNS”,我想将它转换为 Pascal 大小写格式:“WardVsVitalSigns” WARD_VS_VITAL_SIGNS -> WardV
我是 Swift 编码的新手,正在尝试弄清楚如何在触摸节点时制作具有开/关功能的循环音频。我认为实现它的最佳方式是通过 SKAudioNode,但我不确定我在以下代码中做错了什么。当在节点上按下时 -
这是我第一次使用这种枚举,具有关联值类型的枚举,我需要根据对象的类型制作一个 switch 语句,我无法做到,这是枚举: enum TypeEnum { case foo(FooClass)
我想从字符串中删除所有下划线,下划线后面的字符为大写。因此,例如:_my_string_ 变为:MyString 同样:my_string 变为 MyString 有没有更简单的方法呢?我目前有以下内
如何在 Java 中将蛇形大小写转换为 Camel 形大小写? 输入:“input_in_snake_case” 输出:“InputInSnakeCase” 最佳答案 Guava通过其CaseForm
我们有一个表auth_group_access,那么如何使用呢? 在使用M方法时,对于带下划线的表名,可以采用如下方法。 M('AuthGroupAccess'); 对应sql语句SQL: S
我正在制作一个 pygame 游戏,每当我运行我的代码时,我都会收到错误 expected ':'。我知道在 match/case block 中使用 [ 和 ] 用于其他用途,但我该如何解决这个问题
有人能告诉我是否可以使用正则表达式将 url 转换为小写? 这是在 html img 标签内,所以我们可以通过标签找到网址。 这是我所拥有的一个例子 我需要在最后小写图像名称。 该文档包含更多 H
我是一名优秀的程序员,十分优秀!