WEBVTT

00:00.770 --> 00:07.010
Now, if you remember this diagram from the beginning of the project, one of the things related to

00:07.040 --> 00:11.030
database that I wanted us to create is a model class.

00:11.030 --> 00:18.110
This would abstract not the whole database, but instead it would relate to one single table.

00:18.140 --> 00:25.280
So you can create a model that will represent the post, the comment and the user.

00:25.310 --> 00:32.450
The reason for that is typically you might have to write some more complex queries and that's fine.

00:32.450 --> 00:33.950
That's a separate problem.

00:33.980 --> 00:37.460
But a lot of those queries are super simple.

00:37.460 --> 00:46.640
You just fetch one individual record or you fetch all of them, or you just need to count the models,

00:46.640 --> 00:50.600
or you need to create a new record or update it.

00:50.600 --> 00:58.220
And for those cases, it would be super useful to have a generic model class that can do all of that

00:58.220 --> 01:06.340
without us Having to write the same queries over and over again for every single table that we have

01:06.340 --> 01:09.010
and we might have in the future.

01:09.010 --> 01:17.770
That's why in this video, we are going to create this base model class that all the future models that

01:17.770 --> 01:20.080
we're going to have will use.

01:21.640 --> 01:26.350
So our model class will heavily use this database class.

01:26.350 --> 01:30.310
It's going to get access to it through the container.

01:31.330 --> 01:33.130
Let me close the database for now.

01:33.130 --> 01:37.120
And inside the core let's create the model.

01:37.360 --> 01:38.350
PHP file.

01:38.650 --> 01:44.290
And this time I'm not gonna forget the core namespace.

01:45.520 --> 01:47.920
So this is our class model.

01:47.920 --> 01:51.280
And I think that this should be an abstract class.

01:51.280 --> 01:53.470
It should not exist on its own.

01:53.470 --> 01:55.960
It only needs to be extended.

01:57.310 --> 02:04.600
So we add a protected field that is static and it's a table name.

02:04.600 --> 02:11.350
So every model that extends this base model class would have to define the table name.

02:11.350 --> 02:15.160
That can be posts, users or comments in our case.

02:16.090 --> 02:23.650
So I think that it would make a lot of sense if I would begin this by defining the names of methods

02:23.650 --> 02:26.020
that this model would have.

02:26.890 --> 02:32.350
So let me start with the public ones and they are static.

02:32.710 --> 02:41.410
So we're going to have an all method which will just return all instances of this model.

02:41.650 --> 02:44.470
And that's always an array.

02:44.500 --> 02:46.990
Now I'm not going to implement it right away.

02:46.990 --> 02:53.350
I'm just defining those methods methods first so we can see what's the generic idea.

02:53.380 --> 02:56.230
Then we have a find method.

02:56.230 --> 03:02.910
And this accepts an id I think it should be mixed because it can be a number.

03:02.940 --> 03:09.750
Sometimes we also might use strings as primary keys, so we shouldn't be limited here.

03:10.500 --> 03:15.330
And this should return an instance of our model class.

03:15.480 --> 03:22.410
So I will define this as static or null if the model can't be found.

03:22.410 --> 03:29.100
But then we should also have some shortcut methods to quickly create a new model.

03:33.240 --> 03:35.580
So this would just be called create.

03:36.000 --> 03:42.060
And this is going to accept the array with the data with all the fields.

03:42.060 --> 03:46.470
And this should create an instance of this model.

03:46.470 --> 03:49.020
I'm using static as the return type.

03:49.020 --> 03:56.550
Because once we extend this base model class, this return type would have the proper class type.

03:56.550 --> 04:03.900
So it would be a specific model like post comment or a user, not the model class.

04:05.550 --> 04:10.830
So why won't we just go ahead and implement those methods starting with all?

04:10.920 --> 04:13.680
Now we need to get the database first.

04:13.710 --> 04:19.620
For that we're going to be using the app class, our dependency injection container.

04:20.520 --> 04:27.300
Now here is a thing in PHP, if you have classes at the same level of the namespace, you don't need

04:27.300 --> 04:34.290
to add use statements for them and model and app seem to be at the same level.

04:34.320 --> 04:41.910
That's why I can just do app get and I get the database.

04:41.910 --> 04:48.660
Now remember I told you that we won't have the suggestions with the methods of the database class,

04:48.690 --> 04:51.840
but we are going to fix that later.

04:51.840 --> 04:58.370
In the meantime, let's have the results by doing the DB query.

05:00.230 --> 05:10.400
And we're just going to select all columns from the specific table which is just static table.

05:10.970 --> 05:12.050
That's everything.

05:12.080 --> 05:14.750
This method is this simple.

05:14.750 --> 05:19.970
And we're going to do fetch all because this returns a statement.

05:20.210 --> 05:29.240
And then we're just going to say that using PDL we want to fetch that as an associative array.

05:30.050 --> 05:37.550
Let's make sure I got this PDL object imported because this one actually has to be imported.

05:38.390 --> 05:44.480
Now the problem with this is that we're going to get an array an array of arrays.

05:44.480 --> 05:47.420
So this would be a multi-dimensional array.

05:47.420 --> 05:53.930
And what I'd like instead is to have an array of objects.

05:53.930 --> 06:02.590
So every single time we use the model to fetch the data we wanted returned us this model class.

06:02.590 --> 06:04.870
So as a post or as a comment.

06:05.440 --> 06:12.520
Now this is not easily doable if we want to fetch multiple records.

06:12.520 --> 06:18.490
That's why we would need a helper method that we're going to make it protected.

06:18.700 --> 06:26.830
And I will call that create from array.

06:27.940 --> 06:34.480
And this receives an array data and returns static.

06:34.480 --> 06:37.300
So the current model we are working on.

