web-dev-qa-db-ja.com

laravel:データベースにデータを挿入する雄弁な例

これを聞いて申し訳ありませんが、私はcodeIgniterから来ており、雄弁なモデル挿入を理解するのに本当に苦労しています。これは私にとってモデルを扱う新しい方法です。

私は この記事 を読み、いくつかの基本を理解しました。

私は次の例を持っています。私は多くの属性を持つ製品を持っていますが、関連するものはブランドと製品名です。 (次の表の例を参照)

製品:id(PK)、name、description、brand_idブランド:id(PK)、name

ここで問題が発生します。私は新しいブランドを作成できることを知っており、新しい製品を作成する方法を知っています。ただし、この2つを接続する方法はありません。ここに私が今持っているコードがあります。新しい製品を作成し、ブランドテーブルに自動的に入力したい。これは、現在コントローラーの一部です。

要するに。 products.brand_id内にbrands.idが必要です

    $product = new Products;
    $product->name = "product1";
    $product->description = "description1";

    $brand = new Brands;
    $brand->name = "brand1"
    $product->brand()->associate($brand);

    $brand->save(); 
    $product->save(); 

より明確にするため。 2つのモデルがあります。製品およびブランドモデル。しかし、モデルに何を含めるべきかは明確ではありません。これは私の現在の製品モデルです。ブランドモデルには、保護された$ table = "brands"のみが必要だと思います。モデルクラス内の行。

 class Products extends Eloquent  {

    protected $table = 'products';

    public function brand()
    {
       return $this->hasOne('brands');
    }
  }

誰かが私が間違っていることを私に説明できますか?関係のある雄弁なモデル内にデータを挿入する方法についての良いチュートリアルは見つかりません。ほとんどのチュートリアルは、データの表示に関するものです。

16
Klaas

さて、あなたの質問を読み直しましたが、あなたはいくつか間違っていると思うので、メインの投稿にコメントを残さずに答えに行くことができると思いましたので、ここに行きます。

まず、あなたの関係は間違ったタイプであり、間違った方法です。私が理解しているように(そして私自身の仕事でこれらのことを実装しているように)製品はブランドに属します。したがって、最初にDBスキーマ-通常の列と外部キー_brand_id_を含むproductsテーブルがあることに言及します。これまでのところ良い:これは私が関係を解釈する方法と一致しています。

ただし、その後、モデルを表示します。 ProductモデルはhasOne Brandですが、実際にはブランドに属します。また、関係の逆を定義しません-Laravelをうまく機能させるためには両側が必要です。それに加えて、あなたの命名はちょっとしたものではありません-それはおそらく動作しますが、Laravelの規則に従うと、次のようになります:

productsモデル:_Product.php_

_class Product extends Eloquent
{
    public function brand()
    {
        return $this->belongsTo('Brand');
    }
}
_

brandsモデル:_Brand.php_

_class Brand extends Eloquent
{
    public function products()
    {
        return $this->hasMany('Product');
    }
}
_

さて、これまでのところとても良い。さまざまな規則に気付くでしょう。

  1. テーブル名は複数形(productsbrands
  2. 外部キーは単数形を使用します(_brand_id_)
  3. モデル名は単数形およびStudlyCaseです(テーブルProductの場合はproducts、テーブルBrandの場合はbrands
  4. Laravelの規則に従う限り、_$table_プロパティを指定する必要はありません(つまり、テーブル名はモデルクラス名の複数形のsnake_caseバージョンです)
  5. リレーションシップは両方の方法で定義する必要があります(各モデルに1つ、belongsToの逆はhasManyで、hasOne/belongsTobelongsToMany/belongsToMany
  6. リレーションシップを取得するメソッドの名前は意味があります-1つの結果が予想される場合は単数(brandProduct)、複数の結果が複数であると予想される場合(products in Brand
  7. 関係定義でモデルクラス名を使用します($this->hasMany('Brand')ではなく$this->hasMany('brands')またはその他のバリエーションを使用します

これらのルールを守れば、モデルは本当に簡潔でありながら非常に強力になります。

さて、実際のデータを実際に定義する方法については、投稿したコードが正常に動作するかもしれないと感じています(Laravelが舞台裏にあるかどうかに依存します)が、最初のコメントで提案したように、Laravelが何をすべきかを失ってしまわないように、associate()を呼び出す前に_$brand_を保存したことを確認します。そのようなものとして、私は行きたい:

_// create new brand and save it
$brand = new Brand;
$brand->name = "Brand 1";
$brand->save();

// create new product and save it
$product = new Product;
$product->name = "Product 1";
$product->description = "Description 1";
$product->brand()->associate($brand);
$product->save();
_

この方法で、データベースにIDがすでに定義されているブランドがあることを知ってから、関係で使用します。

また、逆の方法で関係を定義することもできます。そうすることで、頭を痛めにくくなります。

_// create new product and save it
$product = new Product;
$product->name = "Product 1";
$product->description = "Description 1";
$product->save();

// create new brand and save it
$brand = new Brand;
$brand->name = "Brand 1";
$brand->save();

// now add the product to the brand's list of products it owns
$brand->products()->save($product);
_

その最後の行の後にどちらのモデルでもsave()を呼び出す必要はありません。自動的に_$brand_のid値を取得し、_$product_に配置するからです。 _brand_id_フィールド、および_$product_を保存します。

詳細については、この関係を挿入する方法に関するドキュメントを参照してください。 http://laravel.com/docs/eloquent#one-to-many

とにかく、うまくいけば、この投稿で、コードのどこがおかしいのかが明らかになります。上で言ったように、これらは慣習であり、あなたはそれらに反することができますが、そうするためにあなたは余分なコードを入れ始める必要があり、他の開発者にとって非常に読めない可能性があります。特定のフレームワークを選択した場合、その規則に従うこともできます。

46
alexrussell