Laravel Illuminate\Database\Eloquent\Collection::createToken does not exist - laravel

After I create a new user I try to create token via
$user = User::where('user_id', '=', $userid)->get();
$user->createToken('name')->accessToken;
Then i got the following error:
Method Illuminate\Database\Eloquent\Collection::createToken does not
exist.
Thanks

You are calling for a collection of users when you use the get() method, which won't have the createToken method (which is exactly what the error message is telling you).
You need to call for a single User model:
$user = User::find($userid);
And then, assuming you have the createToken method on your User model, this should work.
EDIT per comments:
You may have some other issue that is preventing the creation of the token in addition to the original issue of the collection vs an object. Try to create the token first:
$user = User::find($userid);
$token = $user->createToken('name');
Then if you will either get an error (if your createToken method is incorrect, or the parameter 'name' is not correct, etc), or you will have the token, and can then draw the accessToken from the new variable, $token.
Like this:
$accessToken = $token->accessToken
Either way, this will give you the diagnostics to bug hunt.

Related

How to use Auth::login() without real authentication

I would like to use the "Laravel" Auth features.
I have a middleware which finds some data, extract :
$member = $this->memberService->getMemberRolesFromLdap($accessToken, $id);
$member is an array.
Just after this research, I would like to store this $member somewhere to retrieve some data later in some other classes. Like that :
$roles = Auth::user()->roles;
So I thought it was a good opportunity to use these Auth features. But for the moment, I have this error :
Symfony\Component\Debug\Exception\FatalThrowableError: Argument 1 passed to Illuminate\Auth\SessionGuard::login() must be an instance of Illuminate\Contracts\Auth\Authenticatable, array given
So if I understand, I must declare somewhere that $member uses (or is) an instance of Authenticable. And there I admit my limits.
Is it a good idea to use Auth features to do that, and if so, how can I do that?
I tried this. It works, but I am not sure if it is best practice:
$ldapData = $this->memberService->getMemberRolesFromLdap($accessToken, $id);
// login this member
$user = new User();
$user->ldapData = $ldapData;
Auth::login($user);
And now, I can manipulate the user like that:
Auth::user()->ldapData

Laravel - can't get model after deleting related model records

