0
votes

I am using Laravel 5.3 and I want to send verification mail using the following

php artisen make:auth
php artisen make:mail ConfirmationEmail

ConfirmationEmail.php

<?php

namespace App\Mail;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;

class ConfirmationEmail extends Mailable
{
use Queueable, SerializesModels;

/**
 * Create a new message instance.
 *
 * @return void
 */
public $user;
public function __construct(User $user)
{
    $this->user = $user;
}

/**
 * Build the message.
 *
 * @return $this
 */
public function build()
{
    return $this->view('emails.confirmation');
}
}

emails/confirmation.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Sign Up Confirmation</title>
</head>
<body>
  <h1>Thanks for signing up!</h1>

  <p>
    We just need you to <a href='{{ url("register/confirm/{$user->token}") }}'>confirm your email address</a> real quick!
</p>
</body>
</html>

UserController.php

public function register(Request $request)
{
    $validator = Validator::make($request->all(), [
        'email'         => 'required|email|unique:users',
        'name'          => 'required|string',
        'password'      => 'required|string|min:6',
        'country'       => 'required'
    ]);
    if ($validator->fails()) {
        return response()->json(['error'=>$validator->errors()], 401);
    }
    $input = $request->all();
    $input['password'] = bcrypt($input['password']);
    $input['user_pin'] = $this->generatePIN();
    $user = User::create($input);
    Mail::to($user->email)->send(new ConfirmationEmail($user));
    $success['token'] =  $user->createToken('MyApp')->accessToken;
    $success['user']  =  $user ;
    $now      = Carbon::now();
    UserLocation::create(['user_pin' => $input['user_pin'] , 'lat'=> 0.0 , 'lng' => 0.0 , 'located_at' => $now]);
    return response()->json(['success'=>$success], $this->successStatus);
}

Models/User.php

<?php

vnamespace App\Models;
use App\User as BaseUser;

class User extends BaseUser
 {

  /**
  * The attributes that should be hidden for arrays.
  *
  * @var array
  */
  protected $hidden = [
    'password', 'remember_token',
  ];


  public function groups(){
    return $this->belongsToMany(Group::class, 'group_member', 'member_id', 'group_id');
  }

public function sentRequests(){
    return $this->hasMany(Request::class, 'from_user_pin', 'user_pin');
  }

public function receivedRequests(){
    return $this->hasMany(Request::class, 'to_user_pin', 'user_pin');
  }

public function locations(){
    return $this->hasMany(UserLocation::class, 'user_pin', 'user_pin');
  }
}

App\User.php

<?php

namespace App;

use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;


class User extends Authenticatable
{
 use HasApiTokens, Notifiable;


protected $guarded = ['id'];

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

/**
 * The attributes excluded from the model's JSON form.
 *
 * @var array
 */
 protected $hidden = [
    'password', 'remember_token',
 ];

}

I am now getting this error

ErrorException in Model.php line 2709: Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation (View: /var/www/html/group_map_v1/resources/views/emails/confirmation.blade.php)

2
is token a method on that model? - lagbox
I've answered your question below. If you still not able to fix this, please show User model. - Alexey Mezenin
@lagbox No token not a method it a just a field in the users table - Peter Wilson
the error seems to think otherwise ... provide your user model as that is the relevant part - lagbox
a User model does not have a createToken method by default, so this isn't a default User model that comes with Laravel - lagbox

2 Answers

2
votes

token is a method on the model. When you try to access the dynamic property on the model, it looks for an attribute then for relationship method (or already loaded relationship) by that name.

You have no attribute named token. When you try to access it via the dynamic property it looks for a method named token (this is how it can access relationships via that property). When it does this it hits that method and that method does not return a relationship type object. So Eloquent breaks at that point as that property is for attributes and relationships, and it can't do anything with it.

asklagbox - blog - eloquent misunderstandings - dynamic properties and relationships

1
votes

You're getting this error, you're trying to use a model method as a relationship, but this method doesn't return one. The relationship should look like this:

public function relationship()
{
    return $this->hasMany(Model::class);
}

Update

HasApiTokens trait has a method named token() which is a simple accessor:

public function token()
{
    return $this->accessToken;
}

When you do $user->token, Laravel sees this method and trying to use it as a relationship.

So, what you want to do is to rename your token property in the users table to something else.

Thanks to @lagbox for the pointing in the right direction.