Laravel geçiş dosyasında bir veritabanı doldurma


115

Laravel'i yeni öğreniyorum ve bir kullanıcı tablosu oluşturan çalışan bir geçiş dosyam var. Taşıma işleminin bir parçası olarak bir kullanıcı kaydını doldurmaya çalışıyorum:

public function up()
{
    Schema::create('users', function($table){

        $table->increments('id');
        $table->string('email', 255);
        $table->string('password', 64);
        $table->boolean('verified');
        $table->string('token', 255);
        $table->timestamps();

        DB::table('users')->insert(
            array(
                'email' => 'name@domain.com',
                'verified' => true
            )
        );

    });
}

Ancak çalışırken şu hatayı alıyorum php artisan migrate:

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'vantage.users' doesn't exist

Bunun nedeni, Artisan'ın henüz tabloyu henüz oluşturmamış olmasıdır, ancak tüm belgeler, bir geçişin parçası olarak verileri doldurmak için Akıcı Sorgu kullanmanın bir yolu olduğunu söylüyor gibi görünüyor.

Nasıl olduğunu bilen var mı? Teşekkürler!

Yanıtlar:


215

DB :: insert () 'i Schema :: create ()' in içine koymayın, çünkü create yönteminin siz malzeme eklemeden önce tablo oluşturmayı bitirmesi gerekir. Bunun yerine şunu deneyin:

public function up()
{
    // Create the table
    Schema::create('users', function($table){
        $table->increments('id');
        $table->string('email', 255);
        $table->string('password', 64);
        $table->boolean('verified');
        $table->string('token', 255);
        $table->timestamps();
    });

    // Insert some stuff
    DB::table('users')->insert(
        array(
            'email' => 'name@domain.com',
            'verified' => true
        )
    );
}

5
ve birden çok veri nasıl eklenir?
Sahbaz

6
@ SuperMario'nunYoshi'si böyle bir şey düşünüyorumDB::table('users')->insert([ ['email' => 'taylor@example.com', 'votes' => 0], ['email' => 'dayle@example.com', 'votes' => 0] ]);
Денис

80

Bunun eski bir gönderi olduğunu biliyorum ama bir google aramasında ortaya çıktığı için burada biraz bilgi paylaşacağımı düşündüm. @ erin-geyer, geçişleri ve tohumlayıcıları karıştırmanın baş ağrısı yaratabileceğine dikkat çekti ve @justamartin, bazen dağıtımınızın bir parçası olarak verilerin doldurulmasını istediğiniz / buna ihtiyaç duyduğunuza karşılık verdi.

Bir adım daha ileri gidiyorum ve bazen veri değişikliklerini tutarlı bir şekilde sunabilmenin arzu edildiğini söyleyebilirim, böylece örneğin aşamalandırmaya dağıtabilir, her şeyin yolunda olduğunu görebilir ve ardından aynı sonuçların güvenle üretime geçmesini sağlayabilirsiniz. (ve bazı manuel adımları çalıştırmayı hatırlamak zorunda değilsiniz).

Bununla birlikte, tohum ve göçü birbirinden ayırmanın hala bir değeri vardır, çünkü bunlar birbiriyle ilişkili ancak farklı iki endişe kaynağıdır. Ekibimiz, ekiciler çağıran geçişler oluşturarak ödün verdi. Bu şuna benzer:

public function up()
{
    Artisan::call( 'db:seed', [
        '--class' => 'SomeSeeder',
        '--force' => true ]
    );
}

Bu, tıpkı geçiş gibi bir tohum çalıştırmanıza izin verir. Davranışı önleyen veya artıran mantığı da uygulayabilirsiniz. Örneğin:

public function up()
{
    if ( SomeModel::count() < 10 )
    {
        Artisan::call( 'db:seed', [
            '--class' => 'SomeSeeder',
            '--force' => true ]
        );
    }
}

Bu, 10'dan az SomeModel varsa, tohum makinenizi koşullu olarak çalıştıracaktır. Bu, tohumlayıcıyı hem çağırdığınızda artisan db:seedhem de geçiş yaptığınızda yürütülen standart bir ekici olarak dahil etmek istiyorsanız yararlıdır, böylece "çiftleme" yapmazsınız. Ayrıca, geri dönüşlerin beklendiği gibi çalışması için bir ters tohumlayıcı da oluşturabilirsiniz, örn.

public function down()
{
    Artisan::call( 'db:seed', [
        '--class' => 'ReverseSomeSeeder',
        '--force' => true ]
    );
}

İkinci parametre --force, ekme makinesinin bir üretim ortamında çalışmasını sağlamak için gereklidir.


2
Bu açık ara en iyi cevap. Endişeleri ayıran, korunabilir kod!
helsont

18
Tohumlayıcıları geçiş komut dosyalarından çağırmanın uzun vadeli sonuçlarını dikkate almak konusunda dikkatli olurum. Taşıma komut dosyaları tarih / saat sürümlüdür, ancak ekiciler genellikle değildir. Geliştirme sırasında, seeder'ın ihtiyaçları sıklıkla değişir ve bu da sürümlendirilmemiş tohumlayıcıları çalıştıran sürümlü geçiş komut dosyalarının olasılığına neden olarak idempotensi bozar. Başka bir deyişle, aynı geçiş komut dosyası kümesini günden güne çalıştırmak farklı sonuçlar verebilir.
originalbryan