I have a function postShippingmethods in which I delete, update or create new shipping methods depending what the user specified in the form. It works like it should , except that if any methods are deleted, I get empty result when trying to retrieve the user model with the updated methods.
To delete methods, I first get the user:
$user = \App\User::where('id',$id)->with(['shipping_profiles' => function($query) {
$query->where('default', 1);
}, 'shipping_profiles.methods' ])->first();
I compare the stored methods to the ones in the request; if any are missing , they should be deleted.
This code does the deletion:
foreach($non_included_ids as $id){
$method = \App\ShippingMethod::find($id);
$method->suppliers()->detach();
$method->delete();
}
Then I get the user once again, to get the updated data:
$user = \App\User::where('id',$id)->with(['shipping_profiles' => function($query) {
$query->where('default', 1);
}, 'shipping_profiles.methods' ])->first();
^^ this works well if nothing was deleted, but for some reason if something was deleted, the above code will return nothing. And when I try to use the $user to retrieve data I of course get "Trying to get property of non object".
So can anyone explain why this happen and what I should do to get the user with the updated data?
Use a different variable name in the loop:
foreach($non_included_ids as $non_included_id){
Otherwise, the loop changes the value of $id and \App\User::where('id',$id) fetches the wrong user.

Laravel Auth User

In my controller i'm doing
$user = Auth:user()->get();
dd($user);
This is giving me the list of all users from my database.
why?
The other answers either explain how to solve your problem but not properly why this happens.
The laravel documentation states (source):
The get method returns an Illuminate\Support\Collection containing the results where each result is an instance of the PHP StdClass object.
With the full documentation found here, with API references here.
In essence, the get function here returns a collection and not the User object. The get method on an QueryBuilder executes a select statement.
With the following snippet we can see what queries get executed.
DB::enableQueryLog();
Auth::user()->get();
dump(DB::getQueryLog());
This will output:
DB::enableQueryLog();
Auth::user()->where('id', 1)->get();
dump(DB::getQueryLog());
This will output:
The first query will indeed output the expected user, the second query will grab the user class from the Auth::user() and select all rows from that table.
When we execute the 3rd and 4th query we can see that we once more first get the expected user, the 4th query however does also get a user (in this case the user with id 1). This is due too the where and not the Auth::user().
What we can conclude from these results is that the get takes into account all query builder functions but not the parameters of the supplied class.
If you use a get on an object it will only take into account the Class of that Object.
As too solve your problem the other questions where correct and you can use:
$user = Auth::user();
To fetch the user.
Because get return collection
Laravel Doc
Just remove get() to get single user data
$user = Auth:user();
dd($user);
in this case get() method return user collection object
You can auth user data by :
$user = Auth::user(); instead of using get();
Your user id is: {{ $user->id }}
Your first name is: {{ $user->first_name }}
Your last name is: {{ $user->last_name }}
return User::where('id', auth()->id())->with(['something'])->first()

How to retrieve the related model when using create() in laravel

Is there a way to chain the method with and create together?
I have tried to to do something like this and it doesn't work..
return Post::with('User')->create($inputs);
if I use:
return Post::create($inputs)->user();
I'll only get the user not the post.
The last option is:
$post = Post::create($inputs);
return Post::with('User')->find($post->id);
There must be a better way to do it, I guess.
If you will do it like in your example
Post::with('User')->create($inputs);
how do Laravel will know to what exact user attach this new post?
That's why you have do it like this:
// Get your user
$user = Auth::user();
// Create new post
$post = new Post($inputs);
// Attach your post to a user and save it
$user->posts()->save($post);

How to "Refresh" the User object in Laravel?

In Laravel you can do this:
$user = Auth::user();
Problem is, if I do changes on items on that object, it will give me what was there before my changes. How do I refresh the object to get the latest values? I.e. To force it to get the latest values from the DB?
You can update the cache object like this.
Auth::setUser($user);
for Example
$user = User::find(Auth::user()->id);
$user->name = 'New Name';
$user->save();
Auth::setUser($user);
log::error(Auth::user()->name)); // Will be 'NEW Name'
[This answer is more appropriate for newer versions of Laravel (namely Laravel 5)]
On the first call of Auth::user(), it will fetch the results from the database and store it in a variable.
But on subsequent calls it will fetch the results from the variable.
This is seen from the following code in the framemwork:
public function user()
{
...
// If we've already retrieved the user for the current request we can just
// return it back immediately. We do not want to fetch the user data on
// every call to this method because that would be tremendously slow.
if (! is_null($this->user)) {
return $this->user;
}
...
}
Now if we make changes on the model, the changes will automatically be reflected on the object. It will NOT contain the old values. Therefore there is usually no need to re-fetch the data from the database.
However, there are certain rare circumstances where re-fetching the data from the database would be useful (e.g. making sure the database applies it's default values, or if changes have been made to the model by another request). To do this run the fresh() method like so:
Auth::user()->fresh()
Laravel does do that for you, HOWEVER, you will not see that update reflected in Auth::user() during that same request. From /Illuminate/Auth/Guard.php (located just above the code that Antonio mentions in his answer):
// If we have already retrieved the user for the current request we can just
// return it back immediately. We do not want to pull the user data every
// request into the method because that would tremendously slow an app.
if ( ! is_null($this->user))
{
return $this->user;
}
So if you were trying to change the users name from 'Old Name' to 'New Name':
$user = User::find(Auth::user()->id);
$user->name = 'New Name';
$user->save();
And later in the same request you try getting the name by checking Auth::user()->name, its going to give you 'Old Name'
log::error(Auth::user()->name)); // Will be 'Old Name'
A little late to the party, but this worked for me:
Auth::user()->update(array('name' => 'NewName'));
Laravel already does that for you. Every time you do Auth::user(), Laravel does
// First we will try to load the user using the identifier in the session if
// one exists. Otherwise we will check for a "remember me" cookie in this
// request, and if one exists, attempt to retrieve the user using that.
$user = null;
if ( ! is_null($id))
{
$user = $this->provider->retrieveByID($id);
}
It nulls the current user and if it is logged, retrieve it again using the logged id stored in the session.
If it's not working as it should, you have something else in your code, which we are not seeing here, caching that user for you.

Resources