[Seminar] [Kohana: A Lightweight PHP Framework]
[Brandon Liu] [Harvard University]
[This is CS50.] [CS50.TV]
>> Hi everyone. My name is Brandon.
I'm a junior here at the college doing computer science, and today we're going to talk about
Kohana, which is a PHP web development framework.
Today is going to be a live coding seminar,
so I'm basically going to spend 5-10 minutes explaining what Kohana is,
and then I'm literally going to build a super simple blog
for you right here literally from scratch.
We're going to download the code from the Kohana website,
and we're going to start building a blog, and hopefully it'll be very instructive,
because you'll see perhaps maybe I'll make some mistakes,
and you'll see me recover from them,
or you'll see my thought process as I build through this blog,
and meanwhile, you'll also get familiar with the framework itself.
Hopefully it'll be a very instructive exercise.
>> First, what exactly is a framework?
If you've been taking CS50 so far, you haven't really worked with any
frameworks yet, and the thing is this.
You've probably done 1 web development pset already,
and let's say you continue to build websites and keep building websites.
You'll start to notice a few things.
The first thing you'll notice is that you're probably doing the same things
over and over again all the time,
things like cleaning user input data,
things like organizing your files in a certain way.
The other thing you'll also probably notice is that your code
may start to become very, very messy,
and you may leave it messy and just have a very hard time maintaining it,
or you may start to structure your code and making it modular
in certain ways to make it more maintainable.
>> This is where web frameworks basically came in.
These people who had built a lot of websites, they said,
"We don't need to redo this every single time we build a website."
"Why don't we just make a package that does all these things for you
every single time you want to build a website?"
And so that when you make a new website,
you just focus on what exactly this particular website is about.
You don't need to repeat all the various configuration
and separation of codes and rewriting code
that you often have to do when you're making websites.
The idea is that a framework allows you to write a higher-level code
without having to worry about lower-level details.
A lower-level detail might be something like
dealing with cleaning user input data.
That's something that you shouldn't really need to worry about.
You should focus on what your web allocation is actually about.
It eliminates a lot of boilerplate code.
It is an architecture for your project.
>> The most popular one would be Model-View-Controller,
which I'm going to talk about in a second.
And a lot of times these frameworks embody a set of procedures,
rules, and best practices for you to use
so that when you adopt the web framework
you have to write your code in a certain way,
and it's generally an agreed upon set of principles
by the community that is generally accepted to be
a good way of writing code.
It makes your code more maintainable, more usable,
so on and so forth.
And finally, the thing I want to emphasize about frameworks
versus libraries is this idea about inversion of control, and the thing is this.
The difference between a library and a framework is that with a library
you are still writing the main program,
and you're sort of invoking the library
and calling upon the library to do something for you.
The difference between a library and a framework
is that the framework starts out with the control,
and it invokes your code,
so you can think of it as--this is why it's called a framework--
the framework provides this frame and structure for your code,
and you fill in the holes,
and this will become more apparent in a second
when you see me start to write code within the context of the framework.
You'll see that I'm filling in the gaps,
and the framework is kind of controlling all the moving pieces,
and I have to put the pieces in the right places.
>> Today we're going to talk about Kohana,
which is one of many PHP frameworks.
There are web frameworks, and there are ones in virtually every single language,
and I'm picking Kohana because Kohana is arguably
and generally recognized as the easiest PHP framework to pick up.
It's the most lightweight.
There are other ones out there that come with many, many more features,
but they tend to be more difficult to pick up.
And finally, Kohana uses the MVC architecture.
It's lightweight enough that we can literally build a project
right here right in front of your eyes, and you can pretty much
follow along pretty easily.
>> What is the MVC architecture?
It stands for Model-View-Controller,
and maybe if you think about the code you've been writing so far
for some of your web development psets
you may be able to see some of this, but usually when you start writing
a more complex web application,
the division between these 3 segments becomes more and more evident.
I laid out the MVC here sort of as a stack,
and often you'll hear people talk about stacks in web development,
and this is to illustrate the idea that
each layer, each component really tries to only communicate
between 2 other components.
Someone accesses your website as a client or a browser.
They interact with your program through the view code.
The view code interacts with the controller.
The controller interacts with the model,
and the model interacts with the SQL database.
And there is no hopping in between if you write your code properly.
>> What do these things do?
The model essentially is the piece of code that deals with your data.
Anything that deals with your database, with the objects that you store,
or retrieving those objects in the database,
that's all handled by the model.
Maybe you have objects in your database.
We're going to create a model having to do with posts,
so a post may have some attributes to it.
You may have functions around storing those posts or retrieving posts
or filtering the posts and so on and so forth,
and that's all the code that's handled by the model.
The controller is sort of the application logic,
and a lot of different things can go in the application logic.
If you're talking to a different API,
that may be where you're dealing with the application logic.
If you're trying to have to bring in data from multiple different models
and have to combine them in some way, that often may be handled by the controller.
For example, on Facebook, if you friend someone,
then perhaps that act of establishing that relationship
may be done by the controller.
>> And finally, the view is the code that's generating what you actually see.
A lot of times I think in the CS50 psets
they don't really encourage you guys to separate these 3 things.
You'll probably have this big, long file where at the top
you make some SQL query and maybe do some processing
on the data you retrieved from the database,
and then you have all your HTML at the bottom.
And you may find that as you create more and more pages
that you're going to have some code repetition, and also,
the thing is your file gets really big and long
and becomes unwieldy to manage.
The reason why MVC is so well regarded
is for a number of reasons.
The first thing is something called separation of concerns
which is the idea that when you have--
ideally 1 piece of code should do 1 thing and do it really well,
and you shouldn't combine pieces of code that do disparate things.
For example, view code and model code,
they don't really have to be related.
They don't have to be in the same files, so when you can, separate them out
so it's easy to maintain.
>> The other thing is code reuse.
You may find yourself writing the same SQL query or doing
similar queries that could be abstracted into 1 function,
and that's the idea behind models and controllers,
having it in a separate function that you can reuse in different places in your project.
And finally, that's tied to DRYing your code,
or not repeating yourself, don't repeat yourself.
This is very comprehensible in development.
Whenever you can, you don't want to repeat yourself, because if you repeat yourself,
it's much more costly to maintain.
If you want to change 1 thing, you have to change it everywhere,
and that leads to bugs, and it's horrible.
>> All right.
Any questions so far about Kohana at all?
Great.
Now we're going to dive into the live coding session,
and hopefully everything goes well.
I am going to basically build this website
on one of my remote servers, and that way you guys can also
see the website and access the website,
and also the environment is better configured than my remote machine,
because it's running Linux instead of OS X.
We're literally going to start.
KohanaFramework.org.
I'm going to download the code from the website.
I'm going to copy the link address,
go to my server, download it,
and I'm going to extract it.
>> [Student] What's the largest you can make the text?
[Brandon Liu] Is that better?
[Student] Is that doable?>>[Brandon Liu] Yeah, that's fine.
I downloaded a ZIP file and unzipped that into a directory called Kohana,
and we're going to rename that CS50-Kohana,
and let's go in.
Awesome.
Here you see a bunch of different files.
Most of you can ignore--we're not going to go through every single file that's in here
because of our time constraints,
but generally when you install Kohana, the first thing you do
is you go to the directory,
and you'll basically do some environment tests and whatnot
to make sure your environment is properly set to run Kohana
and make sure that everything is all right.
You can see most things passed, but generally you always run into this 1 problem
where it complains that some directory is not writable,
and that's because of some permissions.
I don't know how much you guys have learned about file permissions in CS50,
but if you do web development, you're going to run into this issue a lot.
I'm going to make it writable
and I think I also have to--there we go.
>> Okay, so now you can see everything passed,
and now it will tell you to rename the install.php file.
I'm going to move the install.php file to installed.php,
and now if I refresh,
it gives me some error, and this is where the debugging comes in.
This is where you can see what's actually going to happen.
The thing is, by default, Kohana assumes that
your project is at the root directory of your domain,
so it's expecting you to be at demo.brandonkliu.com.
We have to tell it that it's actually in a subfolder.
It's in a subfolder called CS50 Kohana.
The thing is, it's misinterpreting CS50-Kohana
as something else, which I'll explain to you in a second.
But I should tell you that's something that's to be expected.
What we're going to do is we're going to go into this folder called bootstrap.php,
which is the configuration folder where a lot of different things are set up.
I open that up.
Then maybe one of the first things I'll do is change the time zone.
>> And then let's see.
Aha! Right here.
There are a bunch of different configuration sayings in here,
but the one I'm looking for is this thing called base URL,
and by default I get it set to Kohana,
but I'm going to change that to CS50-Kohana,
and I think that should fix it.
Yes, great.
By default, to see that it's working, it says, "Hello World."
Where did that come from? How did we get to Hello World?
Where exactly is the code that actually wrote that?
To understand that, I'll introduce this concept called routing.
Pretty much all web frameworks have the concept called routing,
which is the piece of the software that will map a certain URL
to a certain piece of code within your framework.
For example, if you have some URL and you go to some URL like foo.com/blog/all
then what the framework is going to do--or at least what Kohana is going to do--
is it's going to find a class called controller blog,
and it's going to run the function named action all.
I know I'm talking about class and functions,
and I know you guys haven't covered classes and functions
in CS50 yet, but for now,
you can think of classes as just a group of functions,
a way of grouping functions together.
That's really all you need to know.
>> Now if we look at our folder structure,
inside the application folder there is another folder called classes,
and the other folders are called Controller and Model.
If you look inside the Controller folder,
we see that there is a file called Welcome,
and you can see here is a class called Controller Welcome,
and there is a function called Action Index,
and what it does is it sets the body of your response to Hello World.
That's where the code is being written.
The other question is, well, I didn't go to
blah, blah, blah, /welcome/index.
How did I end up here?
Well, that's simply because
here at the bottom of our bootstrap file
where we set our routes
you can see that they set some defaults for you.
The default controller is Welcome. The default action is Index.
That's why when we put nothing in there it automatically went to the Welcome controller
and the index Action.
>> Everything make sense so far?
Now, you can do more than just go to Controller
and a specific action.
You can also pass in parameters to the controller.
Just as an example,
I'm going to add another action to this controller to show you.
Let's call this action Echo, because it's going to tell you whatever you give it,
and so I'm basically going to grab
a parameter that's going to be sent through me to the routing program,
and as you can see here,
this line right here, you can see that
this basically means you have controller, and you have a /,
and you have action, and you have another /,
and that's going to be parameters, and because we have this name ID
within angle brackets, that means that we're naming this parameter ID.
Later in my controller code if I want to grab a hold of that parameter,
I can use the code I wrote, find the parameter named ID.
That's what I did here, and I'm going to return and say,
"You said" that.
And so now if I go to our website,
I go to cs50-kohana/welcome/echo/Helloooo--
oh, that's right.
There is 1 step I left out.
This is part of the live coding idea.
>> Here's 1 thing. Let's see.
So normally by default with a lot of these web applications
you have to include this index.php thing in your URL,
because the idea is index.php is sort of the entry point
of your application, but of course,
that's sort of annoying to have.
You don't want to have index.php appear in your URL,
and pretty much every web framework out of the box
has this index.php problem,
and so you have to take some measures to be able to remove that.
And so in this case,
what we're going to do is we're going to use a file called .htaccess,
and this is something that's specific to the Apache web server,
and it can do things like rewrite URLs
and redirect URLs and so on and so forth,
and Kohana is nice enough to provide a template .htaccess file that we can use.
>> As you can see, there is a file there called example.htaccess,
and we're going to copy that to .htaccess.
I'm going to open this and edit it,
and basically it does a bunch of different things.
The key line you may want to look at is right here.
The idea is that this sets up a rule that says,
"Okay, whatever you type in, prepend index.php to that."
You can see that.
The .* stands for anything, match anything,
and then the second part is index.php/$0,
and $0 refers to whatever was matched previously.
Does that make sense?
But the really key thing I want to change is change this rewrite base,
which is the URL base.
It sort of assumes where you're working from.
I'm going to add CS50 Kohana to that,
and that way now if I remove the index.php,
it should work, and I'm going to add some numbers
to show you that it indeed did work.
Sounds good.
>> Any questions so far?
[Student] How did it know to make the 123?
Is that an argument?
Exactly. You can think of it just like an argument.
But the weird thing, though, is that the way Kohana does it
is they don't do it exactly like an argument.
You have to grab it like this.
You have to grab the request object and ask for the parameter that's named ID,
and that name ID comes from that bootstrap file
that I showed earlier, and the name ID was in those angle brackets,
and that's how you grab those parameters.
Awesome.
Any other questions?
Like I said, controllers, they handle application logic,
so that's 1 instance where you can see that's--
it's very basic, but it's still application logic,
the idea of grabbing the parameter and creating a new string
that says, "You said blah," and then spitting that back to you.
And generally what you do is you create different controllers.
You create separate controllers for different parts of your website.
>> Today we're going to make a very simple website,
and it's going to be a very basic blog.
We're going to make a new controller just for the posts in a blog.
But then if I were to also add comments to the blog post,
then I would probably want to make a new controller for those comments.
If I wanted to add users, I would probably add a new controller for those users,
and in general, the idea is that whenever you have a new model,
a new data object that you're dealing with,
you have a single controller for that data object.
Today we're only going to work with 1 data object,
and that's going to be posts,
and also you can think of data objects as corresponding to tables.
Generally each table corresponds to 1 type of data object,
so the post table will have 1 post model,
which will have 1 post controller corresponding to that,
and the same for comments, the same for users, and so on and so forth.
And that's a general rule of thumb.
There are going to be special cases where you may differ from that,
but 90% of the time that's what you're going to be doing,
and I'll show you that's what we're going to be doing today.
1 more concept before we dive back into the code,
this idea of object relational mapping.
>> You guys have already done a web development pset,
and you've seen that you make an SQL query,
and whatever it returns to you are rows.
You get these rows, and you index them by some name,
the name of the column and the table,
and that's how you work with it,
and it can be a bit cumbersome.
But furthermore, if you have relationships within your database,
like for example if I have comments and posts,
then maybe I want to grab the parent post of a comment.
If I use just rows in SQL, then all I can get is the ID
of the parent post and not the actual post itself.
But when we're coding, what we actually want is to actually grab
the parent post itself sometimes.
What object relational mapping does is
it takes the results of the database query
and puts it into objects for you, which are much nicer to work with
than plain arrays and rows.
>> For example, now when I have a comment perhaps,
and I want to grab its parent post,
and I do maybe comment arrow post,
then it will actually give me the post object
corresponding to the actual parent post, not just some ID,
which I would otherwise have to use and make another SQL query to grab the post,
which is cumbersome and unnecessary.
And furthermore, by mapping all these data rows into objects,
you can also attach more functions to objects,
so for example, I talked about how classes are essentially groupings of functions.
You can think of it like that.
For example, maybe I have this post object,
and maybe I'd like to have some sort of function attached to it
that basically tells me was it recently posted?
Was it posted within the last week, true or false?
And that's a function I can attach onto that object,
and it's really convenient to have it in the same place,
and there are a host of different functions you can create
for these objects, and it's really nice to be able to attach it to a class,
to an object, whereas if you just had rows coming from your database,
then you can't really attach any functionality to that.
It's literally just data.
Any questions about that at all?
ORMs are very common web development,
and there are a lot of different types of ORMs,
and Kohana has its own ORM.
It's very basic, but you'll get a taste of what it looks like.
>> Let's create a model for our blog posts,
and the first thing we obviously need to do is to create an actual table
within our database to actually store our data for those posts.
The first thing I'm going to do is go to phpMyAdmin.
Have you guys used phpMyAdmin before?
Okay, awesome, so you guys already know what that is,
and I'm going to create a new table called Kohana Posts,
and it's going to be really simple.
I'll have to log back in.
All we're going to do today is have an author and a body,
just keep it simple.
I'm going to create that table,
and now we just have a table representing our posts
with 2 fields for our author and our body.
The other thing I am going to do now is
configure my web application so it knows how to connect to the database,
and this, again, is something that you'll have to do with all web applications.
You have to tell it the user name and the password
and the name of the database and so on and so forth
to figure out how to actually connect to your database.
>> In Kohana, we have something called a database module,
and in the configuration folder we have this folder called Database,
and as you can see, there are a bunch of settings you have to set here
to tell it what's the user name and the password
for the database so I can actually connect to it.
And since I don't want you guys to actually know
the user name and password of my database,
I have a file where I already set it all up, and I'm going to copy and paste it over.
Awesome.
Okay. I think that's all the configuration I need to do,
but let's see.
We'll keep working in it, and if something crashes,
then we'll fix it.
Now what I'm going to do is I'm going to create a new controller.
Or actually, sorry.
First I have to create a new model.
I'll create a new model called Post.php,
and what we're going to do is we're going to call it class Model_Post.
Get some syntax highlighting on,
and so when I say, "extends ORM," that's basically
some more object-oriented programming,
which unfortunately you guys haven't learned in CS50 yet,
but it's pretty easy to pick up.
It gives me all this extra functionality that comes in this ORM package,
and so I get a bunch of extra functions and whatnot for free,
which you'll see a bit of in a second.
>> Right now actually all I need to do is create this class.
I don't even need to make any function or anything,
but I've created a class that represents the table,
and because I've extended this ORM class,
I get a bunch of things for free, so for now you don't have to set anything more up.
And now what I'm going to do is I'm going to create a new controller,
which I'm going to name blog.php,
and I'm going to copy over the Welcome controller
so I don't have to retype some stuff,
and now I have to rename this.
Now what I'm going to do to test to make sure everything is working out,
I'm going to grab the first post from my database
and print the body of the post on the screen.
To do that what I'm going to do first is I'm going to save the posts
to a variable so what we're going to do is--
in Kohana what you do is to grab the post object
it's kind of cumbersome, but you have to do this thing called ORM:: factory,
and then you pass in the name of the model you want,
and it returns the ORM object that represents that model.
And then, like I said, when we extend the ORM object,
we get all these methods for free, so for example,
we get this new function called "find all,"
which automatically returns every single post in the database,
which is pretty convenient.
>> And now in the body I'm going to return
the first post and return its body.
And of course, I need to create a post,
so let's insert a new post.
I'll say, "Brandon, my very first post."
Awesome.
And now we're going to go to blogs
and if all works well--oh, this is some other dumb file permission thing again.
Hold on 1 second. It's kind of absurd.
There we go. Okay.
I fixed that permission problem.
It was trying to create some files and some log,
and the permissions, again, weren't properly set, so I made it
so those files were writable and executable
so it could actually log to things.
Now it's giving me another exception saying, "class ORM not found,"
and that's because I forgot another step.
That's too bad.
In the bootstrap folder file, there are these modules here,
which you can choose to enable or disable.
These are a bunch of different features that you can choose to use
within Kohana, which is sort of nice.
>> For example, they have an authentication module
which you can use for authenticating users.
They have a caching module if you want to implement
some sort of caching back end to make the application work faster and whatnot.
We need to enable the database and the ORM module,
because like I said, we're using the database, obviously,
and we also need to enable the ORM module,
because we'd like to have the extra functionality, which is nice to have.
All I have to do is uncomment those 2 lines,
and now if I refresh, it gave me another error.
It says, "Class Model_Post not found."
Now this is a good problem to have.
Let's see.
Make it public.
No. Hold on.
Oh, dear.
I do not know why it's not able to find that.
That's really strange.
I have this class right here.
I guess I might have to--oh.
I am so dumb. I forgot to add a PHP tag.
That's why.
Now I have to undo that 1 change I just did.
>> Okay. There we go.
That was really silly. I didn't have an opening PHP tag.
But as you can see, now it's working properly, right?
We have 1 post.
We grabbed the first post, and now we printed out its body.
Great. Fantastic.
Any questions so far?
Nope? Any questions?
Okay, so we just created the post model, very basic,
and we're going to add some functions later on.
We can add validations and filtering.
Validations are one of the things
that frameworks solve for you really, really well,
and I don't think you guys had to do this for your CS50 pset,
but if you do web development for your final project,
you're likely going to want to do some sort of validation,
like not having blank user names,
maybe having a password with at least some length, things like that.
And it's really cumbersome to implement these things by ourselves,
and pretty much every single web framework does it for you
and allows you to do it in a very clean way.
And the model is where you generally express those validation rules,
because it's validating whether a model is valid or not.
>> But for now, we're going to put that until later,
and for now we're going to work on another part,
and we're going to try and make a new view
that lists all the posts.
The steps involved in making a new action for listing all the posts
is to grab a list of all the posts
and then render the list of all the posts through a view.
Right here, fortunately enough, we already grabbed all the posts
using this first line, the find all function,
and now what we're going to do is so far
I've been directly setting the body of the response
by passing the string, but now I want to use a view,
and the difference between a view and just doing this
is with a view I can have a nice, big HTML template,
and what I can do is pass it certain variables
and then have the view automatically populate its template
using those variables.
What I'll do is I'll create a new view,
and I'll name the view something like "blog/index,"
and I'm going to basically bind this--oh, what am I writing?
My brain is somewhere else.
I'm going to bind the posts variable to the view,
so that way the view has access to this post variable.
>> And so now I need to create this view,
so here we have this folder called "Views,"
and first, I'm going to create a new folder under that called "Blog."
This is nice. That way we can have a nice hierarchy for our views.
And then I'm going to create another file in there called "index.php."
Awesome.
Actually, let's have them both here.
Making a view file is probably the simplest part of all this,
and these are probably things you're already familiar with.
We're going to do something really simple,
start saying, "My list of blog posts."
Then we can go through,
and we can iterate through the posts array,
grab every single post and say something like--
maybe add a line
and then print out the author and the body.
That make sense so far?
And let's see if it works.
Nothing happened.
I wonder why.
Oh, I missed 1 step. Very silly of me.
I created a view, but I didn't set the view as the response,
so you have to do 1 more thing.
You have to do "this response body" and set it to be the view.
There we go.
We have our heading, and then we have a post,
and just for kicks, let's insert another post
so we can see a list.
And insert these 2 posts,
and now if I refresh the page,
we see all these posts here.
>> Does that make sense so far?
Yeah, a question? Oh, okay.
As you can see, we've been able to separate all these codes out
into different sections, and then you can see it's most clear with the view code.
This file here that represents the view,
it only cares about representing data, displaying data.
It gets passed some sort of data, and all it does is just show it to you.
In all other parts of your code, you won't have to worry about any of that,
and similarly, your view code doesn't have to worry anything about
how to access the database and so on and so forth,
which is really good and makes your code a lot more maintainable.
Like I said, views, they're dynamic in that
it's 1 file, but it would generate different views
based on the variables you actually pass in,
and furthermore, there are a lot of different helper functions
that you can use to help you write your code faster,
which I'll show you in just a second.
Yeah.
>> [Student] So $0 is a controller, right?
That second thing.
The question is is $0 a controller?
$0 is a variable I created right here.
I created a view first. I assigned it to some variable.
Then I passed it into this function, set it as the body of the response.
Does that make sense?
[Student] So is view :: factory, is view like a class
or a library [inaudible] factory function?
The question is about the view :: factory function,
and basically this is some more object-oriented programming essentially.
View is the view class, and it has a method called "Factory,"
and that's a way to grab the object that's named "blog/index."
And that's some more object-oriented programming stuff
that I'm not going to go into here too much.
Now obviously, we want to create new posts,
but we don't want to have to do it through a database,
so we're going to create a new action for creating a new post,
and there is a lot of stuff we have to do.
>> The first thing we're going to do--let's tackle these things one by one.
The first thing we'll do is we've got to create a form
for inserting a new post,
but I'm also going to add a new action first,
so adding a new action is just as easy as
adding a new function with your controller,
and for now I'm going to do something very basic,
just grab this view and post it, just display it for you.
And then now I'm going to create a new view file,
and I'm going to start writing some stuff.
What's nice about Kohana is that they provide a lot of different helper functions
for you to write view code more easily,
and 1 of those helper functions or helper modules
is around writing forms.
For writing forms, I don't really have to directly write any HTML myself.
You guys have written HTML forms.
You know how it can be really, really painful and cumbersome to write forms.
It's not fun, so fortunately,
we can basically write a form using Kohana's
form helper functions to do it for us.
We're going to basically have fields for every single thing we have,
so one for authors and one for the bodies.
We're going to have a label, and we're going to have an input.
>> And then finally, we're going to have a submission.
And as you can see, this is much cleaner to write
than all that messy HTML, which is kind of nice.
Granted, there are other web frameworks that have it even cleaner than that,
but at least this is better than writing the HTML yourself.
Awesome, so this is what you see.
That's kind of messy,
so I'm going to add a line break there
to make that look a little nicer.
Well, of course, it still looks really, really bad, but we're just focused
on the functionality for now and not on the aesthetics.
No time to do everything.
And as you can see, now we have a super basic form,
which is kind of nice.
This code I would say is cleaner than trying to write an HTML form yourself,
so that's nice.
What's next?
Now we need to do things with the action.
Normally when you write HTML forms,
you have to tell it where it's going to submit the form to.
By default in most web frameworks,
it submits to the exact same URL, so the thing is,
if you send a get request to /blog/new,
it should display you the form,
but if you send a post request to /blog/new with the data,
it should actually try to save that post
and do something with it.
>> What we're going to do is
basically all we have to do to check whether it's a post request or a get request
is to check what are the post variables you can set.
And if the post variable is set, then we're going to try and create a new post.
Again, we just do this,
and that creates a new post, and we're literally going to
set its fields like this,
and then we're going to save it.
And then I'm going to redirect
to the index page so they can see our list of posts again.
Let's try that.
I'll say, "Brandon,"
and then submit the post, and if all goes well,
as you can see, it redirected me to the index page,
and if I scroll to the bottom, we have a newly inserted post.
Yay!
Yeah, question.
>> [Student] What if you had entered the exact same thing
you entered before?
Does it check to make sure you haven't duplicated
the same submission?
Be default, no, because by default--
sorry, the question is if you enter in the exact same data in the form
and submit that, will it allow you to insert a duplicate object,
a duplicate entry, essentially?
Right now, yes, it will allow you to do that,
because in databases it's perfectly valid to have completely duplicate rows,
but if that is a concern, then you can add validations, for example,
to make sure that if this is exactly the same as something that already exists,
then say that it's an invalid object,
and then you can even specify your error message
and say, "Invalid because this already exists" or something like that.
But in this case, I could just create something duplicate.
Now let's try and add some validations.
The problem with this right now is that
I could literally submit a completely blank post.
I can click this button right now, and there we go.
You can't really see it, but this extra line here
indicates that I literally have a new post.
It just has a blank author and a blank body,
and we don't want to allow people to do that.
This is where validation comes in.
>> I can go to my model object,
and now I can add a new function that specifies
what validation rules I should add to this model
to make sure that it is valid or to specify what does it mean to be a valid post?
And I want to say it's only a valid post if both the author and body
are not blank, and this is how you do it in Kohana.
You create a new function called "Rules,"
and then you basically return an associative array
that defines the validation rules for this object.
We're going to return the array, and then what we're going to do is
say "author," it goes to an array,
which goes to another array called "not empty."
And then I'm going to say "body."
Okay, and the syntax for this and structure for this
may look a little cumbersome and a little complicated.
If you read the documentation, it's pretty straightforward to figure out,
But essentially this is what you need to do to specify
some validation rules, and there are a lot of different rules
that Kohana will give you for free, like you can add rules to say
it must be at least this length.
Maybe it has to be numeric. Maybe it has to be alpha numeric.
Maybe it has to be at most this length, so on and so forth.
There are a lot of different rules that Kohana provides for you,
and you can go on their website, look at the documentation,
and you can see all the different things that you can do.
>> But this is all I have to do,
and now let's see what happens
if I submit a blank post.
What's going to happen? Oh, no, I get an error.
I get a validation exception.
Well, it's good.
It told me that my model is invalid,
but I don't want to display an exception
to my users when they try to submit something invalid, right?
I want to give them some sort of friendlier error message
when something goes wrong.
What we're going to do is we're going to
wrap everything in a try catch loop.
Actually, I think this is also something you have not learned yet
in CS50, because C, the programming language C,
doesn't have exceptions, but almost every single other language
has exceptions, so really, really briefly,
an exception is something that a piece of code can
throw an exception when something goes wrong,
but then maybe some other piece of code higher up
can catch that exception and do something with it.
>> For example, in this case,
the piece of code that's trying to save a model,
it validates the model, and if it says, "Okay, this model is invalid,"
it's going to throw an exception, and this is kind of equivalent to
in C you might return a -1 or something like that.
And then for me, this function, my code
at a higher level, I can try and catch that exception
and basically say, "Okay, if I catch the exception, what am I going to do?"
Or I could choose not to catch that exception and let someone higher up
catch the exception, or if nobody catches it,
then the whole program crashes and says,
"Something went wrong, and I couldn't handle it."
>> But what we do is you wrap a piece of code in a try block,
and then you also add something called a catch block,
which is the sort of code that will try and catch exceptions that may occur.
And so if I catch this particular exception
or invalidation exception, then what I'm going to do is
I'm going to set the errors--I think that's how I do it--
and I'm going to set the errors to some object.
And then what I'm going to do is if it hits this exception,
it's not going to redirect, and if it doesn't redirect,
it's going to come out of the if blog
and hit this blog/new, which is want I want to do.
If there is an error, then I want to go back to the form
and display those errors.
Now what I want to do is I want to pass in those errors
to the view.
Okay, I think I have the view right here,
and basically I want to display those errors if they exist.
Before I write the HTML for that, I'm going to really quickly
show you what the structure of this errors variable looks like,
and this is a good practice in general.
A lot of times you get something back from some method,
some function in the web framework,
and you don't know what the variable looks like,
so you don't know how to work with it.
I'm going to use a print r method to basically print it out.
>> And as you can see, it tells me it's an associate array,
and you have a key, author, points to this string,
author must not be empty, and another key, body,
points to another string, body must not be empty.
I'm like, okay, cool.
Then I can iterate through the array and print out every single message.
It's basically like an associative array with a bunch of messages.
What I'm going to do is "if errors,"
and I'm going to create an unordered list,
and I'm going to iterate through all the errors.
And this, and now I'm going to try submitting this again,
and let's see what we get.
Now we get this nice list of errors,
and this is still pretty ugly, but this obviously can be formatted to look nice,
but the basic idea is just in a few lines of code,
we were able to validate our model,
make sure that certain fields weren't empty,
and if something went wrong, then return some sort of error message
I could then present back to the user.
You can also customize your validation
so that you can actually have an error message
that is more specific to your application or something like that.
All that is generally customizable.
>> Unfortunately, we're running out of time,
so I'm going to have to cut off the live coding session here.
There are a bunch of other features that I want to demonstrate for you
in this example.
For example, you can add templates to your site,
so maybe there is some sort of HTML code that you want to apply
to every single page in your site, and instead of pasting that
in every single view file you have, which obviously would be a bad practice,
you can basically define these templates,
and then in your controller say, "Okay, I'm using this template."
"Have all my views use this template."
And the one last thing I want to demonstrate to you as well
that we don't have time for is cross-site scripting,
and basically I think you guys have probably seen in CS50--
I think David Malan probably talked about how you can usually inject
JavaScript code into--have you talked about this?
Maybe? Maybe not?
>> But a lot of times you can inject malicious JavaScript code
into someone's database, and if they don't escape that properly,
then when they present that data back to the user,
then it may run some sort of random JavaScript code you don't want to happen,
and I was going to demonstrate how you'd do that within Kohana.
It's actually really, really easy.
I could do it right now in 2 seconds literally.
All you have to do is basically wrap these things
in this thing called HTML entities.
And that will automatically escape all the characters properly
and make sure you don't get this problem.
[Student] You spelled the first test incorrectly.
[Brandon Liu] Oh, oops.
>> Okay, that's all I had to share with you for today.
These slides are going to be posted, but these are generally
the only resources you should really need to get started with Kohana.
You can go to the website. They have a user guide, and they also have an API explorer.
We can explore all the different functions and helper functions they have for you.
They generally have enough information on the website
that you can use to get started and get going with Kohana.
There aren't that many tutorials, I think, for Kohana, outside of
what they have on the website here, so this is probably your best bet.
But if you want to go with the web framework
and you don't want to have to pick up a new language,
and you want something that is relatively lightweight and has an easy learning curve,
I would definitely suggest Kohana.
That's probably the best offering for that.
The funny thing, though, is if we were using Ruby on Rails,
we could have replicated what we just did
and probably more in under 3 minutes.
No joke, but learning Ruby on Rails takes a lot longer
than it would take to learn Kohana.
It's basically your choice on what you want to choose to learn,
but if you want to get up and running quickly,
Kohana is definitely a very good choice.
>> Any last questions before we end? Yes.
[Student] How would we integrate that
in a CSS framework like you were using when you were instructing?
The question is how would we integrate that with a CSS framework?
What we would probably do is we would probably include
a new folder where we would dump all our CSS files,
and then we'd also add a new template.
In the template we'd include those CSS files
to make sure they're referenced on every single page,
and then when you actually are writing HTML,
you just add appropriate classes and whatnot,
and for example, when you're using something like the form
helper function, you can add more parameters afterwards
to specify what classes you want to be attached to various things
so they could style it properly, and that's basically how you would go.
>> Any other questions?
Awesome.
Thank you for your time, and thank you for coming.
I wasn't going to add very much else,
but 1 really quick thing is we don't have a link
to the form.
Really dumb.
Let's add a--actually in the view, blog, index,
let's really quickly add a link that goes to the new page,
the page where we can insert a new post.
We're going to do this.
What's nice is there is this whole group of HTML helper functions
which do different things for you, so you already saw the entities
function here, but they also have a function called "anchor,"
which you can type in blog/new
and say, "Post a new blog."
And it would create that link for you,
and this seems really trivial to do, but this is nice,
because suppose that you are moving your website from 1 domain to another.
And if you just wrote out the URLs yourself,
then you would have to change all the URLs.
Or maybe you moved it from 1 subfolder to another subfolder.
You would have to change all those URLs yourself,
and that's no fun.
You can use this anchor right here,
and you can change the domain or the subfolder prefix
in the configuration file once,
and then it will apply that everywhere, and this is, again,
a great example of do not repeat yourself, DRYing your code out.
Wherever you're repeating yourself, try and extract in some sort of configuration file
or to a different function and have it handle that for you.
>> And the very last thing that I wanted to show you was
suppose we're back at this post, and I had composed some really long essay,
but I forgot to include my author.
Now when I click "Submit Post,"
I just lost everything.
No! Really sad.
So how do you deal with that?
This is what we do.
What we do is here for these input and text area functions,
if we include a second parameter, then the value of that second parameter
is going to be what the field is going to be initially populated with.
What we could do is in our blog controller,
we could bind another variable.
Call it "values" maybe.
And pass in the post array, literally.
That means that if the validation failed,
pass to me the post array that I submitted from the last request,
and that way I can use the values from my last submission
to repopulate the fields.
Now I can do something like values author
and values body, and that way now if I do some random stuff
and click "Submit Post," then it stays there.
But we're going to run into another problem.
That works, but if I go to the page the very first time,
it's going to crash, and that's because the very first time
we go to the page, this post variable has not been defined yet.
It's null. It doesn't exist.
>> And what we want to say is if this key exists,
then return the value of this array,
but if the key doesn't exist, then return a blank string.
That's the functionality we want here.
We want to check if the key exists before trying to access the array,
and fortunately enough,
Kohana also gives us a helper function for that.
They have this whole suite of functions
under the name ARR, short for array,
and they have 1 function called "get,"
and you can pass in the array,
and you can pass in the name of the key.
Then basically what it will do is it will try to get that key,
but if that key doesn't exist in the array,
then it will return blank, or we can also specify a default, I believe,
which is nice.
Now if we do the same thing again,
then you see now it works the first time around,
and again, if we type in some random stuff
and try and submit, then it stays there.
>> And I guess I can also show you how to add a template really quickly.
What we can do first is we can add a new view called "template.php"
within the Views folder,
and what I'm going to do is I'm going to print out something called "content,"
which is going to be my main content.
And maybe at the very bottom I'm going to add, say,
copyright.
[inaudible student question]
[Brandon Liu] Maybe this is a super basic template I want to use.
I want to have a folder with my copyright on every single page,
and now what I'm going to do within my controller
is now instead of saying, "extends Controller"
I'm going to say, "extends Controller_Template,"
and now instead of saying, "response body is equal to this view,"
I'm going to say, "this template content is --"
and I think--do I put an equal sign?
I forget. Yeah, I thought so.
And now I set that content variable to equal the view.
I can do the same here.
And now if I refresh, you can see now this copyright is added there,
and just make some random post,
and then, again, you should see that the copyright is at the very bottom of the page.
>> Great. That's all I wanted to show you guys.
[Applause]
Any questions?
[CS50.TV]