Okay, so last time I've mentioned that the remember token needs to be rotated.
And this just means that once we use such token, we should replace the token value and extend the expiry
date.
Now those tokens that we set for let's say 30 days, they are fine to use.
But the problem is that if they end up in the wrong hands and anyone will just get access to the value
of this token, it would be super easy for a person that gets his hands on the token to just use it
to take over an account, and that's the reason we should be replacing the value of the token every
single time we use it.
Just for the security purposes.
So let me start here by adding a method.
This time it would be a method that is on the object instance, not a static one.
And it's to be used when we have a loaded token can be just called rotate and it can return itself,
meaning this remember token instance.
That's why we use this keyword.
And we'd like to replace the token.
So we're gonna generate a new one.
Then we also would like to get the new expiry date.
That's why we'll also generate a new one.
And we return this.
Okay.
So we can do that.
We can change the value of the fields But it doesn't mean that this data will be stored in the database.
So currently we represent the records from the database through instance of classes like this.
Remember token object.
But there is no way for us really to save changes easily.
We've got a create method that is static, but it requires the input to be an array.
And this means that we should really add the model method that can get all the fields from the model,
which we have to define anyway, and just try and perform a database query.
And I'd like it to be able to do two things.
One, if the ID column has a value, then it needs to perform an update just updating the values of
other columns.
But if the ID is not specified, this means that certain entity model wasn't saved yet doesn't have
a record in the database.
Then we need to perform an insert and models should just have a save method.
That's something also present in Laravel, where you can just save a class and it will know whether
it needs to insert or update a record.
So this method does not exist, which means we need to jump to the model and implement one.
And this is what we're gonna do right now.
So this is public function.
Save.
And it might return the current model.
So here's what we can do.
The first is to get the database object using the application container.
And another step is to get the values of this current object fields, which can be done using get object
vars.
A little handy function that when you pass an object to it, it will give you all the fields of that
object and also the field values, and it will return an array.
So it returns an associative array with all the defined object.
Non-static properties exactly what we need.
We only need the instance properties, not static ones.
And by having this, we can now check if the id is set on this model because if it's not, it means
this database record doesn't exist in the database.
So our first step in this case would be to remove the value of id, which would be null anyway.
And we can just return the call to static create passing the data.
So as a quick reminder this create is a method a static method in the model which from the given associative
array constructs an insert query.
And then we just have an alternative.
So if the ID is actually set then we need to perform an update.
So in this case we also would have to remove the ID from the data.
Then we need to construct the SQL.
So we've already used the update statement.
So we write update followed by the table name which we're going to read from this static property.
This is followed by the set keyword.
Then we need to say which columns we update and with what values.
So let me assume this would be somewhere over here.
But then eventually since we are updating one specific record, we need to make sure we add an if statement.
So the where statement.
And we pass the ID of the model that we want to update.
Then we need to grab all the values that should be updated because we are making a prepared statement.
So we use array values from the data.
And the last parameter is this one.
That's the last question mark in the query.
That's why to the parameter we need to append the value of this class this object id.
And now we can run the database query using this SQL and the values.
And we just return this object.
So the thing missing is constructing this part.
What to update and how.
Let me call this set parts.
And let's use array Map.
So we're going to go over the keys from the data.
That's why I'm getting the array keys from the data.
Basically we're going to get all the column names except ID which we have just removed.
Okay.
And next up let me add an arrow function.
So with every key or rather column I'm going to construct an SQL part where I'm going to do column equals
question mark which basically stands for prepared statement parameter.
Now remember that those prepared statement parameters when you use question marks you just pass them
in order.
And this is also why we had to add the id as the last parameter.
Because values is essentially the parameters.
I might even call this params.
So maybe this would be a little bit more understandable.
And this place here is where we should add the set parts.
So set parts is an array.
And this is why we should convert it to a string.
We can do that using PHP implode where the separator is a comma.
And here we pass the set parts.
Maybe I can reformat this so it would be more readable.
What are the specific parts of the query that we are using.
So we are updating a table using set here we've got those columns equals a placeholder for parameter.
We implode.
So we generate a string from an array.
And last we've got this where statement to just make sure we just update this single model, not anything
else.
Okay, let me move that to multiple lines.
So the editor does not like that we use a property that is undefined.
Now I think we can assume that we will always going to have the ID property on the model.
This is basically the assumption that we create.
So that's something that we force that every database needs an ID column.
By the way this is not used.
So this can be made configurable.
But we try to keep things simple and manageable.
That's why we had to make some assumptions.
So by adding this field it no longer complains that it is undefined.
So I hope this is understandable.
It might go through this again.
So we get the database.
We get the values and names of all the fields on an object, all the public properties that are non-static,
which is what we want because those are columns on our model.
ID is not set.
This means we can just use create and insert a new record.
Otherwise, we need to construct an SQL query that will perform an update.
We collect the prepared statement parameters because we never want to just run raw SQL without the prepared
statements.
Not to be vulnerable to SQL injection, we add the ID as the last parameter because we know it is the
last parameter.
Here we run it and we just return the object itself.
Do this.
Now if we jump back to our remember token, we just can be sure that this token rotation will just work.
Save will always, in our case, perform an update because we only rotate a token that has an ID.