Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

MichaelGrossklos's avatar

save() on polymorphic relation don't work

Hi,

I want to save records for polymorphic tables.

<?php namespace App\Commands;

use App\Commands\Command;

use App\Http\Requests\CustomerRequest;
use App\Http\Requests\UserRequest;
use App\User;
use App\Customer;
use Illuminate\Contracts\Bus\SelfHandling;
use Illuminate\Foundation\Bus\DispatchesCommands;
use Illuminate\Queue\SerializesModels;


class CreateCustomerMemberCommand extends Command implements SelfHandling {

    use SerializesModels, DispatchesCommands;
    /**
     * @var \App\Http\Requests\UserRequest
     */
    private $userRequest;

    /**
     * Create a new command instance.
     *
     * @param \App\Http\Requests\UserRequest $userRequest
     * @param \App\Http\Requests\CustomerRequest $customerRequest
     */
    public function __construct(UserRequest $userRequest)
    {
        $this->user = new User;
        $this->customer = new Customer;
        $this->userRequest = $userRequest;

    }

    /**
     * Execute the command.
     *
     * @param \App\Http\Requests\CustomerRequest $customerRequest
     *
     * @return
     * @internal param \App\User $user
     */
    public function handle(CustomerRequest $customerRequest)
    {
        // TODO: Change UserRequest to an CustomerRequest
        $customer = $this->dispatch(new CreateCustomerCommand($customerRequest));
        $user = $this->dispatch(new CreateUserCommand($this->userRequest));

        return $user->membership()->save($customer);
    }
}

<?php namespace App\Commands;

use App\Commands\Command;

use App\Customer;
use App\Http\Requests\CustomerRequest;
use App\Http\Requests\UserRequest;
use Illuminate\Contracts\Bus\SelfHandling;

class CreateCustomerCommand extends Command implements SelfHandling {

    /**
     * @var \App\Http\Requests\UserRequest
     */
    private $request;

    /**
     * Create a new command instance.
     *
     * @param \App\Customer                      $customer
     * @param \App\Http\Requests\UserRequest $request
     */
     public function __construct(CustomerRequest $request)
    {
        $this->request = $request;
    }

    /**
     * Execute the command.
     *
     * @return void
     */
    public function handle()
    {
        $customer = new Customer;
        $customer->firstname = $this->request->get('firstname');
        $customer->lastname = $this->request->get('lastname');
        $customer->save();

        return $customer;
    }

}

When I dd the $user on CreateCustomerMemberCommand::handle() I get it right. But if I want to save it, I get the following error:


BadMethodCallException in Builder.php line 1992:
Call to undefined method Illuminate\Database\Query\Builder::save()

Don't know what to do.

Thanks

0 likes
11 replies
isaackearl's avatar

Can we see your membership() relationship on the model?

MichaelGrossklos's avatar

Of course:

<?php namespace App;

use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;


class User extends Model implements AuthenticatableContract, CanResetPasswordContract {

    use Authenticatable, CanResetPassword;

    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'users';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['name', 'email', 'password', 'membership_type', 'membership_id'];

    /**
     * The attributes excluded from the model's JSON form.
     *
     * @var array
     */
    protected $hidden = ['password', 'remember_token'];
    
    /**
     * Always hash the password
     *
     * @param $value
     */
    public function setPasswordAttribute ($value )
    {
        $this->attributes['password'] = bcrypt($value);
    }
    
    /**
     * Creates an polymorphic relationship for Lenicura, Employees, Customer and Partner
     *
     * @return \Illuminate\Database\Eloquent\Relations\MorphTo
     */
    public function membership ()
    {
        return $this->morphTo();
    }

}
<?php namespace App;

use Illuminate\Database\Eloquent\Model;

class Customer extends Model {

    protected $fillable = ['firstname', 'lastname'];

    public function user ()
    {
        $this->morphOne('App\User', 'membership');
    }

}

I don't think it's a relationship problem. But who knows ;)

JarekTkaczyk's avatar
Level 53

@MichaelGrossklos There's no save on belongsTo and morphTo - these are child relations, so you need to have the parent saved, before you can create such relationship with associate. Like this:

$customer->save();
$user->membership()->associate($customer);
1 like
MichaelGrossklos's avatar

For all struggling with that, heres what I've changed:

Instead of using User::create() I do this:

 private function createUser ()
    {
        $user = new User;
        $user->name = $this->request->get('name');
        $user->email = $this->request->get('email');
        $user->password = $this->request->get('password');
        $user->save();

        return $user;
    }

And then simply follow @JarekTkaczyk suggestion:

 /**
     * Execute the command.
     *
     * @param \App\Http\Requests\CustomerRequest $customerRequest
     *
     * @return
     * @internal param \App\User $user
     */
    public function handle(CustomerRequest $customerRequest)
    {
        $customer = $this->dispatch(new CreateCustomerCommand($customerRequest));
        $user = $this->dispatch(new CreateUserCommand($this->userRequest));

        return $user->membership()->associate($customer);
    }

It works. Thx

JarekTkaczyk's avatar

@MichaelGrossklos Well, I might have been not precise enough :)

associate doesn't update anything, it just sets the FK and the relation on the object. That said, after associating you still need to save the child model, a user in your case.

4 likes
MichaelGrossklos's avatar

Ahhh ok. Makes sense ;) Thanks. Because of Behat problems I'm not in the situation to test it right now, but I will!

MichaelGrossklos's avatar

@JarekTkaczyk Nope, seems not be the case:

public function handle(CustomerRequest $customerRequest)
    {
        $customer = $this->dispatch(new CreateCustomerCommand($customerRequest));
        $user = $this->dispatch(new CreateUserCommand($this->userRequest));

        $user = $user->membership()->associate($customer);
        $user->save();

        return $user;
    }

User gets created but no relation.

MichaelGrossklos's avatar

@JarekTkaczyk Sorry, found it. Was my foult. Was a problem with the controller. Anything is working like you suggested. But to answer your question: yes I do. Thanks again!

Please or to participate in this conversation.