Search code examples
phplaravellaravel-5referrals

How do I call model function on create event? Laravel-5


I'm trying to create a referral url when a user is first created. My function inside my User model looks like this:

private function make_url()
{
    $url = str_random(40);
    $this->referral_url->url = $url;
    if ($this->save()){
        return true;
    }
    else{
        return false;
    }
}

Within the model, I've tried doing this but didn't work

USER::creating(function ($this){
$this->make_url();
})

I also tried calling it in my User Controller within the create user action

public function create(UserRequest $request)
{
$data = $request->all()
$data['password']= bcrypt($request->input('password'));

if($user=User::create($data))
{
  $user->make_url();
}
}

I get this error in return

Indirect modification of overloaded property App\User::$referral_url has no effect

Thanks in advance for your help guys =]

p.s: If there's a better way to go about creating referral urls please tell me.

update

My entire user model

<?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;

    protected $table = 'users';

    protected $fillable = [
                            'first_name',
                            'last_name',
                            'url',
                            'email',
                            'password',
                            'answer_1',
                            'answer_2',
                            'answer_3'
                            ];                           


    protected $hidden = ['password', 'remember_token'];


    public function make_url()
    {
        $url = str_random(40);
        $this->referral_url->url = $url;
        if ($this->save()){
            return true;
        }
        else{
            return false;
        }
    }

    public function user_info()
    {
        return $this->hasOne('App\UserInfo');
    }

    public function sec_questions()
    {
        return $this->hasOne('App\SecurityQuestions');
    }

    public function referral_url()
    {
        return $this->hasOne('App\ReferralUrl');
    }
}

update I modified the function in the model to look like this now.

public function make_url()
{
    $url = str_random(40);
    $referral_url = $this->referral_url;
    $referral_url = new ReferralUrl();
    $referral_url->user_id = $this->id;
    $referral_url->url = $url;
    if ($referral_url->save()){
        return true;
    }
    else{
        return false;
    }
}

When I call

$user->make_url() 

I'm able to create it and it shows up in my db, but I also get the error-

Trying to get property of non-object

Solution

  • Normally the creating method should be called within boot():

    public static function boot() {
        parent::boot();
    
        static::creating(function ($model) {
            $model->foo = 'bar';
        });
    }
    

    This would then be called automatically before the model is saved for the first time.

    The problem that I see with your code is that you're attempting to modify a relation which doesn't exist yet.

    So to explain, the hasOne method will attempt to join the current model to the remote model (in your case a ReferralUrl model) in SQL, but it can't do that before you save your model because your model doesn't exist in the database.

    With your second attempt, the ReferralUrl object is the one that is changing, so that is the one that you need to save:

    public function make_url() {
        $url = str_random(40);
        $referral_url = $this->referral_url
        $referral_url->url = $url;
        if ($referral_url->save()){
            return true;
        } else {
            return false;
        }
    }