0
votes

I'm trying to get a polymorphic relationship working on laravel but every test I make returns either null or ax exception on laravel's pretended SQL query...

FYI: My laravel version is 5.8 running on a MySQLserver 5.7 (WAMP package)

According to what I read on laravel's docs, I think I must use morphTo() in the polymorphic model's class and morphMany() on it's children tables, so I coded like this:

App\Models\Company

public function accounts(){
    return $this->morphMany(Accountable::class, 'accountable');
}

App\Models\Account\Accountable

public function company()
{
    return $this->belongsTo(Company::class);
}

public function accountable()
{
    return $this->morphTo();
}

Migrations:

companies

Schema::create($this->tableName, function (Blueprint $table) {
    $table->bigIncrements('id');
    ...
})

bank_accounts migration

Schema::create('bank_accounts', function (Blueprint $table) {
    $table->bigIncrements('id');
    ...
});

company_has_accounts migration

Schema::create('company_has_accounts', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->morphs('accountable');
    ...
});

Errors:

The thing is: Whenever I try to debug BankAccount::find(1)->company I keep getting:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'company_has_accounts.company_type' in 'where clause' (SQL: select * from `company_has_accounts` where `company_has_accounts`.`c
ompany_id` = 1 and `company_has_accounts`.`company_id` is not null and `company_has_accounts`.`company_type` = Financeiro/Models/Account/BankAccount and `company_has_accounts`.`deleted_at` is null)

and when I try: Company::find(1)->accounts I keep getting an empty Collection.

My objectives are:

App\Models\Account\BankAccount

public function company()

To return a App\Models\Company Object.

App\Models\Account\Company

public function accounts()

To return a collection of mixed "App\Models\Account\BankAccount" and "App\Models\Account\CreditCard" Objects, all belonging to the current App\Models\Account\Company Model, as filtered by the "company_id" column on "company_has_accounts" table.

1
IMHO this question is well written and could have a Reproducible Example, but, it lacks the Minimal part. If you want to learn Polymorphic relationships my advice is to start slim with a fresh project with 2 or 3 models and tables following the examples provided in the docs. Then if you find some problems you can ask here with the minimal code needed. Not everybody here have the time to read all your code and post a "good" answer, considering that it can have more than one issue and no one wants to post a bad answer.dparoli
I see your point, but let's just say that my work environment doesnt allow me to 'waste time' with this sort of things. So with that in mind I decided to write a question as quickly as possible. That's why my code was so badly indented, by the way...Gabriel Cesar
oh, and I appreciate all the help with editing the question! just an update: after some more struggling I managed to get App\Models\Account\BankAccount::company() up and running by calling with('company'). Don't have the code here on my home PC, but I'm getting pretty close. Will update the question with the new codes ASAPGabriel Cesar
I wish you to get a good answer, my point was to post minimal code, so would be easier to give you a correct answer. Your question is written right but with too much code to read for anyone with spare time, I gave the question more tags to give you more views for a possible answer.dparoli

1 Answers

0
votes

After some struggle I managed to get it working. But since I'm new to Laravel I don't know if it's the best approach...

App\Models\Account\Accountable

public function company(){
    return $this->belongsTo(Company::class);
}

public function accountable(){
    return $this->morphTo();
}

App\Models\Account\Company

public function accountables(){
    return $this->hasMany(Accountable::class)->with('accountable');
}

public function accounts(){
    $accountables = $this->accountables();
    $accounts = [];
    if ($accountables->count()) {
        foreach ($accountables->get() as $accountable) {
            $accounts[] = $accountable->accountable;
        }
    }
    $accounts = collect($accounts);

    return $accounts;
}

App\Models\Account\BankAccount

public function accountable(){
    return $this->morphOne(Accountable::class, 'accountable');
}

public function company(){
    $accountable = ($this->accountable())->with('company');

    return $accountable->first()->company;
}