skip to Main Content

I’m new to laravel and trying to make two tables with a one (customer) to many(table) relation and a custom Foreign Key tables.customer(I can not change this)

The connection is over customers.id on tables.customer.

After Running php artisan migrate:fresh --seed everything is created as expected. But tables.customer is always 0.
I don’t get any errors. And both tables are created correctly.
What do I miss?

Here are my settings:

Models:

Customers.php

namespace AppModels;

use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;

class Customers extends Model {
  use HasFactory;

  public function tables() {
    return $this->hasMany(Tables::class, 'customer');
  }

  public $timestamps = false;
}

Tables.php

namespace AppModels;

use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;

class Tables extends Model {
  use HasFactory;

  public function customers() {
    return $this->belongsTo(Customers::class, 'customer');
  }

  public $timestamps = false;
}

Migration:

customers

use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;

return new class extends Migration {
  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up() {
    Schema::create('customers', function (Blueprint $table) {
      $table->string('id', 6)->primary();
      $table
        ->string('img', 23)
        ->nullable()
        ->default(null);
      $table->tinyText('name');
      $table->tinyInteger('active')->default(1);
      $table->bigInteger('created'); // unix timestamp when created
      $table
        ->bigInteger('status')
        ->nullable()
        ->default(null); // null not deleted / unix timestamp when deleted
    });
  }

  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down() {
    Schema::dropIfExists('customers');
  }
};

tables

use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;

return new class extends Migration {
  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up() {
    Schema::create('tables', function (Blueprint $table) {
      $table->string('id', 8)->primary();
      $table->tinyText('number');
      $table->string('customer', 6); // TODO: repalce with uuid
      $table->bigInteger('created'); // unix timestamp when created
      $table
        ->bigInteger('status')
        ->nullable()
        ->default(null); // null not deleted / unix timestamp when deleted
    });
  }

  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down() {
    Schema::dropIfExists('tables');
  }
};

Factories:

CustomersFactory.php

namespace DatabaseFactories;

use IlluminateDatabaseEloquentFactoriesFactory;

/**
 * @extends IlluminateDatabaseEloquentFactoriesFactory<AppModelsCustomers>
 */
class CustomersFactory extends Factory {
  /**
   * Define the model's default state.
   *
   * @return array<string, mixed>
   */
  public function definition() {
    return [
      'id' => $this->faker->unique()->regexify('[A-Za-z0-9]{6}'),
      'name' => $this->faker->company(),
      'active' => $this->faker->boolean(),
      'created' => $this->faker->unixTime(),
      'status' => $this->faker->boolean() ? null : $this->faker->unixTime(),
    ];
  }
}

TablesFactory.php

namespace DatabaseFactories;

use AppModelsCustomers;
use IlluminateDatabaseEloquentFactoriesFactory;

/**
 * @extends IlluminateDatabaseEloquentFactoriesFactory<AppModelsTables>
 */
class TablesFactory extends Factory {
  /**
   * Define the model's default state.
   *
   * @return array<string, mixed>
   */
  public function definition() {
    return [
      'id' => $this->faker->unique()->regexify('[A-Za-z0-9]{8}'),
      'number' => $this->faker->unique()->numberBetween(1, 1000),
      'customer' => Customers::factory()->create()->id,
      'created' => $this->faker->unixTime(),
      'status' => $this->faker->boolean() ? null : $this->faker->unixTime(),
    ];
  }
}

Seeders:

customersSeeder.php

namespace DatabaseSeeders;

use AppModelsCustomers;
use IlluminateDatabaseConsoleSeedsWithoutModelEvents;
use IlluminateDatabaseSeeder;

class CustomersSeeder extends Seeder {
  /**
   * Run the database seeds.
   *
   * @return void
   */
  public function run() {
    Customers::factory()
      ->count(10)
      ->hasTables(20)
      ->create();
  }
}

TablesSeeder.php

namespace DatabaseSeeders;

use AppModelsTables;
use IlluminateDatabaseConsoleSeedsWithoutModelEvents;
use IlluminateDatabaseSeeder;

class TablesSeeder extends Seeder {
  /**
   * Run the database seeds.
   *
   * @return void
   */
  public function run() {
    //
  }
}

DatabaseSeeder.php

namespace DatabaseSeeders;

// use IlluminateDatabaseConsoleSeedsWithoutModelEvents;
use IlluminateDatabaseSeeder;

class DatabaseSeeder extends Seeder {
  /**
   * Seed the application's database.
   *
   * @return void
   */
  public function run() {
    $this->call([CustomersSeeder::class]);
  }
}

2

Answers


  1. By inspecting your models, you are recommended to define the table name first.

    // ========== SPECIFY TABLE TO USE (https://stackoverflow.com/a/51746287/19250775) ========== //
    protected $table = "users";
    

    And then you need to define fillable properties in order to mass assign your database, as the docs said.

    // ========== MASS ASSIGNABLE ATTRIBUTES ========== //
    protected $fillable = 
    [
        'id',
        'name',
        'email',
    ];
    

    Or if you want every column becomes fillable just add guarded attribute.

    protected $guarded = [];
    
    Login or Signup to reply.
  2. Your issue is that you did not tell each model that the id is not an integer, it is by default (check the source code).

    So add this to both models:

    protected $keyType = 'string';
    public $incrementing = false;
    

    Read about that here.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search