【发布时间】:2019-10-03 05:32:24
【问题描述】:
我正在为一家诊所建立一个父->n-子模型关系(多表),并尝试自动映射父数据。我收到 array_key_exists(): The first argument should be either a string or an integer 错误。
我正在关注本教程:https://design-patterns12.blogspot.com/2018/01/laravel-model-inheritance-through.html
DB关系是:
剧集(PK'['audit', 'episode', 'mrn']')
抽象病房
五种不同类型的Ward 之一。其中每一个都有大约 100 个字段,这些字段彼此独立且独立于 Episode 父级。
class Episode extends Model
{
use HasCompositePrimaryKey;
protected $table = 'episodes';
protected $primaryKey = ['audit', 'episode', 'mrn'];
public $incrementing = false;
protected $fillable = ['audit', 'episode', 'mrn'];
protected $ward_fields = [];
public $timestamps = false;
public function audit()
{
return $this->belongsTo($this->audit(), 'id');
}
public function ward()
{
return $this->morphTo();
}
public function __get($name) {
$ret = parent::__get($name);
if ($ret === null) {
if (isset($this->ward_fields[$name])) {
$ret = $this->ward_fields[$name];
} else if (array_key_exists('ward', $this->getRelations())) {
$ret = $this->ward->{$name};
}
}
return $ret;
}
public function __toString() {
return $this->audit . ' ' . $this->episode . ' ' . $this->mrn;
}
}
抽象类
<?php
namespace App;
use Illuminate\Support\Facades\Schema;
abstract class Ward extends Episode
{
public $timestamps = false;
protected $episode_fields = [];
public function parent_episode()
{
return $this->morphOne(Episode::class, 'ward');
}
public function __get($name)
{
$ret = parent::__get($name);
if ($ret === null) {
if (isset($this->episode_fields[$name])) {
$ret = $this->episode_fields[$name];
} else if ($this->parent_episode()->count() > 0) {
$ret = $this->episode->{$name};
}
}
return $ret;
}
public function __set($key, $value)
{
if (!Schema::hasColumn($this->getTable(), $key)) {
$this->episode_fields[$key] = $value;
} else {
parent::__set($key, $value);
}
}
public function __unset($key)
{
if (!Schema::hasColumn($this->getTable(), $key)) {
unset($this->episode_fields[$key]);
} else {
parent::__unset($key);
}
}
public function __isset($key)
{
if (!Schema::hasColumn($this->getTable(), $key)) {
return isset($this->episode_fields[$key]);
} else {
return parent::__isset($key);
}
}
public function save(array $options = array())
{
$ret = parent::save($options);
if ($ret) {
$episode = $this->episode;
if ($episode == null) {
$episode = new Episode;
}
foreach ($this->episode_fields as $key => $value) {
$episode->{$key} = $value;
}
$episode->save();
$this->parent_episode()->save($episode);
}
return $ret;
}
public function delete()
{
$ret = false;
if ($this->episode->delete()) {
$ret = parent::delete();
}
return $ret;
}
}
Example.test Rehabilitation 病房
namespace App\Ward;
use App\Ward;
class Rehabilitation extends Ward
{
protected $table = 'rehabilitations';
protected $with = ['episodes'];
protected $fillable = ['audit', 'episode', 'mrn'];
public $timestamps = false;
}
这一切似乎都很顺利,直到我运行种子并偶然发现了 save() 方法
ErrorException : array_key_exists(): The first argument should be either a string or an integer
at /Users/doug/Code/Snap/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php:317
313|
314| // If the attribute exists in the attribute array or has a "get" mutator we will
315| // get the attribute's value. Otherwise, we will proceed as if the developers
316| // are asking for a relationship's value. This covers both types of values.
> 317| if (array_key_exists($key, $this->attributes) ||
318| $this->hasGetMutator($key)) {
319| return $this->getAttributeValue($key);
320| }
321|
Exception trace:
1 array_key_exists([])
/Users/doug/Code/Snap/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php:317
2 Illuminate\Database\Eloquent\Model::getAttribute()
/Users/doug/Code/Snap/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasOneOrMany.php:376
3 Illuminate\Database\Eloquent\Relations\HasOneOrMany::getParentKey()
/Users/doug/Code/Snap/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasOneOrMany.php:70
4 Illuminate\Database\Eloquent\Relations\HasOneOrMany::addConstraints()
/Users/doug/Code/Snap/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphOneOrMany.php:51
5 Illuminate\Database\Eloquent\Relations\MorphOneOrMany::addConstraints()
/Users/doug/Code/Snap/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php:71
6 Illuminate\Database\Eloquent\Relations\Relation::__construct(Object(Illuminate\Database\Eloquent\Builder), Object(App\Ward\Rehabilitation))
/Users/doug/Code/Snap/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasOneOrMany.php:46
7 Illuminate\Database\Eloquent\Relations\HasOneOrMany::__construct(Object(Illuminate\Database\Eloquent\Builder), Object(App\Ward\Rehabilitation), "episodes.ward_id")
/Users/doug/Code/Snap/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphOneOrMany.php:40
8 Illuminate\Database\Eloquent\Relations\MorphOneOrMany::__construct(Object(Illuminate\Database\Eloquent\Builder), Object(App\Ward\Rehabilitation), "episodes.ward_type", "episodes.ward_id")
/Users/doug/Code/Snap/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php:158
9 Illuminate\Database\Eloquent\Model::newMorphOne(Object(Illuminate\Database\Eloquent\Builder), Object(App\Ward\Rehabilitation), "episodes.ward_type", "episodes.ward_id")
/Users/doug/Code/Snap/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php:143
10 Illuminate\Database\Eloquent\Model::morphOne("App\Episode", "ward")
/Users/doug/Code/Snap/app/Ward.php:14
11 App\Ward::parent_episode()
/Users/doug/Code/Snap/app/Ward.php:77
12 App\Ward::save()
/Users/doug/Code/Snap/database/seeds/Ward/RehabilitationTableSeeder.php:31
13 RehabilitationTableSeeder::run()
/Users/doug/Code/Snap/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:32
14 call_user_func_array([])
/Users/doug/Code/Snap/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:32
15 Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
/Users/doug/Code/Snap/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:90
16 Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Object(Closure))
/Users/doug/Code/Snap/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:34
17 Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), [])
/Users/doug/Code/Snap/vendor/laravel/framework/src/Illuminate/Container/Container.php:576
18 Illuminate\Container\Container::call()
/Users/doug/Code/Snap/vendor/laravel/framework/src/Illuminate/Database/Seeder.php:122
19 Illuminate\Database\Seeder::__invoke()
/Users/doug/Code/Snap/vendor/laravel/framework/src/Illuminate/Database/Seeder.php:42
20 Illuminate\Database\Seeder::call("RehabilitationTableSeeder")
/Users/doug/Code/Snap/database/seeds/DatabaseSeeder.php:18
21 DatabaseSeeder::run()
/Users/doug/Code/Snap/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:32
我期待我所遵循的教程中的人的成功可以复制。
我可以在代码中看到一些我不太理解的问题:
在Ward 类中,save() 方法有一个$this->episode 魔术变量,我不确定它是如何设置的。它还返回一个整数,而我原以为它会返回一个 (Episode) 对象。
有人可以帮忙解释一下吗?
【问题讨论】:
-
仍在努力,我想我现在有更多信息。堆栈跟踪和进一步调试向我表明,变形字段无法处理复合字段。错误是“获取主键”函数正在使用
array_key_exists,同时将(主键的)数组作为第一个参数传递。是否可以使用特征来覆盖这种特殊情况?
标签: php laravel eloquent laravel-5.8