2
Bunu yayınladığımdan bu yana uzun zaman geçti ve bu tekniği kullanarak deneyimimizi sağlamak istedim. Genel olarak bizim için iyi çalıştı ve eğer tekrar yapmam gerekirse yapardım. Bu, dikkat edilmesi gereken bir şey olduğunu söyledi. @originalbryan tam olarak haklı ve bunun sonucunda, yeni bir DB döndürürken zaman zaman geçişlerin kesildiği durumlarla karşılaşıyoruz çünkü geçişler çalıştırılırken seeder (ve model) veritabanından daha günceldir (çünkü şema tamamen güncellenmeden önce). Bu olduğunda, sorunu gidermek için eski geçişi güncelliyoruz.
darrylkuhn

@darrylkuhn Eski taşıma dosyalarını güncellemenin iyi bir uygulama olmadığını duydum - eski dosyaları güncellemek yerine, yeni taşıma dosyası oluşturmalısınız - bu, tasarım gereği taşıma dosyaları için "iş akışı"
Kamil Kiełczewski

2
Laravel'in tüm dili, bir tohum makinesinin test verileri için olduğunu ima eder, bu yüzden bunun tasarımda akılda tutulması gerektiğini düşünüyorum. Uygulamanın parçası olan verilerle test verilerini birbirinden ayırt etmek önemlidir ve gerekli verileri doğrudan bir geçişe dahil etmek, bu ayrımı çok açık bir şekilde yapar.
Brettins

13

Laravel'in Database Seeder'ı kullanmanın neden Migrations yerine tercih edildiğine dair çok iyi bir açıklama: http://laravelbook.com/laravel-database-seeding/

Bununla birlikte, resmi belgelerdeki talimatları takip etmek çok daha iyi bir fikirdir çünkü yukarıdaki bağlantıda açıklanan uygulama işe yaramıyor gibi görünüyor ve eksik. http://laravel.com/docs/migrations#database-seeding


1
Sana katılıyorum Erin. Taşıma işlemlerini çekirdek verileriyle karıştırmayın, çünkü büyük olasılıkla geliştirme ortamınızda bazı verileri tohumlamak isteyip de üretim ortamınızda değil.
Daniel Vigueras

18
İyi bir nokta, ancak bazı verilerin üretim ortamında bulunması gereken durumlar vardır. Örneğin, müşterinin ilk kez oturum açabilmesi için ilk varsayılan yönetici kullanıcının var olması gerekir, önceden belirlenmiş bazı yetkilendirme rolleri mevcut olmalıdır, bazı iş mantığı verileri de hemen gerekli olabilir. Bu nedenle, göçlere zorunlu verilerin eklenmesi gerektiğini düşünüyorum (böylece veri kayıtlarını ayrı geçişler yoluyla da yukarı / aşağı yapabilirsiniz), ancak geliştirmeye tohumlar bırakılabilir.
JustAMartin

Küçük bir not; veritabanı tohumlama bağlantısı şu anda: laravel.com/docs/5.3/seeding
magikMaker

3

Bu ne istiyorsan yapmalı.

public function up()
{
    DB::table('user')->insert(array('username'=>'dude', 'password'=>'z19pers!'));
}

1

Bunu yapmanın başka bir temiz yolu, ilgili Model'i oluşturan ve kalıcı olan örneği oluşturan özel bir yöntem tanımlamaktır.

public function up()
{
    Schema::create('roles', function (Blueprint $table) {
        $table->increments('id');
        $table->string('label', 256);
        $table->timestamps();
        $table->softDeletes();
    });

    $this->postCreate('admin', 'user');
}

private function postCreate(string ...$roles)  {
    foreach ($roles as $role) {
        $model = new Role();
        $model->setAttribute('label', $role);
        $model->save();
    }
}

Bu çözümle, zaman damgası alanları Eloquent tarafından oluşturulacaktır.

DÜZENLEME: Veritabanı yapısı üretimini ve veritabanı popülasyonunu ayırmak için tohumlama sistemini kullanmak daha iyidir.


Bunu beğendim ... tam olarak yapmam gereken şeyi sunuyor, geçişte varsayılan olarak birkaç kullanıcı rolü ekliyor. Modeli içe $model = new App\UserRoles();aktardığınızdan veya doğrudan ona başvurduğunuzdan emin olmanız gerekir , ancak bunun dışında ... mükemmel!
FAB

1

Bu DB ekleme yöntemini denedim, ancak modeli kullanmadığından modeldeki yavaş bir özelliği görmezden geldi. Bu nedenle, bu tablonun Modeli mevcut olduğu için, taşınır taşınmaz modelin veri eklemek için kullanılabileceğini düşündüm. Ve şunu buldum:

public function up() {
        Schema::create('parent_categories', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('slug');
            $table->timestamps();
        });
        ParentCategory::create(
            [
                'id' => 1,
                'name' => 'Occasions',
            ],
        );
    }

Bu doğru bir şekilde çalıştı ve aynı zamanda bu giriş için otomatik olarak bir bilgi bilgisi oluşturmak için Modelimdeki durgun özelliği hesaba kattı ve zaman damgalarını da kullandı. NB. Kimliği eklemek gerekli değildi, ancak bu örnekte kategorilerim için belirli kimlikler istedim. Laravel 5.8 üzerinde çalışırken test edildi


0

Sütunları zaten doldurduysanız ve yenilerini eklediyseniz veya eski sütunu yeni sahte değerlerle doldurmak istiyorsanız, şunu yapın:

public function up()
{
    DB::table('foydabars')->update(
        array(
            'status' => '0'
        )
    );
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.