06:38.530 --> 06:45.130
So we're going to be creating a new instance of static which means the current class whatever that is

06:45.130 --> 06:47.200
post comment user.

06:47.230 --> 06:50.620
Because this class always has to be extended.

06:51.610 --> 07:01.930
Then we're gonna go over the data which should be keys and values because that's an associative array.

07:02.380 --> 07:07.330
And then if the property is defined on the model.

07:07.570 --> 07:13.840
So there is this property exists function in PHP which accepts object or class.

07:14.290 --> 07:19.960
Well we have an object and the name of the property is the key.

07:20.230 --> 07:27.700
So if that's the case, if this property is defined I seem to forget to ask you what here.

07:27.700 --> 07:34.390
So if it is defined we just do model key.

07:34.420 --> 07:39.760
So we dynamically calculate the property name by using a variable.

07:40.120 --> 07:42.730
And we set that to value.

07:44.410 --> 07:47.290
And then we return a model.

07:47.320 --> 07:58.350
Now in the model PHP versions since PHP 8.2 I think you shouldn't really set the properties on classes

07:58.350 --> 07:59.340
dynamically.

07:59.340 --> 08:01.590
That was previously a feature of PHP.

08:01.740 --> 08:10.350
Now, if you use an object of a specific class, you have to define the properties explicitly.

08:10.350 --> 08:12.000
So this is deprecated.

08:12.000 --> 08:19.530
And if you would try to set the properties dynamically without them being explicitly defined on the

08:19.530 --> 08:23.400
class, this would cause a notice or warning.

08:23.400 --> 08:25.710
We're going to see that later on.

08:25.740 --> 08:35.610
Anyway, we need to use this method to now convert an array of arrays into an array of objects.

08:36.390 --> 08:44.100
So now we would like every single record of data that sits inside this results array to be converted

08:44.100 --> 08:45.330
to an object.

08:45.330 --> 08:52.200
And for that we're going to use our newly created create from array method.

08:53.400 --> 08:57.380
Now to convert every single record that is returned.

08:57.380 --> 09:06.200
Because this is results variable with multiple possible results, we can use an array map.

09:06.230 --> 09:08.360
This can be done different ways.

09:08.360 --> 09:15.170
We can also use a for each loop, but I think the array map makes the most sense.

09:15.200 --> 09:17.360
Let me start with the second argument.

09:17.360 --> 09:20.180
This would be the results array.

09:21.020 --> 09:25.010
And now going back to the first argument, this needs to be a callback.

09:25.040 --> 09:27.380
But here we don't have a function.

09:27.380 --> 09:31.490
We have a class method that is static.

09:32.090 --> 09:40.340
To parse it, we're going to use an array where the first element of the array is the name of the class.

09:40.370 --> 09:48.740
Now, to get the name of the current class, we can use the static keyword and it should have a class

09:48.740 --> 09:49.670
constant.

09:49.700 --> 09:57.890
Every class has this special constant that will give you the full class name, including the namespace,

09:58.550 --> 09:59.870
and after a comma.

09:59.900 --> 10:02.150
The second element is the method name.

10:02.690 --> 10:05.960
In our case, that's create from array.

10:06.290 --> 10:13.520
Now this is actually an important thing to remember that every single time you need to pass a method

10:13.520 --> 10:18.530
of a class, like in this case that's a class method.

10:18.560 --> 10:27.260
Or if you would need to pass a method of an object, then this first element of the array can be a variable

10:27.260 --> 10:28.610
with an object.

10:28.790 --> 10:38.390
And that's the way you can use if you pass a callback that is just a part of a class or a method, not

10:38.390 --> 10:40.040
a simple function.

10:41.420 --> 10:45.410
Okay, next up, let me build this find method.

10:45.410 --> 10:49.100
It would be pretty similar to the all method.

10:49.880 --> 10:52.790
There are of course some slight differences.

10:53.050 --> 10:57.970
That's why I'm just gonna copy and paste some of the code.

10:58.180 --> 11:02.860
So in the find method, we expect just a single result.

11:03.130 --> 11:07.300
We can still use this database query method.

11:08.020 --> 11:12.160
We're gonna select a record from the same table.

11:12.160 --> 11:13.360
This stays the same.

11:13.360 --> 11:16.390
But here we need some filters.

11:16.420 --> 11:21.700
That's why we are adding a Where clause to specify some conditions.

11:22.210 --> 11:28.150
In our case this is an ID and we're going to use prepared statements.

11:28.150 --> 11:34.660
That's why I'm going to add a question mark here for the positioned query arguments.

11:34.660 --> 11:36.910
And then I can pass the ID.

11:37.180 --> 11:44.350
So when you are using those question marks in prepared statements the order of them matters.

11:44.350 --> 11:48.880
Because then you just need to pass the parameters that you want to pass there.

11:48.910 --> 11:51.340
In the same order.

11:51.640 --> 11:57.670
So in this case, we will be using just a fetch method to get one record.

11:58.000 --> 12:06.040
Well, we can also use PDO fetch as sock to fetch the data as an associative array.

12:06.070 --> 12:07.900
Just a single record.

12:07.900 --> 12:14.350
And then we return the result depending on whether the result is not null.

12:14.830 --> 12:23.110
So if it is not null, we're going to use the static create from array method on the result array.

12:23.140 --> 12:25.240
Otherwise we return null.

12:26.650 --> 12:33.940
Now the last thing remaining so far is this create static method that will just insert one record into

12:33.940 --> 12:34.930
the database.

12:34.960 --> 12:43.030
Now this might take some time to implement and also explain, because we need to go in more details

12:43.030 --> 12:46.330
into how the insert SQL query works.

12:46.330 --> 12:52.300
That's why I think we should take a short break right now and just go back to it in the next video.
