joshuadempseygb's avatar

Weird issue with Eloquent database naming?

I'm encountering a weird issue with Eloquent. In short, I have a model, which is called Jobrole. This describes a role in a company.

The model for this (jobrole.php) is:

<?php

namespace App\Models;

use \Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Jobrole extends Model
{
    use HasFactory, hasUuids;
    protected $guarded = [];
}

The migration file is below:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('jobroles', function (Blueprint $table) {
            $table->uuid('id')->primary();
            $table->uuid('owner_id');
            $table->foreign('owner_id')->references('id')->on('workplaces')->onDelete('cascade');
            $table->uuid('user_id');
            $table->foreign('user_id')->references('id')->on('users');
            $table->string('name');
            $table->string('description')->nullable();

            $table->timestamps();
        });
    }

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

It's important to note that I have not changed the database name in the migration.

When hitting the store method on the controller with some data, I receive the following error:

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'shiftlog.job-roles' doesn't exist

Here's where it gets interesting. If I change the name of the table, via a migration, I receive the exact same error, only with the new table name! So depending on which table name I use, it complains that the other isn't found. Now I'll receive the error:

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

I'm really at a loss as to why this is occurring. I've tried composer -o dump-autoload, and I've tried manually altering the table name in table plus, and also using $protected table = 'tablename' in the model which is ignored.

It might be interesting to note that the model name was originally JobRole, but I thought the capital R might have been causing issues so I've deleted the model, and regenerated it using

php artisan make:model Jobrole -a

Which does not seem to have made a difference.

Any help would be much appreciated, thank you.

0 likes
10 replies
LaryAI's avatar
Level 58

The issue seems to be with the naming convention used for the table in the migration file. By default, Eloquent assumes that the table name is the plural form of the model name, with underscores separating the words. In this case, the model name is "Jobrole" and Eloquent is looking for a table named "job-roles" or "job_roles".

To fix this issue, you can explicitly specify the table name in the model by adding the following line to the "Jobrole" model:

protected $table = 'jobroles';

This will tell Eloquent to use the "jobroles" table instead of trying to find a table with a different name.

Here's the updated code for the "Jobrole" model:

<?php

namespace App\Models;

use \Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Jobrole extends Model
{
    use HasFactory, hasUuids;
    protected $guarded = [];
    protected $table = 'jobroles';
}

After making this change, you should be able to use the "Jobrole" model without any issues.

joshuadempseygb's avatar

@LaryAI I've added the code to the model and Laravel is, it seems, ignoring it. It's still searching for 'job-roles', but if I create this table it searches for 'job_roles.' Very confusing.

christogonus's avatar
Level 12

Hi @joshuadempseygb,

If this is a new project, I would advise that you follow convention like @jeffreyway encourages, which is to name the model "JobRole".

So, my command will read as below:

php artisan make:model JobRole -a

Also, in the migration, I will check the "owner_id" to "workplace_id" and the column code will read as

$table->foreignUuid('workplace_id')->constrained('workplaces')->cascadeOnDelete();

In the model, you can define the relationship with "public function owner()" and add the neccessary references.

Best regards.

2 likes
joshuadempseygb's avatar

@christogonus Thank you this did seem to go some way to fixing the issue. I did think my migrations were a bit 'icky', I have a similar employee model who is also linked to organisations. I've copied your code and changed both migrations to 'workplace_id' and I'll try and create the relationships through relations in the model. Thank yu very much for your help. I'm on the right track now :)

jlrdw's avatar

Also read the documentation that covers the part about custom naming.

I do agree you are better off following conventions

1 like
joshuadempseygb's avatar

@jlrdw I shall do and I agree, I try too. I'm just starting out and wherever possible try to stick rigidly to documentation. Thanks for your help.

1 like
Snapey's avatar

You said earlier that your model was jobrole.php - but the class is Jobrole. Rename the file.

My guess is that you have a relationship somewhere where you have typed JobRole as the relationship name?

2 likes
joshuadempseygb's avatar

@Snapey I think the issue was more my lack on understanding regarding relationships. My migrations were adding unnecessary information and I've recreated this using the correct relationships in the model and it seems to be working so far. I just have to refactor some code using new relationships etc which shouldn't cause too many problems. Thanks for your help :)

1 like
joshuadempseygb's avatar

Aha, I found it. Buried inside a Rule::unique was a call to the table name... job-roles... problem solved. However thanks for all the tips everyone, my code is now a lot cleaner and less "icky" and is setup with the correct relationships.. which has massively improved my policies and controllers as well.. Thank you for all your help :)

Please or to participate in this conversation.