2017-09-02 16 views
0

(質問は、あまりにもLaracastに掲載まだ答えを明らかにしなかったので、私はStackOverflowのを試してみる)Laravel /雄弁:モデルで計算され、データベースのフィールドどの

こんにちはコミュニティ、私が解決しなければならない

さまざまなデータベースから読み込まれるフィールドを持つモデルを持つEloquentのデータベースの問題です。私は英語/ OOP/Laravel/Eloquent/PHPの用語で問題を適切に表現するのが難しいので、私は自分のニーズを一例として表現しようとします(正しいPHP構文はあまり気にしません)。

を考えると、使用される属性は通常、ツリー状の構造に似ているモデルがあります:

[treenode] 
id 
parent_id (=self referencing key to id) 
name 
... 

今すぐ木は、異なる種類、たとえば、家、車やユーザーのノードへのポインタを格納することであると言います、そのそれぞれが異なるテーブル/モデルに格納されます。

[house] 
id 
name 
street address 
zip 
... 

[car] 
id 
name 
brand 
horsepower 
... 

[user] 
id 
name 
age 
gender 
... 

問題は透過的に、すべてのモデルが持っている「名前」フィールドを、移入するために他のデータベースにアクセスし、「ツリーノード」のためのモデルを持つことは明らかです共通して、木を描く。

私はへのTreeNodeモデルを変更することについて考えた:

[treenode] 
id 
parent_id 
kind (house | car | user) 
data_id (key into house | car | user table) 
... 

次のステップは「何とか」コード「名前」フィールド雄弁でにあったので、それはまだ「ツリーノード」の一部であったようにそれが表示されますモデル、これは私が立ち往生している場所です。そのように、ドキュメントに記述のように私は、モデル内の「計算フィールド」を試してみました:

public function name() { 

select case $this->kind { 
    case house: return House::findorfail($this->data_id)->first() 
    case car: return Car::findorfail($this->data_id)->first() 
    case user: return User::findorfail($this->data_id)->first() 
} 
} 

これは一見何とか作業を行いますが、明らかに「名前は」本当にモデルの属性リストに含まれていませんしたがって、シリアル化されません。つまり、私がJSON_encodeをtreenodeにすると、 "name"は含まれません。

また、名前を変更する場合は、適切なデータベースに書き戻す必要があり、また、JSONのサポートも必要になりますので、treenodeを変更して「名前」を設定すると同様の問題が発生します。私はこれをどのように達成できるかという手がかりはありません。 getNameAttributeやsetNameAttributeのようなアクセサについては読んでいますが、私が見た限りでは、treenodeモデルに "name"フィールドがある場合にのみ動作します。

私の鼻を正しい方向に向けることができます...私は何とか私のtreenodeモデルを再加工して、他のテーブルからその内容を取得する「名前」フィールドを必要とすることができます。その名前を他のテーブルに書き出しますが、そうでなければ「treenode」モデルに含まれていたときとまったく同じように動作します。

thx、

アルミン。

+0

Laravelのどのバージョンをお使いですか? –

+0

V5.4、申し訳ありませんが、私は言及するのを忘れました。しかし、私はすでにあなたの提案された答えを見ました、そして、これは本当に有望なようです。私は今夜​​それを試してみましょう、あなたができるだけ早く結果について知ってみましょう。その間に:ありがとう! – Nimral

答えて

0

読み込み問題から、モデルを異なるモデルにリンクでき、モデルの型を外部キーとして「ハーコード」しないため、laravelのPolymorphic Relationsがあなたの問題に対する正しい答えと思われます。

多型関係により、モデルは単一の関連付けで複数の他のモデルに属することができます。

は一例でこれをチェックアウト:

https://laravel.com/docs/5.4/eloquent-relationships#polymorphic-relations

+0

これは行く方法ですが、ロスが答えを出すために数秒であなたを打ち負かすようです。それにもかかわらず、あなたのご意見をありがとうございます、これはまさに私が探していたものです! – Nimral

+0

ハハそれは大丈夫です、あなたはそれをupvoteすることができます:) – Sletheren

+0

最初にテストし、次に応援します:-) Upvote来る、約束:-) – Nimral

0

あなたの例からは、Polymorphic Relationships後にしているように聞こえます。まず

kind_iddata_idkindを変更し、kind_typeすなわち

data_idkind_id

kindあなたとあなたの移行ファイルでこれを行うことができますkind_type

なり次のようになります。

$table->morphs('kind'); 

は、その後、あなたのtreenodeモデルに追加します。

/** 
* Kind Relationship 
* 
* @return \Illuminate\Database\Eloquent\Relations\MorphTo 
*/ 
public function kind() 
{ 
    return $this->morphTo(); 
} 

/** 
* Get the name from the "kind" relationship 
* 
* @return mixed 
*/ 
public function getNameAttribute() 
{ 
    return $this->kind->name; 
} 

その後、あなたは次のことを行うことができます:

$treeNode = App\TreeNode::with('kind')->first(); 

$treeNode->name; //This would be the name on the other model 

(上記のことは、あなたがtreenodeモデルがApp\TreeNodeであることを前提としています。そうでない場合は、正しいものに変更してください)。

希望すると便利です。


EDIT

すでに本番環境/そして、あなたはそれを参照するのモデルの完全修飾名前空間であることをkind_typeを更新する必要がありますされるようにデータを維持する必要性と作業している場合例えば

DB::table('treenode') 
    ->where('kind_type', 'user') 
    ->update(['kind_type' => \App\User::class]); 

あなたは(あなただけが、これは自動的に行われますassociate()メソッドを使用する場合、その後、最初にこれを実行する必要がある必要があります)すべての異なるkind_typeのためにこれを行う必要があります。

また、あなたはモーフマップを設定することができます。

use Illuminate\Database\Eloquent\Relations\Relation; 

Relation::morphMap([ 
    'user' => 'App\User', 
]); 

あなたのAppServiceProviderboot()方法に上記を追加することができます。

+0

こんにちはロス、あまり運がない。 2つの問題:最初に、提案したようなモデルを変更しましたが、Treenodeモデルではまだ達成したい目標の1つだった「名前」属性は含まれていないようです。 – Nimral

+0

また、ネームスペースに深刻な問題があるようですが、私のモデルは見つかりません。私はこのエラーが発生します: "Symfony \ Component \ Debug \ Exception \ FatalThrowableError:Class 'user'が見つかりません[...] \ vendor \ laravel \ framework \ src \ Illuminate \ Database \ Eloquent \ Concerns \ HasRelationships.php:487を参照してください。 App \ UserステートメントをコントローラとTreenodeモデルファイルに入れようとしましたが、両方のファイルで任意のユーザーモデルを正常にクエリできます。 $ test = User :: find(6)、それでもコントローラから$ node-> kind-> nameを呼び出すとエラーが続く。 – Nimral

+0

テーブルの列名も変更しますか? PSR-1とPSR-4に従っていることを確認してください。クラス名はファイル名と正確に一致し、StudlyClass、すなわち 'User.php'と' user'ではなく 'class User'で書かれています。 –