IntroductionWelcome| 00:00 |
(music playing)
| | 00:04 |
Hi, I'm John Peck, and welcome to Up and
Running with CodeIgniter.
| | 00:08 |
In this course, we'll look at CodeIgniter,
the open source PHP web application framework.
| | 00:13 |
I'll start by describing what CodeIgniter
is and why it's useful, then demonstrate
| | 00:17 |
how to install the framework.
I'll model records in the database, add
| | 00:22 |
functionality using libraries, and
finally, show how to save time using helpers.
| | 00:28 |
Throughout the course, we'll create a
magazine catalog web application for
| | 00:31 |
keeping track of a collection of back
issues.
| | 00:34 |
We'll be covering all of these features
plus plenty of other tools and techniques
| | 00:38 |
that a modern developer can use to quickly
build PHP applications without having to
| | 00:43 |
constantly reinvent the wheel.
Now, let's get up and running with CodeIgniter.
| | 00:47 |
| | Collapse this transcript |
| Exercise files| 00:00 |
In this course, I'm going to be developing
a Sandbox PHP environment using
| | 00:04 |
CodeIgniter 2.1.3 as the framework, PHP
5.3 as server side language, MySQL 5.5 as
| | 00:12 |
the database server and Apache 2 as the
web server.
| | 00:15 |
Other web servers, such as, nginx, IIS
will not be covered in this course but
| | 00:19 |
they should work.
If you don't already have a server for
| | 00:22 |
development, I recommend using a local
development server running on your workstation.
| | 00:26 |
In this course, I'm going to be
demonstrating using a virtualized server
| | 00:30 |
running in my existing operating system.
If you'd like a server configured using
| | 00:34 |
this technique, check out, Up and Running
with Linux for PHP Developers here in the
| | 00:38 |
lynda.com online training library.
Alternatively, you can use a web server
| | 00:42 |
solution stack package, in your native
operating system.
| | 00:45 |
XAMPP from apachefriends.org, has
distributions for Linux, Windows, and Mac
| | 00:50 |
OS X.
WampServer from wampserver.com, is
| | 00:53 |
explicitly for windows, and MAMP from
mamp.info is for Mac only.
| | 00:58 |
Each of these packages will allow you run
the exercises found in this course.
| | 01:02 |
Installing additional software within your
native operating system is covered in the
| | 01:05 |
course, Installing Apache, MySQL and PHP
with David Gassner here in the lynda.com
| | 01:11 |
online training library.
Regardless of the location of your web
| | 01:14 |
server you'll need access to the command
line with administrative credentials in
| | 01:18 |
order to install and configure server
software.
| | 01:20 |
For Mac and Linux, the Terminal allows you
to access the command line which includes
| | 01:24 |
access to the ssh command if the site is
hosted remotely.
| | 01:28 |
For Windows, you can use the free program
PuTTY to connect via ssh to remote servers
| | 01:32 |
available from the official Putty website.
I'm going to demonstrate writing code
| | 01:37 |
using the NetBeans 7.3 IDE bundle for PHP.
NetBeans is a free open sourcing cross
| | 01:43 |
platform integrated development
environment from netbeans.org.
| | 01:47 |
Keep in mind the goal of the course is to
use CodeIgniter not how to use NetBeans
| | 01:51 |
but with that said I'm only going to be
editing code in NetBeans.
| | 01:54 |
Any IDE or text editor will work.
The exercise files for this course are
| | 01:59 |
contained in folders by chapter and movie.
On my work station I have them in a folder
| | 02:03 |
named sandbox that my virtualized lending
server can access.
| | 02:07 |
Depending on your web server configuration
you may need to store these files in a
| | 02:10 |
different place, such as a remote web
server or in a folder accessible by a
| | 02:14 |
local Apache and PHP stack.
There's some additional folders in the
| | 02:18 |
exercise files that you should be aware
of.
| | 02:21 |
The first is Assets which contains images
for testing uploading during the course.
| | 02:25 |
Next is the Bootstrap folder, this is
minimal modified version of Twitter
| | 02:29 |
Bootstrap including a custom navigation
system this would be copying during the course.
| | 02:34 |
Along with the Bootstrap folder are css,
js and image, these will be copied same
| | 02:40 |
time as Bootstrap.
Finally the Database folder contains a
| | 02:43 |
single SQL file for import called
Issue_publications.sql.
| | 02:48 |
Please import the file now to prepare for
database interactions.
| | 02:52 |
A final note, as different web hosts in
configurations serve content from
| | 02:55 |
different URL's, the address you see in my
browser may not exactly match what you see
| | 03:00 |
on your work station.
Additionally the location shown in the
| | 03:03 |
command prompt demonstrations will differ
depending upon the location of site files
| | 03:07 |
and configurations on the server.
The software configuration will be very
| | 03:10 |
similar if not identical across platforms.
| | 03:13 |
| | Collapse this transcript |
| What you should know| 00:00 |
This course was designed with the
assumption that you have a working
| | 00:03 |
knowledge of the PHP language and have
written a few scripts.
| | 00:06 |
Without this background, you might not
have enough contacts to follow along with
| | 00:09 |
what I'm doing, which can be a bit
frustrating.
| | 00:12 |
For some background door refresher, I
recommend PHP with MySQL essential
| | 00:17 |
training with Kevin Skoglund, here in the
Lynda.com online training library.
| | 00:22 |
Additionally, the use of object-oriented
PHP is required for this course.
| | 00:26 |
If you're not familiar with it, check out
Object-Oriented Programming with PHP here
| | 00:30 |
in the lynda.com online training library.
It'll include examples and explanations
| | 00:35 |
that should make Codelgniter adoption much
more seamless.
| | 00:39 |
If you're unfamiliar with configuring web
server components, check out the course,
| | 00:43 |
Installing Apache, MySQL, and PHP with
David Gassner here in the lynda.com online
| | 00:48 |
training library, for comprehensive
instructions on how to manage the solution stack.
| | 00:53 |
If you're interested in MVC and Frameworks
in general, take a look at MVC Frameworks
| | 00:57 |
for Building PHP Web Applications with
Drew Falkman, here in the lynda.com online
| | 01:02 |
training library.
it covers a number of key structures and
| | 01:05 |
techniques, then goes into a brief survey
of many different frameworks including
| | 01:09 |
Codelgniter, which is the sole subject of
this course.
| | 01:13 |
Finally, it's always good to know where
the manual is.
| | 01:15 |
Codelgniter maintains a comprehensive user
guide that provides both tutorials and
| | 01:20 |
functional references.
These can all be found at ellislab.com.
| | 01:25 |
I recommend bookmarking this page and
using it as a reference as we go along.
| | 01:29 |
| | Collapse this transcript |
|
|
1. First Steps with CodeIgniterWhat is CodeIgniter and why should I use it?| 00:00 |
Before I jump directly into describing
what CodeIgniter is, let's take a step
| | 00:04 |
back and look at how developers typically
learn a new language.
| | 00:08 |
I found that people tend to go though a
number of common stages as their skills
| | 00:11 |
grow and improve.
The first stage is basic structure and
| | 00:15 |
syntax, where a program can be written
that can go from start to finish without
| | 00:19 |
any major failures.
Next comes in understanding of the
| | 00:22 |
vocabulary and functionality of the
language.
| | 00:25 |
There's a lot less guess work and more
certainty about what can and cannot be done.
| | 00:30 |
Once they're comfortable with that
foundation, it could be expanded with
| | 00:32 |
knowledge of development techniques and
relations of the language features.
| | 00:36 |
The final stage, excluding actually
developing the language itself, contains
| | 00:40 |
scalable programming structures and
architecture.
| | 00:42 |
Including design patterns, libraries and
knowledge of APIs and so forth.
| | 00:47 |
This is where development speed really
comes into play rather than reinventing
| | 00:51 |
the wheel, a programmer can focus on
building components that deliver value.
| | 00:55 |
I personally place CodeIgniter at this
final stage.
| | 00:58 |
Why is that?
CodeIgniter is an open-source PHP web
| | 01:02 |
application framework which can be used
for rapid development without the overhead
| | 01:06 |
of having to constantly build reusable
components.
| | 01:10 |
Providing both a logical structure and a
reusable interface to libraries written to
| | 01:14 |
perform common tasks.
CodeIgniter provides a fast extensible
| | 01:18 |
foundation for writing complex software.
Some of the key features include, a small
| | 01:24 |
footprint meaning that its lightweight and
has very little overhead.
| | 01:27 |
Which lends itself towards fast
performance especially when its compared
| | 01:31 |
to other frameworks.
It's also easy to get going requiring
| | 01:34 |
almost no configuration to get started.
Originally released in 2006, Codelgniter
| | 01:40 |
has reached an adoption rate and a
maturity that makes it a production-ready
| | 01:44 |
candidate for the basis of your next
project.
| | 01:46 |
In 2008, PHP creator Rasmus Lerdorf
praised Codelgniter because it's faster,
| | 01:52 |
lighter, and least like a framework.
But, why should I use somebody else's work?
| | 01:58 |
Consider creating your own framework.
While nobody will prevent you from writing
| | 02:01 |
your own programming framework.
Ask yourself, is this really the best use
| | 02:05 |
of my time?
Are you going to review your work with
| | 02:08 |
thousands of other developers?
What's your bug reporting process and
| | 02:11 |
testing methodology?
What about security and penetration testing?
| | 02:15 |
Finally, do you want to have to build each
new piece of functionality from scratch
| | 02:19 |
every time you want to do something new?
I could go on, but I'm trying to get to
| | 02:23 |
three basic points.
Why?
| | 02:25 |
Reusability and modularity, where I'm
avoiding copying and pasting code.
| | 02:30 |
Components can be reused on multiple
projects leveraging a common interface.
| | 02:34 |
Next is maintainability, which is
particularly important if you want others
| | 02:38 |
to be able to easily build upon or extend
your application.
| | 02:41 |
If their familiar with Codelgniter and
you've used the recommended structures,
| | 02:45 |
they shouldn't have any problem
understanding your code.
| | 02:47 |
Finally is delegation.
You want to focus on delivering value, not
| | 02:51 |
creating the building blocks for
repetitive or common tasks that others
| | 02:55 |
have already completed.
Codelgniter uses a loose MVC development
| | 03:00 |
pattern for organizing code and logic.
MVC stands for Model-View-Controller,
| | 03:06 |
which looks great on a resume, but what
does this really mean?
| | 03:09 |
| | Collapse this transcript |
| Introducing the MVC development pattern| 00:00 |
I'm going to explain MVC at only a very
high level as this courses focus is on
| | 00:05 |
CodeIgniter .
For a more comprehensive description I
| | 00:08 |
recommend MVC Frameworks for Building PHP
Web Applications with Drew Falkman here in
| | 00:14 |
the lynda.com online training library.
MVC stands for Model-View-Controller.
| | 00:20 |
It's a software design pattern that
separates the representation of
| | 00:24 |
information from user interaction.
This explicit separation of components
| | 00:29 |
allows for greater code reusability and
logical separation of program responsibilities.
| | 00:33 |
In short MVC keeps code organized, which
in turn helps projects and teams.
| | 00:39 |
CodeIgniter uses a loose approach to MVC
which I'll get into more detail in a bit.
| | 00:45 |
There are three components to MVC.
The first, model is the representation of
| | 00:50 |
data structures, business rules, and
functions.
| | 00:53 |
This is where really basic, create, read,
update, and destroy or CRUD functionality
| | 00:58 |
is defined.
Next is a View, which is a representation
| | 01:01 |
of the information that's presented to the
user.
| | 01:03 |
The View is where all HTML rendering takes
place.
| | 01:07 |
The most program logic that's in a View is
a really simple if, then, like if
| | 01:11 |
something exists then display it.
Anything that takes more logic than that,
| | 01:15 |
like deciding what to do based on user
input, is delegated to the controller,
| | 01:20 |
which serves as kind of an intermediary
between the model and the view.
| | 01:24 |
The controller sends commands to the other
components like model, save yourself, then
| | 01:29 |
view, show a message saying that the model
was saved.
| | 01:33 |
As a visual explanation of a regular
interaction, a site user will send a
| | 01:38 |
command to the controller which will in
turn manipulate the model, like create
| | 01:42 |
this record, for example.
Through which the control updates the View
| | 01:45 |
with a confirmation that the record has
been updated.
| | 01:48 |
The User sees the final HTML
representation in the View.
| | 01:52 |
Earlier, I mentioned that CodeIgniter uses
a loose approach to MVC.
| | 01:56 |
To be clear, CodeIgniter's use of models
is unique and does not precisely fit in
| | 02:01 |
traditional definition within a model MVC
design patterns.
| | 02:04 |
They're more like a domain object, which
is a collection of properties.
| | 02:08 |
Models in Codelgniter are optional.
Depending on your project needs, you can
| | 02:12 |
completely leave it out, leaving only a
minimal application with just controllers
| | 02:17 |
and views.
I'm going to demonstrate Codelgniter's
| | 02:19 |
implementation of models.
Now that we've got this theory out of the
| | 02:23 |
way, let's start building an application
by installing the Codelgniter framework.
| | 02:27 |
| | Collapse this transcript |
| Installing CodeIgniter| 00:00 |
CodeIgniter installation is really
straight forward.
| | 00:03 |
I'm going to start by connecting to my
local development server, SSH sandbox.
| | 00:08 |
Next, I'm going to change directory to a
temporary directory.
| | 00:13 |
I prefer /var/tmp.
I'm going to use wget to download the
| | 00:18 |
archive containing CodeIgniter.
I'm using version 2.1.3.
| | 00:23 |
So, here's the current full path to that
file.
| | 00:26 |
Http://ellislab.com/asset/ci_download_files/reactor/codeigniter _2.1.3.zip.
| | 00:45 |
Now that the archive has been downloaded,
extract it.
| | 00:48 |
I'm going to use unzip and then the name
of the file.
| | 00:52 |
Now that the archive has been extracted,
change directory to your web root.
| | 00:56 |
In my case, it's media/sf_sandbox.
Make sure it's empty before preceding.
| | 01:03 |
Good, I've got a clean slate.
Copy the extracted files to the web root.
| | 01:07 |
I'm going to recursively copy using CP -R,
and the path for our temp, and then CodeIgniter.
| | 01:16 |
And then the full contents of the
directory to the current directory.
| | 01:21 |
Now that it's been copied, a little
configuration is needed.
| | 01:24 |
I'm going to to switch to NetBeans.
I'm going to create a new project with a
| | 01:29 |
PHP application with existing sources,
that is located on my desktop in the
| | 01:34 |
sandbox folder.
I will put NetBeans metadata into a
| | 01:39 |
separate directory and click Finish.
I don't need index.php, the front
| | 01:45 |
controller, so, I'll just close it.
All configuration files are contained in
| | 01:50 |
application config.
First thing I'm going to configure is the database.
| | 01:55 |
I'm going to scroll down a little bit, I'm
going to set the user name, in my case,
| | 02:00 |
it'll be sandbox.
The password, sandbox again, and the data
| | 02:05 |
base name which is sandbox.
When complete, save and close the database
| | 02:11 |
configuration file.
Finally, I'm going to configure an
| | 02:14 |
automatic connection to the database,
which will automatically load and
| | 02:17 |
instantiate the database connection on
every page load.
| | 02:20 |
To do that I'll use an auto loader.
Navigate to auto load.
| | 02:24 |
I'm going to scroll downy to the bottom
and down in libraries, I'm just going to
| | 02:28 |
add the string database and save.
I'll define libraries in much greater
| | 02:34 |
detail later in the course.
Save the changes, then close all open files.
| | 02:40 |
To verify that the settings are working,
switch to the browser.
| | 02:42 |
I'm going to navigate to my web server
root, which in my case is http://sandbox.dev:8080.
| | 02:53 |
I see a welcome to Codeigniter message.
Success, Codeigniter has been installed.
| | 02:57 |
If you see any errors, verify that your
database credentials have been set up correctly.
| | 03:01 |
If there aren't any errors, then right
now, this application isn't very useful,
| | 03:05 |
it's only showing a stock message.
That's not very fun.
| | 03:08 |
Let's start by customizing Codeigniter to
display something more useful than default text.
| | 03:13 |
| | Collapse this transcript |
| Creating a static page controller| 00:00 |
In CodeIgniter, and other MVC frameworks
for that matter, a controller can be
| | 00:04 |
practically thought of as a class that
delegates work.
| | 00:08 |
Each controller is named so it can be
accessed via URL.
| | 00:12 |
To determine what controller to use,
CodeIgniter uses the following pattern for
| | 00:16 |
routing a user's request to the right
controller.
| | 00:18 |
Index.php, followed by the controller
class, then the controller method, and
| | 00:24 |
then any optional arguments.
Let's take a look at how this default
| | 00:28 |
message is being rendered.
From Netbeans, navigate to the application
| | 00:33 |
route, and open the controllers directory.
There are two files in here: index.html,
| | 00:38 |
which, when I open, I can see is just a
simple place holder denying access.
| | 00:43 |
Close it, then open welcome.php.
The first line is a safety mechanism that
| | 00:48 |
prevents direct access to the controller.
Then, a subclass declaration that extends
| | 00:53 |
the codeIgniter controller class.
The name of the class is Welcome, with a
| | 00:58 |
capital W.
This is different than the file name,
| | 01:01 |
which is all in lower case.
There's only one method within the class, index.
| | 01:06 |
Index is a bit of a fail safe in that if
the controller method is missing from the
| | 01:10 |
URL, then index is the fall back.
The method has only one line of executable
| | 01:14 |
code loading the view named welcome
message.
| | 01:17 |
I'll discuss views in greater detail in a
moment.
| | 01:20 |
First, let's see how CodeIgniter parses
URLs.
| | 01:24 |
Switch back to your browser.
You should be seeing the default page.
| | 01:27 |
Now navigate to /index.php/welcome/index,
the page should reload and look the same.
| | 01:38 |
Let's trigger the default behavior as well
without specifying the index method.
| | 01:43 |
Again, the page looks the same.
If I try to do something that doesn't
| | 01:48 |
exist, however, like the puppies method, I
get a default for our fore message.
| | 01:54 |
That's enough playing around with the
defaults.
| | 01:55 |
Let's actually start writing code.
I'm going to create a new controller for
| | 01:59 |
the magazine database.
Copy the first three lines of the welcome class.
| | 02:04 |
Close the file and then create a new file
in the controller called Magazine.php.
| | 02:11 |
I'll paste the contents, close that out
properly.
| | 02:16 |
I'm going to change class welcome to class
magazine with a capital M.
| | 02:21 |
I'm going to create a public...
Method called index which takes no arguements.
| | 02:27 |
For now let's just echo a headline my
magazines.
| | 02:31 |
So echo h2 my magazines and then close the
h2 .
| | 02:37 |
Add a quick comment stating what this
method does which in this case is just the
| | 02:41 |
index page for magazine controller.
That's all that's needed for the
| | 02:48 |
controller for now.
Save and go back to the browser.
| | 02:50 |
Recall the URL structure with the class
name.
| | 02:53 |
Navigate to Index.PHP/magazine.
My magazines is now displayed directly for
| | 03:01 |
the controller.
However, this is kind of an awkward URL.
| | 03:04 |
Wouldn't it be easier if we didn't have to
explicitly state magazine?
| | 03:08 |
Let's change the default URL route to go
to the magazine instead of Welcome.
| | 03:12 |
To do that, I'm going to explicitly edit
the route's configuration.
| | 03:17 |
Return to Netbeans, open up Config, then
open routes.php.
| | 03:23 |
There's a lot of comments in here, in
short, this file allows remapping of URI
| | 03:27 |
requests to a specific controllers when
you don't want the default behavior.
| | 03:31 |
Scrolling to the bottom, there's actually
only two routes and both are reserved by codeIgnitor.
| | 03:37 |
The default, underscore controller, is
actually what we want to specify.
| | 03:41 |
Currently it's set to welcome which
explains why the default welcome message
| | 03:44 |
was shown when just navigating to the base
URL.
| | 03:47 |
Let's change it to magazine and save.
Then close the router.
| | 03:51 |
Switch back to the browser.
Now, when I navigate to the server root, I
| | 03:56 |
see my magazines instead of the default
message.
| | 03:58 |
If you recall how NBC Architecture
separates logic from display, you're
| | 04:02 |
probably thinking echoing isn't really a
good idea, and you're right.
| | 04:07 |
Echoing is terrible and I should feel bad
for doing it.
| | 04:09 |
Instead, I should feel bad for doing it.
Instead, I should have a view.
| | 04:13 |
All right.
How can I do that?
| | 04:14 |
| | Collapse this transcript |
| Generating output with a view| 00:00 |
A view is a partial or complete webpage.
Designers like views because it's most
| | 00:05 |
HTML with a very bar minimum in PHP code,
and what logic is there are four hs and so forth.
| | 00:13 |
Views can be embedded in other views,
which allows for hierarchies and cleaner,
| | 00:17 |
more reusable code.
Even though they're webpages, a view
| | 00:21 |
cannot be called directly.
It can be only loaded by controller.
| | 00:24 |
So with this context, let's get that HTML
out of the controller and into a view.
| | 00:31 |
From NetBeans, I'm going to navigate to
the Views directory.
| | 00:34 |
Right now, there's only two files.
The same placeholder index.html and
| | 00:40 |
welcome message.php.
Open welcome message.php to see what's inside.
| | 00:45 |
Scrolling through, it's a complete html
five page with no php whatsoever.
| | 00:52 |
At the bottom there is one little anomaly.
Page rendered in elapsed time in curly braces.
| | 00:57 |
This is a pseudo variable from the
benchmarking class...
| | 01:01 |
I'll get into class libraries in a later
chapter.
| | 01:03 |
For the time being, just close welcome
message.
| | 01:07 |
Then create a new file in views called
magazines, plural, .php.
| | 01:14 |
And the magazine controller.
Let's copy that HTML.
| | 01:18 |
And paste it into magazines.php.
Next, we'll need to load the view.
| | 01:22 |
Take a look at the welcome controller for
just a second, and see how it loads the
| | 01:26 |
view using this.
What is this?
| | 01:30 |
This has a special meaning in CodeIgniter.
It's a singleton CodeIgniter instance,
| | 01:34 |
which means there can only be one copy of
it throughout the entire application,
| | 01:38 |
which prevents duplicates in overhead.
When various functionality is loaded, it's
| | 01:43 |
attached to the instance, in such a way,
that it can be referenced, like a property
| | 01:46 |
of the instance.
I'll demonstate how this works in just a moment.
| | 01:51 |
Close the Welcome controller and go back
to the Magazine controller.
| | 01:56 |
We'll replace the echo with this, load and
we're going to load a view.
| | 02:01 |
Named magazines.
Followed by semicolon and save.
| | 02:05 |
I'm going to go back to the browser and
refresh.
| | 02:08 |
Make sure that nothing has changed.
It says, My magazines, again.
| | 02:12 |
Now there's no limit to the number of
views that are loaded.
| | 02:14 |
If you chain them, they'll be appended.
Let's experiment a little bit by going
| | 02:18 |
back to the magazine controller.
And copying and pasting this load view.
| | 02:24 |
And doing it twice.
Save, then in the browser, refresh.
| | 02:29 |
Now there's two My magazines.
If I view the page source.
| | 02:33 |
I can see that the only markup that is
shown is what was in my view.
| | 02:36 |
See what I mean by coding neither having
low overhead.
| | 02:39 |
None of the (UNKNOWN) fully formatted HTML
documents.
| | 02:43 |
Wait a second.
That's actually something I want.
| | 02:45 |
I'm going to get into more detail about
how to set up a proper template in an
| | 02:48 |
outcoming chapter.
Close the source, and go back to NetBeans.
| | 02:53 |
Let's clean up the controller by removing
that extra line, and then save.
| | 02:58 |
In this chapter, I've defined what
CodeIgniter is, and gave a number of
| | 03:01 |
reasons why it should be used.
I've introduced the Model View Controller
| | 03:05 |
development pattern.
Then I installed CodeIgniter and tested
| | 03:09 |
the database configuration.
Starting with some code and concepts, I
| | 03:12 |
created a static page controller and
finally generated output using a view.
| | 03:16 |
At this point, we're ready to display
content but we don't actually have
| | 03:21 |
anything to show.
No worries, we'll sort that in the next
| | 03:24 |
chapter as we model magazines in the
database.
| | 03:26 |
| | Collapse this transcript |
|
|
2. Modeling Magazines in the DatabaseWhat is a model and how is it used?| 00:00 |
In the previous chapter, I discussed how
CodeIgniter loosely implements the
| | 00:04 |
Model-View-Controller pattern, then
demonstrated both a View and a Controller.
| | 00:08 |
The final component, the model,
traditionally contains application data,
| | 00:13 |
logic and business rules, and functions.
Codelgniter defines models as PHP classes
| | 00:19 |
that work with information in a database,
which is pretty vague.
| | 00:22 |
Out of the box, they're treated just as a
collection of properties, which I
| | 00:26 |
mentioned previously, is similar to a
domain object.
| | 00:29 |
These properties are named exactly the
same as the database columns with a one to
| | 00:34 |
one relationship.
Codelgniter models contain no other
| | 00:37 |
stand-alone functionality by default.
Traditionally, the model is a class where
| | 00:42 |
common functionality can be defined,
including Create, where something like a
| | 00:46 |
time stamp or other default values can be
set.
| | 00:49 |
Read, where a record is retrieved from the
database and used to populate the model.
| | 00:54 |
Update, where a record in the database is
saved, and Destroy where the record and
| | 00:59 |
the database is deleted.
Create, Read, Update, Destroy is a common
| | 01:03 |
collection of functionality referred to by
the acronym CRUD.
| | 01:07 |
In this chapter, I'm going to extend the
Codelgniter model to define the database
| | 01:11 |
table and primary key that's associated
with it.
| | 01:14 |
Then, I'll integrate Codelgniter's
database functionality with CRUD methods
| | 01:18 |
to allow models to save themselves similar
to tradition MVC.
| | 01:23 |
With this context, I'm going to create
models that will allow me to represent
| | 01:26 |
back issues of a magazine.
| | 01:28 |
| | Collapse this transcript |
| Modeling a magazine| 00:00 |
Magazine back issues have a number of
common properties.
| | 00:03 |
For the purposes of this course, I'm
going to limit the domain to two models.
| | 00:07 |
One for the publication as a unifying
record and the second for the issues themselves.
| | 00:13 |
Each publication has a unique identifier,
the publication id and a publication name.
| | 00:20 |
Magazine back issues are a little bit more
complex.
| | 00:24 |
They have a unique identifier, the issue
id, then the unifying record to the
| | 00:28 |
publication, publication id.
As an issue number, which is the number
| | 00:32 |
given by the publisher and the date of
publication, and finally the path to the
| | 00:37 |
file containing the cover.
Let's switch to the IDE and start the
| | 00:41 |
models for the publication and issue.
Models are stored in application models,
| | 00:48 |
navigate there now.
There's currently nothing in there, except
| | 00:51 |
for the index place holder.
I'm going to create a new file for the publication.
| | 00:58 |
Same as controller names, the file name
will be all lower case.
| | 01:01 |
Publication.php.
In the empty file, let's start a new class.
| | 01:07 |
The class name must be the same as the
file name with the exception that it must
| | 01:12 |
start with an uppercase letter.
So publication and all remaining letters
| | 01:17 |
must be lowercase.
You can use an underscore as well.
| | 01:20 |
Each model extends the coding nighter
underscore model.
| | 01:25 |
Class.
Save the empty class, then right-click on
| | 01:29 |
CI_Model and go to Navigate, Go To
Declaration.
| | 01:35 |
Let's see what it's actually doing.
It's extremely minimal.
| | 01:38 |
The parent constructor is just sending a
log message and provides a magic get
| | 01:43 |
method for allowing models to access
loaded classes using the same syntax as controllers.
| | 01:48 |
In short, I've got a pretty blank slate.
But that's cool.
| | 01:51 |
Close the CI model.
I'm going to add two properties to the
| | 01:56 |
publication to store both unique
identifier and the name.
| | 01:59 |
Remember to add proper documentation.
Public publication_id then public
| | 02:08 |
publication name.
I'm going to add documentation, so this
| | 02:13 |
will be an integer.
This will be a string.
| | 02:22 |
So this will be the location unique
identifier, and this is a publication name.
| | 02:30 |
Save because that's all that's needed for
now.
| | 02:31 |
I'll add persistence and other
functionality in a moment.
| | 02:35 |
Next, I'll create the model for the issues
themselves.
| | 02:38 |
Create a new file, called Issue.php.
So, class issue, extends, ci_model.
| | 02:51 |
I'll start off with a public issue id,
which will be issue unique identifier,
| | 03:01 |
which is an integer.
Next will be a public publication id,
| | 03:08 |
which is a publication unifying record,
which is an integer.
| | 03:18 |
Then the public issue number which is the
publisher assigned issue number also an integer.
| | 03:30 |
Public issue, date of publication.
Date that the issue was published.
| | 03:44 |
Let's try that as a string.
And finally a public issue_cover, which is
| | 03:52 |
the path to the file containing the cover
image.
| | 03:57 |
That will also be a string.
Save the issue_model.
| | 04:00 |
I now have two models, which is enough to
keep track of a simple collection of magazines.
| | 04:07 |
I built this wonderful place to put things
in but how am I going to get the data?
| | 04:10 |
| | Collapse this transcript |
| Saving magazines using active records| 00:00 |
One of the convenient and time saving
features of CodeIgniter is a loose
| | 00:03 |
implementation of the active record design
pattern.
| | 00:06 |
When I use CodeIgniter's active records, I
don't need to create classes to connect to
| | 00:10 |
each database table, but I should create a
model for each database table.
| | 00:14 |
And I can use active records to make the
models perform database operations.
| | 00:18 |
This system is database agnostic, meaning
all the query syntax is generated automatically.
| | 00:24 |
I can access CodeIgniter's database using
$this->db followed by commands such as
| | 00:30 |
insert Update and delete.
Rather than explicitly breaking down each
| | 00:34 |
command, I will demonstrate by example, by
updating the models to allow them to be persistent.
| | 00:39 |
I am also going to extend the bare minimum
of native CodeIgniter model class to be
| | 00:43 |
more functional by adding generic CRUD
functionality to it.
| | 00:47 |
This approach will also demonstrate how to
extend the CodeIgniter functionality.
| | 00:51 |
If I wanted to generically extend a
CodeIgniter class, a specific naming
| | 00:55 |
convention is required.
Instead of ci_, use my_.
| | 01:02 |
I'll switch to NetBeans and navigate to
the Core folder.
| | 01:05 |
I'm going to extend the CI model class,
so, I'll create a new file named, my_model.php.
| | 01:14 |
Class, my_model extends CI_model.
Now, your initial reaction may be to make
| | 01:26 |
this class abstract.
I'll be honest, that's what I wanted to do first.
| | 01:30 |
But CodeIgniter instantiates these classes
and abstract classes can't be instantiated.
| | 01:35 |
Therefore, it'll just have generic
functionality that won't work until it's extended.
| | 01:40 |
I'll start by adding a constant containing
the name of the database table that'll
| | 01:46 |
store records of a given model.
This is very helpful for organization and
| | 01:49 |
documentation as well.
I have to set a value, so, I'll just make
| | 01:53 |
it abstract, and just override it.
I will define a second constant containing
| | 01:58 |
the primary key for the table, const
DB_TABLE_PK equals abstract.
| | 02:06 |
Next, I am to going to create the four
CRUD methods.
| | 02:09 |
I will start with create, which will be an
insert method.
| | 02:12 |
I will make it private as I'm going to
have a more unifying save method that will
| | 02:18 |
determine whether to call insert or
update.
| | 02:21 |
That's in documentation, create record.
I'm going to use this DB to access active
| | 02:27 |
record, then the method insert, which
takes two arguments.
| | 02:33 |
The name of the table then questioned as a
string.
| | 02:37 |
And then object containing the arguments
that mapped to table columns that will be
| | 02:41 |
written, which will just be this.
The insert operation will not manually
| | 02:45 |
populate anything, so, I will have to
manually populate the model with the
| | 02:49 |
insert ID.
Fortunately there's a method for that.
| | 02:52 |
This curly brace this DB_TABLE_PK equals
this db, and then the method, insert_id.
| | 03:02 |
That's all that' needed.
And let's do a more complex one, which is
| | 03:06 |
the update method, which I'll also make
private, so, I can call it from the
| | 03:09 |
unified save method.
Private function update.
| | 03:13 |
Then give a documentation, update record.
This -> db -> update, takes three
| | 03:23 |
arguments: the name of the table to
update, which will be this db table, and
| | 03:28 |
an array or object containing the columns
or values to update, which will just be this.
| | 03:34 |
And the primary key of the table that will
be updated.
| | 03:36 |
This DB_TABLE_ PK, I'll use the constants
defined earlier to make a generic.
| | 03:42 |
To prepare for a loading method, I'm
going to make a helper that will populate
| | 03:46 |
the model from an array or standard class.
Which will take one argument, a mixed row.
| | 03:50 |
So, public function populate.
And I'll take a row.
| | 03:58 |
So, populate from an array or standard
class, param mixed row.
| | 04:08 |
And then for each row as key value, this
dollar sign key equals value.
| | 04:19 |
Next, I'll implement a method for loading
a single record from the database into a
| | 04:23 |
model that takes one argument.
I'll call it public function load,
| | 04:28 |
which'll take one argument, the ID of the
record.
| | 04:33 |
(NOISE) Load from the database.
Param will be an integer containing the
| | 04:40 |
primary key.
In this method, I will assign a variable
| | 04:43 |
called query to the result of this -> db
-> get_where, which retrieves a standard
| | 04:51 |
object with a result.
It takes two arguments, which is the table
| | 04:54 |
name again, DB_TABLE followed by an array
of the key value pairs that it will be
| | 04:58 |
matched against.
Which in this case will be just the
| | 05:02 |
primary key and the ID I want to look up.
This DB_TABLE_PK, assign to ID.
| | 05:10 |
I'll use the previously created populate
method to populate the object.
| | 05:14 |
So, this -> populate with query -> row.
The final method of CRUD is delete: public
| | 05:26 |
function delete.
Delete the current record, this -> db -> delete.
| | 05:36 |
The delete method takes the name of the
table, this DB_TABLE followed by an array
| | 05:41 |
similar to the where statement I used in
load.
| | 05:46 |
This time, I'll specify the argument
containing the primary key using the constant.
| | 05:51 |
This DB_TABLE_PK, this, this DB_TABLE_PK.
Finally, I'll unset this primary key once
| | 06:07 |
the deletion operation has occurred, as
the record won't exist anymore.
| | 06:11 |
Now that I have the full CRUD
functionality to find, let's make a public
| | 06:14 |
method for saving that will decide whether
to insert or update, public function save.
| | 06:21 |
Save the record.
If is set this primary key, use the update
| | 06:32 |
method, this -> update.
Otherwise, it's an insert.
| | 06:42 |
The final piece of common funtionality
that I'll impliment is an unfilter get
| | 06:46 |
which will retrieve all records from the
models database table.
| | 06:50 |
I'll include optional support for a limit
and off-set, which will be useful if I
| | 06:53 |
ever implement impugnation.
I'll start with documentation.
| | 07:00 |
Get an array of models with an optional
limit, offset.
| | 07:07 |
Param, int, limit, which will be optional.
Param, int, offset: optional, like if it's
| | 07:15 |
set, requires limit.
Return an array of models populated by
| | 07:24 |
database, keyed by the primary key.
Then, public function get, will limit
| | 07:29 |
defaulting to 0 and an offset also
defaulting to 0.
| | 07:37 |
So, if there is a limit, I'm going to
assign query to this -> db -> get.
| | 07:46 |
Which takes the name of the table, this ->
DB_TABLE, and an optional limit and offset.
| | 07:53 |
Limit offset.
So, if there is no limit query equals this
| | 08:00 |
db -> get, and then just this DB_TABLE,
which will return all rows.
| | 08:08 |
Now that the query's been performed, let's
build the return value.
| | 08:11 |
I'll start with an empty array.
Alright val equals array.
| | 08:15 |
Then, get the class of the current model,
get_class of this.
| | 08:21 |
I can iterate over the query using the
method result, which will return database
| | 08:26 |
rows, for each query -> result as row.
Create a new instance of the current class.
| | 08:35 |
So, model equals new class.
Populated with a helper function, so,
| | 08:42 |
model -> populate with row.
Then, added to the return value using the
| | 08:48 |
primary key.
Ret_val, row, and then this DB_TABLE_PK
| | 08:57 |
equals model.
The primary key is a nice shortcut if you
| | 09:01 |
don't want to use the constant or try to
remember what the key name is.
| | 09:05 |
Finally, return the ret_val, save the
file.
| | 09:10 |
This seems like a lot of work, and in
someways it is.
| | 09:13 |
However, it also highlights how to extend
native CodeIgniter classes, and it will
| | 09:17 |
save me from writing returning code in
returning my models.
| | 09:19 |
Let's give the models' four CRUD
functionality, open the publication model.
| | 09:24 |
Instead of CI model, we'll extend my model
instead.
| | 09:30 |
Then I'll add the constants containing the
table name, Const DB_TABLE equals publications.
| | 09:40 |
And the primary key, const DB_TABLE_PK
equals publication_id, save then open the
| | 09:49 |
issue model.
Again, I'll extend MY_MODEL const DB_TABLE
| | 09:56 |
equals issues, and const DB_TABLE_PK
equals issue id.
| | 10:05 |
Save again.
At this point the models have now four
| | 10:08 |
CRUD functionality using CodeIgniter's
active records.
| | 10:11 |
Let's test it out.
Open the magazine controller and navigate
| | 10:15 |
to the index method.
CodeIgniter requires that models be loaded
| | 10:19 |
before they can be used by using load.
I'll demonstrate two ways of working with methods.
| | 10:25 |
One by using this and the other by
instantiation.
| | 10:29 |
I'll start by creating the publication.
So, this -> load -> model, which has just
| | 10:36 |
one argument, the name of the model, which
will be Publication.
| | 10:40 |
When a model is loaded, the model is made
available through this using the class
| | 10:44 |
name as the property name.
I'm going to set the publication name
| | 10:48 |
using, this.
So, this -> publication ->
| | 10:52 |
publication_name equals Sandy shore.
That's all I need to create the record.
| | 10:59 |
So, I will save it.
This -> publication -> save.
| | 11:05 |
Let's see the result by dumping the model.
Echo tt pre, var_export, this ->
| | 11:14 |
publication, True.
Now close the pre and the tt.
| | 11:21 |
After I've created the publication, I'll
create a new issue.
| | 11:25 |
Same as before, I'll use load to get the
model.
| | 11:27 |
This -> load -> model, the model's name is
Issue.
| | 11:33 |
However, this time I'll instantiate a new
issue model and assign it to a variable.
| | 11:37 |
If I didn't use this load, the class would
not be found.
| | 11:41 |
Issue equals new Issue.
I'll set the publication id from the
| | 11:47 |
publication model.
Issue -> publication_id equals this ->
| | 11:52 |
publication -> publication_id.
I'm going to set the issue number to two.
| | 12:01 |
Issue -> issue_number equals 2.
And I'll set the date of the publication
| | 12:07 |
using PHP's date for February 1st, 2013.
Issue -> issue_date_publication equals
| | 12:15 |
date, 2013-02-01.
CodeIgniter is going to handle the
| | 12:21 |
conversion of MySQL's date format, which
is time saving.
| | 12:24 |
When I'm done, I'll save the issue; issue
-> save, and then debug the result.
| | 12:31 |
I'm just going to copy and paste that from
above, and var_export issue, TRUE.
| | 12:38 |
Save the controller, then return to the
browser and refresh.
| | 12:44 |
I can see two models.
The first containing publication id number
| | 12:48 |
one named sandy shore, and then issue id
number one with publication id number one,
| | 12:53 |
an issue number set as two, and the date
publication.
| | 12:58 |
Note that the issue cover which I didn't
set, is still null.
| | 13:02 |
We'll set the cover later in the course.
This way of looking at magazine back
| | 13:06 |
issues works, technically I guess, but is
this really nice to look at?
| | 13:10 |
Instead of dumping the result, let's
format it cleanly.
| | 13:13 |
| | Collapse this transcript |
| Displaying a magazine| 00:00 |
Earlier I created a view for presenting
content to separate presentation from logic.
| | 00:05 |
One of the key features of Codelgniter
views is the ability to pass data to the
| | 00:09 |
view for rendering in a standardized way.
Data can be passed either as an array or
| | 00:14 |
an object.
I'm going to create a view that renders a
| | 00:17 |
magazine, but firs tI'll need to pass data
to the view.
| | 00:20 |
When data is passed to the view the keys
and array or the parameters of an object
| | 00:24 |
are accessible as variables with the same
name, which can be really handy.
| | 00:29 |
Since an issue relates to a publication
I'm going to pass both the issue and the
| | 00:33 |
publication to the view.
So, I'll just use an array.
| | 00:36 |
A more complex implementation that I'm not
going to demonstrate but something to keep
| | 00:40 |
in mind would be to use lazy instantiation
and actually load the publication from the
| | 00:45 |
issue model.
I'll keep it simple for now.
| | 00:47 |
Switch the ID, and make sure that you have
the magazine controller open.
| | 00:52 |
In the index method, let's wipe everything
out, and start fresh.
| | 00:56 |
I'm going to start with the variable data
containing an array that I'll pass to the view.
| | 01:02 |
Then I'll load the publication model.
I'll instatiate a new publication, and
| | 01:14 |
load the first record by ID.
Publication, load, by the ID.
| | 01:20 |
Now that the publication has been
populated, i'll put it into the data array.
| | 01:24 |
Data, key named, publication, equals
publication.
| | 01:31 |
Next, we'll prepare the issue by loading
the model.
| | 01:34 |
This, load, model, issue.
I'll instantiate, issue, equals new issue,
| | 01:42 |
and load issue load one then I'll also put
this issue into the data array, data issue
| | 01:54 |
equals issue.
Now that all the data has been prepared,
| | 02:00 |
I'll render the magazine list field.
This, load ,view magazines, then, a new
| | 02:09 |
view that doesn't exist yet for rendering
a magazine back issue.
| | 02:12 |
For the second argument I'll pass the data
array.
| | 02:15 |
So, this load view, magazine, and then
data.
| | 02:22 |
Save the controller, then navigate to the
views folder and create a new file for the
| | 02:30 |
magazine view called magazine.php.
Remember, a view is HTML with a little bit
| | 02:37 |
of php, so I'll start off with a div with
a class of magazine.
| | 02:43 |
On a new line I'll create the container
for the publication name and issue with a classname_issue.
| | 02:48 |
Now for a little PHP I'm going to echo the
publication name but as a developer I know
| | 02:55 |
that I can't ever trust user input.
To sanitize the display, I'll use a code
| | 03:01 |
ignitor, common function.
Common functions are available at any
| | 03:05 |
point during execution.
In this instance, I'll use HTML escape
| | 03:10 |
which is a shortcut for HTML special
chars.
| | 03:13 |
HTML accepts either an array of input or
just a string.
| | 03:18 |
When I pass an array of data to the view,
CodeIgniter makes each key available as
| | 03:22 |
the variable with the same name.
I want the publication name, so I'll
| | 03:29 |
access publication and the property
publication name.
| | 03:34 |
Close parenthesis, add a semicolon, and
close the PHP tag.
| | 03:39 |
On a new line, I'm going to display the
issue number.
| | 03:42 |
So, I'll start with a hash tag, then I'll
open a PHP tag, then echo, html, escape to
| | 03:48 |
issue parameter issue number and semicolon
and close out.
| | 03:54 |
And then make sure the div is closed out
as well.
| | 03:58 |
Finally I'll create a div that'll contain
the issues_data_publication, class date.
| | 04:06 |
I'm just going to echo, HTML escape the
issue, issue date publication for now.
| | 04:16 |
Make sure that the date div is closed, and
the magazine div is closed.
| | 04:20 |
Save, then go back to the browser, and
load the Sandbox page.
| | 04:24 |
Now I see my magazines, and my one lonely
back-issue of Sandy Shores.
| | 04:30 |
It's not very pretty, but it's functional,
and shows that I'm able to store and
| | 04:34 |
retrieve persistent data, then render it
in a standardized manner.
| | 04:38 |
In this chapter, I've described what a
model is and how it's used.
| | 04:42 |
Then modelled the two components of a
magazine, the publication and a back issue.
| | 04:46 |
Then I demonstrated how to save a magazine
using Active Record and added common
| | 04:52 |
functionality to a base coding meta class.
Then finally rendered a magazine by
| | 04:56 |
passing data to a view where I escaped
user input so it doesn't break HTML or
| | 05:01 |
introduce security risks.
In the next chapter, I'm going to use
| | 05:05 |
another major feature of Coding Nyder,
known as Libraries.
| | 05:08 |
| | Collapse this transcript |
|
|
3. Adding Functionality with LibrariesWhat are CodeIgniter libraries?| 00:00 |
In computer science, a library is a
collection of functionality that serves a
| | 00:04 |
specific purpose with a well defined
interface and logical structure.
| | 00:07 |
CodeIgniter comes with several dozen
libraries for common tasks.
| | 00:11 |
Each implemented as a class.
Examples of classes include the input
| | 00:15 |
class, form validation class and HTML
table class.
| | 00:20 |
To use a library, it needs to be
initialized within a controller using the
| | 00:24 |
following initialization method: this ->
load ->library, followed by a string
| | 00:27 |
containing the machine name of the
library.
| | 00:30 |
For example, form_validation.
Multiple libraries can be initialized at
| | 00:36 |
once by passing an array of strings
containing the names of the libraries to load.
| | 00:40 |
Such as form validation and table.
Each library has a dedicated page within
| | 00:45 |
the CodeIgniter User Guide, which includes
usage examples and a function reference.
| | 00:50 |
In this chapter, I'm going to allow users
to add magazines using a form, then
| | 00:54 |
validate those forms including some custom
validation.
| | 00:58 |
After that, I'll use a number of
CodeIgniter libraries to accept user input
| | 01:02 |
and list magazines in a generated HTML
table.
| | 01:05 |
Let's get started.
| | 01:06 |
| | Collapse this transcript |
| Creating a form to add magazines| 00:00 |
In order to implement a validating form in
CodeIgniter, I'll need three things.
| | 00:04 |
First, a controller function that contains
the form logic, like processing submitted data.
| | 00:10 |
Second, a view that contains the form
itself, including a place for displaying messages.
| | 00:14 |
And finally, a view for a message that
will be shown upon successful submission.
| | 00:19 |
Once I have those pieces, I can then add
the validation logic.
| | 00:23 |
I'm going to create a forum to add
magazines and I'll start with the controller.
| | 00:27 |
Within Net beans open the magazine
controller.
| | 00:31 |
Let's add a new method for adding a
magazine called add public function add,
| | 00:38 |
give it a little bit of documentation.
Add a magazine.
| | 00:43 |
One of the parts of the magazine is the
publication.
| | 00:46 |
While it'd be great if users could
remember data base identifiers, they tend
| | 00:51 |
to get lazy and need all the help they can
get.
| | 00:54 |
Therefore, I'll populate the list of
available publications on their behalf
| | 00:57 |
using the publication model.
Start by loading the model, populate publications.
| | 01:05 |
This load model, and I'll give it the
publication as the argument.
| | 01:11 |
Then I'm going to use the get method,
which returns an array of populated models.
| | 01:16 |
Publications equal this, publication get.
Now that I have the data, I'll populate
| | 01:24 |
form options.
Publication, form, options equals array,
| | 01:31 |
foreach the publications, as ID,
publication.
| | 01:34 |
Assign the option by ID to the publication
name.
| | 01:41 |
So publication, form options, ID equals
publication.
| | 01:46 |
Publication_name.
When complete, load a view using this,
| | 01:55 |
load view.
With a name of magazine_form, we'll create
| | 02:01 |
the view in a moment.
I'm going to pass it an array.
| | 02:05 |
Containing one key,
publication_form_options assigned to the $publication_form_options.
| | 02:13 |
Remember to add the semicolon and save.
I'll add the validation logic later.
| | 02:19 |
Next I'll create the view for the form.
So I'll navigate to the Views Folder and
| | 02:24 |
create a new file called magazine_form.
Clear out the content, then let's create a
| | 02:32 |
form in good old fashioned HTML.
Form, method equals post.
| | 02:37 |
I'll start with a div, and then a label
for publication, ID with a more human
| | 02:47 |
readable publication name.
Start a select tag with a name of
| | 02:54 |
publication ID.
Select, name equals publication ID.
| | 03:00 |
Now for a little PHP.
Let's iterate through the publication form
| | 03:03 |
option, for each publication form options
as publication id, publication name.
| | 03:12 |
I'm going to echo an option with a value
of the HTML.
| | 03:22 |
Escaped publication ID.
Followed by the html escape publication
| | 03:33 |
name and close the option.
Close out the PHP tag at the end.
| | 03:39 |
Make sure that the select is closed and
the DIV.
| | 03:43 |
Hm, that seems like a lot of work for a
lowly select list.
| | 03:46 |
I wonder if there is a faster way.
Anyway, let's continue with the input text
| | 03:50 |
for the issue number.
Div, then label for equals issue
| | 03:57 |
underscore number.
For the human readable name issue number.
| | 04:04 |
So, for the input.
Type equals text, name is issue number and
| | 04:12 |
the value.
Right now we don't need any default value,
| | 04:16 |
so we'll just leave it blank.
And close out the div.
| | 04:20 |
The last bit of data that I'll need is the
date that the issue was published.
| | 04:24 |
So, div then label for issue date
publication and then date published, human
| | 04:35 |
readable label.
Then again this will be input type equals
| | 04:40 |
text, the name is issue date publication
and the value is empty.
| | 04:48 |
Was that the div?
Finally I'll add a submit button.
| | 04:51 |
Div input type equals submit, and the
value, it's just going to say save.
| | 05:01 |
Close out the div and the form.
Save the magazine form.
| | 05:03 |
One more piece is needed.
The success message.
| | 05:08 |
Create a new view named
Magazine_form_success.php.
| | 05:17 |
I'll just say div class equals alert and
then alert-success say magazine created
| | 05:26 |
and close the div.
Save the success farm.
| | 05:29 |
Let's see how it looks so far by switching
to the browser and navigating to index.php
| | 05:38 |
magazine add.
I see a very bare bones form with a
| | 05:43 |
publication name select list.
Text input for issue number, and date
| | 05:48 |
published, and a Save button.
Type issue three into issue number, and
| | 05:52 |
click Save.
And the input has disappeared.
| | 05:55 |
We have no logic yet, so it's actually
performing perfectly well.
| | 05:58 |
It's not very useful, on the other hand,
so let's add some validation using the
| | 06:02 |
Form Validation library.
| | 06:03 |
| | Collapse this transcript |
| Validating user input with the form validation library| 00:00 |
Now that the two views of the controller
have been set up, I now have something
| | 00:03 |
that I can use the Form Validation Library
with.
| | 00:06 |
Here's the control flow at a high level.
First, I'll load the form_validation library.
| | 00:11 |
Then, I'll set the validation rules for
each form element.
| | 00:15 |
When that's complete, I'll execute the
validator to see if it passed or not.
| | 00:19 |
With that answer, the application can
decide what to do based on validation success.
| | 00:23 |
I'm going to get started by returning to
the IDE.
| | 00:25 |
I'll open the magazine controller, and
navigate to right before the view is displayed.
| | 00:32 |
I'll start by loading the form validation
library.
| | 00:35 |
So, this, load, library, with a name,
form, underscore, validation.
| | 00:42 |
Next I'll call a method called set rules.
Set rules takes an array of arrays that
| | 00:48 |
contain three key value pairs.
The field which is the form fields name, a
| | 00:54 |
label which is a human readable label that
will be shown on failures and rules.
| | 00:58 |
A string containing the names of form
validation call back functions.
| | 01:02 |
There's a complete list of validators that
ship with CodeIgniter at the following URL.
| | 01:07 |
For the time being we'll start slow and
build up.
| | 01:10 |
This form validation set underscore rules.
I'll pass an array.
| | 01:18 |
The first array will be for publication
Id.
| | 01:23 |
Array, field, publication_id and then the
label will just be publication.
| | 01:30 |
The publication will be required.
Fortunately there's a validator callback
| | 01:35 |
named required which will just check to
see if content has been set.
| | 01:38 |
So, rules, required.
That was pretty straightforward.
| | 01:48 |
I'll add a validator for the issue_number
as well.
| | 01:53 |
Array, field, issue_number, label Issue
number.
| | 02:01 |
This time for the rules I'm going to chain
two validators together using another
| | 02:07 |
validator that ships with CodeIgniter that
checks if input is numeric.
| | 02:11 |
To specify multiple validators separate it
with a pipe character, so required and
| | 02:17 |
then a pipe and then is underscore
numeric.
| | 02:23 |
Finally, the publication date.
Array, field, issue, date, publication.
| | 02:26 |
The label is publication date.
Now, there are no date validators that
| | 02:29 |
ship with CodeIgniter, so I'll use a
custom callback.
| | 02:42 |
To do that, start with rules.
The publication date is required, but for
| | 02:49 |
the custom callback.
I'll need to start the method name with a
| | 02:52 |
callback_ followed by the name of the
actual method, which I'll call date_validation.
| | 02:59 |
The callback is a method in the current
controller, which I'll create in a moment.
| | 03:04 |
By default, the error messages are wrapped
in a paragraph tag.
| | 03:07 |
Let's spruce things up a little bit by
setting the error message to limiters.
| | 03:09 |
The method takes two arguments.
The opening and the closing delimiter.
| | 03:15 |
This form validation.
Set_error_delimiters.
| | 03:22 |
Have an opening DIV for the class of
alert, and alert-error, then followed by a
| | 03:32 |
closing DIV.
Finally, I'll execute the form validator
| | 03:36 |
using the method run.
This, form, validation, run.
| | 03:40 |
It returns Boolean, true or false, so I
can use it with an if statement.
| | 03:46 |
So we'll start off if the form does not
validate.
| | 03:54 |
We'll show the regular form else if the
form did validate, this, load, view,
| | 04:04 |
magazine form success.
Now that we've completed the logic so far,
| | 04:10 |
let's create a callback function to
validate the date.
| | 04:13 |
Within the controller, create a new public
function called date validation that takes
| | 04:22 |
a string input.
Add a little bit of documentation.
| | 04:28 |
This is a date validation call back, takes
a string and it returns a Boolean value.
| | 04:39 |
True if it passes, fault if it fails.
I'm going to use the PHP function check
| | 04:43 |
date for validation.
To do that I'll explode the input on dash,
| | 04:48 |
so test date equals explode and then
input.
| | 04:54 |
So if then not and I'm going to surpress
errors and warnings from check eight.
| | 05:00 |
Test date 1, test date 2, and then test
date 0.
| | 05:08 |
So if it fails that check I'm going to use
one of the methods in form validation
| | 05:14 |
known as sent message.
So this form validation set message, which
| | 05:21 |
takes two arguments.
The first is a string containing the field
| | 05:24 |
name, which in this case is, date
validation, followed by a string
| | 05:29 |
containing the message, itself.
The, and I can use a percent, S, that will
| | 05:34 |
be replaced with the human readable label
set earlier.
| | 05:37 |
So the percent S field must be in year,
month, day, format.
| | 05:45 |
Since it failed return Boolean false,
otherwise it succeeded so return true.
| | 05:50 |
Save the controller and switch to the
browser.
| | 05:55 |
For the issue number type A which won't
validate and click save.
| | 06:00 |
There's no message, because the form
validation method doesn't produce any
| | 06:04 |
automatic output.
Which gives developer control over how the
| | 06:07 |
application performs.
Go back to the IDE, and open the Magazine
| | 06:13 |
Form view.
At the very top, above the form itself,
| | 06:17 |
I'm going to Echo a function provided by
the validation library that will render
| | 06:23 |
the errors, validation errors.
Save then return to the browser and try
| | 06:31 |
filling validation again.
This time I see the error messages I was expecting.
| | 06:36 |
Lets try to pass validation, so, issue
number three.
| | 06:41 |
And it was published on 2013, March 1st.
Click save.
| | 06:47 |
Magazine created, success.
Except it didn't actually create it,
| | 06:52 |
because one more piece is needed.
Persistence.
| | 06:56 |
| | Collapse this transcript |
| Getting user input securely| 00:00 |
The CodeIgniter input class, which is
initialized automatically, serves two purposes.
| | 00:05 |
Securely pre-processing global input data,
and providing helper functions for getting
| | 00:09 |
input data.
Among other things, it destroys global
| | 00:12 |
variables if register_globals is turned
on.
| | 00:15 |
Filters the GET, POST and COOKIE array
keys, and provides optional cross site
| | 00:20 |
scripting attack filtering.
Let's go back to the magazine controller.
| | 00:24 |
Before I show the success message, let's
save a new magazine issue.
| | 00:28 |
I'll start by loading the model.
This -> load -> model issue.
| | 00:36 |
Then, I'll create a new instance of the
issue model.
| | 00:39 |
Issue equals new issue.
I'll set the publication ID, issue ->
| | 00:45 |
publication id equals this, and I'm
going to use the input class post method
| | 00:51 |
with one argument.
So input -> post, a string containing the
| | 00:56 |
element I'm looking for, which is the
publication id.
| | 01:00 |
I'll do the same for the issue_number,
equals this -> input -> post ->
| | 01:09 |
issue_number, and the issue date of
publication.
| | 01:13 |
Issue -> issue -> date publication equals
this -> input -> post Issue_date_publication.
| | 01:25 |
Tell the issue to save itself.
Let's make this success message a tiny bit
| | 01:32 |
more verbose by passing the issue to the
view.
| | 01:34 |
So, comma array, set a key called issue,
and assign it to the issue itself.
| | 01:42 |
Save the controller, then open the
magazine form success view.
| | 01:45 |
I'm going to echo the HTML escaped issue,
Issue ID.
| | 01:50 |
So, magazine number PHP echo html_ escape
issue -> issue_id.
| | 01:59 |
Close it out, put in a space, and then
save the view.
| | 02:03 |
Let's go back to the browser and refresh.
It'll ask me if I wish to confirm the
| | 02:10 |
re-submission of the form.
Say yes.
| | 02:12 |
Now, I see a message saying that magazine
number two has been created.
| | 02:16 |
However, if I navigate back to the root
page, I don't see a list containing the
| | 02:22 |
magazines I created, I only see the one
that is being loaded by ID.
| | 02:25 |
Let's fix that.
| | 02:27 |
| | Collapse this transcript |
| Listing magazines with tables| 00:00 |
The HTML table class, generates HTML
tables from arrays or database results sets.
| | 00:06 |
The table class is initialized in the
controller, using this load library table.
| | 00:12 |
Once it's loaded it can be accessed using
this table.
| | 00:15 |
While I can technically call the library
class from within the controller, it's
| | 00:19 |
best practiced to keep display in the
view.
| | 00:23 |
Going back to the IDE, I'm going to take a
look again at the magazine controller
| | 00:27 |
index method.
Right now there's a bunch of hard coded
| | 00:30 |
stuff, instead I'm going to replace it
with something a lot more flexible.
| | 00:35 |
I'll start by loading the library for
table.
| | 00:36 |
This load, library, table.
Next, I'm going to build an array of
| | 00:44 |
magazines for table library to render,
magazines equals array, I will load the
| | 00:50 |
models for both the issue and the
publication by passing in a array, this
| | 00:55 |
load model then a array containing issue
and publication.
| | 01:03 |
Then I'll get all the issues that are
known in the database.
| | 01:05 |
Issues, equals, this, issue, get, foreach,
issues as issue, instantiate a
| | 01:16 |
publication, publication equals new
(SOUND) .
| | 01:21 |
Publication.
Load it with a publication ID from the issue.
| | 01:24 |
So, publication load, issue, location ID.
Then, add an array to the magazine's array
| | 01:33 |
with the values in the following order.
So, magazines equals array, publication.
| | 01:40 |
Publication name, the issue, issue number
and issue, issue date publication.
| | 01:53 |
Finally, pass the magazines view a
variable with the magazines you can remove
| | 01:58 |
all this data, and then pass magazines in
array containing magazines and the
| | 02:07 |
contents of magazines.
We no longer need a single display of the
| | 02:12 |
magazine so just delete it and save.
Next, I'll go to the magazines view.
| | 02:18 |
I don't have to do anything to initialize
the table, it's already been done.
| | 02:22 |
However, I do want to set a header row and
I'll use a method called set heading to do that.
| | 02:28 |
It just sets th elements with a string
that I specified.
| | 02:30 |
Open up, php, this table set heading
Publication, issue, and date.
| | 02:42 |
I'll pass the magazines variable to the
table generation method and echo the result.
| | 02:47 |
Echo, this, table, generate, magazines.
That's all that's needed.
| | 02:54 |
Save, and then go to the browser and
refresh.
| | 02:58 |
I see a nice table of issues listed.
View the source.
| | 03:03 |
Notice that it's even creating a proper t
head and t body using th for the headers.
| | 03:08 |
You can probably believe the number of
times that I've written that markup by hand.
| | 03:12 |
This is very convenient.
Close the source.
| | 03:16 |
The application is coming along nicely.
And building it in some increasingly
| | 03:20 |
usable functionality, but it's still
looking kind of well, unstyled/g.
| | 03:24 |
Lets add Twitter bootstrap to the mix to
improve the look and feel.
| | 03:28 |
To save time, I performed a little
customization at Twitter bootstrap to
| | 03:31 |
separate things out in implemented at bare
bones navigation system.
| | 03:35 |
Open up your exercise files, and copy the
folder named bootstrap to sandbox, into
| | 03:43 |
application, views.
Then copy css, image, and js.
| | 03:56 |
And put that in the web root.
Going back to the IDE, let's take a look
| | 04:01 |
at the magazine control.
Note that since I put the bootstrap into a
| | 04:04 |
folder, I'm going to start the view name
with the name of the folder, slash, then
| | 04:08 |
the name of the actual view.
This, load, view, bootstrap slash header
| | 04:17 |
and then add at the very end the footer.
I'm going to do the same for the add method.
| | 04:25 |
For the header and the footer.
Save.
| | 04:35 |
Then reload the browser.
Things should look a lot better now with
| | 04:39 |
standardized styling.
If I go to add a magazine, the error
| | 04:45 |
messages will look properly styled.
I'll try adding a magazine.
| | 04:48 |
Sandy Shore issue number 4, published in
2013, 04-01.
| | 04:54 |
And save.
Cool.
| | 04:56 |
The success message is also properly
assigned.
| | 04:59 |
In this chapter I've defined what
CodeIgniter libraries are and how to use them.
| | 05:03 |
I then created a form to add magazines.
With that form, I validated user input
| | 05:08 |
using the form validation library.
Then, securely took user input and saved
| | 05:13 |
it in data base.
Finally, i listed the saved magazines
| | 05:18 |
using (INAUDIBLE) tables.
libraries are useful collection of tools
| | 05:21 |
in coding but they are not the only
collection there are also helpers which
| | 05:25 |
serve different purpose
| | 05:26 |
| | Collapse this transcript |
|
|
4. Saving Time with HelpersUsing a helper to perform tasks| 00:00 |
Helper files are similar to libraries in
that they're a collection of
| | 00:03 |
functionality, but they're different in
that they're not object oriented.
| | 00:07 |
Instead, they're procedural functions that
perform one specific task with no
| | 00:11 |
dependence on any other function.
Examples of helper function files include
| | 00:16 |
a date helper, form helper and URL helper.
Helper files aren't loaded by default.
| | 00:21 |
So, if I wanted to use one, I'd have to
explicitly load it from the controller
| | 00:25 |
using the helper method.
Similar to loading libraries, I can either
| | 00:29 |
pass a string or an array as the argument.
If I needed help getting a date, I just
| | 00:34 |
use the string date, this -> load ->
helper, date.
| | 00:38 |
If I wanted to load multiple helpers at
once, I'd pass it in an array of strings
| | 00:42 |
like date, form, url.
Now, let's revisit that form, but this
| | 00:47 |
time I'm going to use helpers.
| | 00:49 |
| | Collapse this transcript |
| Avoid reinventing the wheel with the Form Helper| 00:00 |
The form helper is a great shortcut for
quickly building forms.
| | 00:03 |
Instead of writing raw HTML I can greatly
simplify the view by using the form helper
| | 00:08 |
functions to generate the markup.
The form helper functions return html, so
| | 00:13 |
they should be used in the view, not in
the controller.
| | 00:16 |
I will have to load the helper from the
controller.
| | 00:19 |
I'm going to switch back to Netbeans.
And go to the add method if I'm not
| | 00:23 |
already there.
And add the method to load the form helper.
| | 00:27 |
So, this, load, helper, form.
Save the controller, then open the
| | 00:34 |
magazine form the first line echoing the
validation errors is good so let's leave
| | 00:39 |
that alone.
However I'm sorry to say that everything
| | 00:42 |
else is going to get replaced.
Its good to have perspective to know that
| | 00:45 |
there's than one way to perform a task.
I'm going to start with a new form using
| | 00:51 |
the function form open PHP echo form open.
I have the ability to specify a particular
| | 00:58 |
action and attribute.
But since it's posting to the same place I
| | 01:00 |
can leave the action off and form open
defaults to post so there's really nothing
| | 01:05 |
else to do, and close the tag.
We don't need the duplicate form so remove that.
| | 01:11 |
Next the label for publication name,
surely there's a better way.
| | 01:14 |
Yes there is, using the echo form label,
PHP, echo, form, label.
| | 01:22 |
It takes two arguments, human readable
name and the identifier, publication, id
| | 01:29 |
and close the tag.
Select lists are referred to as drop downs
| | 01:35 |
with encoding data/g, which is a little
funny.
| | 01:37 |
PHP, echo, form dropdown.
Which just takes the form element name,
| | 01:43 |
publication ID, followed by an array of
option labels keyed by value.
| | 01:48 |
Just as I did before.
So publication, Form options, the third
| | 01:54 |
argument is the default value.
I'm going to use another form helper
| | 01:58 |
called set value, which grabs the value
from the post array, great for failed
| | 02:02 |
formula submissions.
So set value and then the key publication
| | 02:08 |
ID and close that out.
I'll completely remove the redundant html
| | 02:14 |
contents, so that's one, two, three, four,
five, six, seven lines of code that have
| | 02:19 |
been saved.
Next, I'll replace the label for the issue
| | 02:22 |
number, PHP echo form label issue number,
followed by the identifier, issue number
| | 02:34 |
and close the tag.
I'll use form input which defaults the
| | 02:37 |
text input for the issue number.
Php echo form input.
| | 02:43 |
The first argument takes the form element
name, which is issue number, and the
| | 02:47 |
second is the default value.
I'll use set value again, passing it,
| | 02:52 |
issue number.
To populate it on failed submissions.
| | 02:56 |
Close out the php tag, and remove the
unnecessary HTML.
| | 03:00 |
We'll do something very similar for the
issue date publication.
| | 03:11 |
And date published.
Replace the label.
| | 03:15 |
And remove the unnecessary html.
The last element will be the submit
| | 03:21 |
button, which we'll use form submit.
PHP echo form submit, save with label, save.
| | 03:31 |
Semi colon, and close the PHP tag.
I'll close the form with php echo
| | 03:38 |
form_close and save the viewing.
Doesn't this look a lot cleaner?
| | 03:44 |
Rather than a mix of loops and hard coded
html.
| | 03:47 |
There's some clean html for designer to do
their magic to and some simple php
| | 03:51 |
function calls.
Go back to the browser and go to the add
| | 03:55 |
form and intentionally fail validation by
submitting issue number kitty.
| | 04:01 |
This time the default value is set.
Very cool.
| | 04:04 |
Let's kick things up a notch with the
ability to upload cover images.
| | 04:09 |
| | Collapse this transcript |
| Uploading images with the File Uploading class| 00:00 |
File uploads can be a pain, but
CodeIgniter tries to eliminate some of the
| | 00:03 |
more obnoxious parts using the file
uploading class which is especially
| | 00:08 |
helpful for images.
File uploads consist of the following process.
| | 00:12 |
First, the file form element is displayed
to the user.
| | 00:15 |
Then, the form is submitted and the file
is uploaded.
| | 00:19 |
Based on file upload preferences such as
image height, width or maximum size, the
| | 00:23 |
file is validated.
When validation is past, the file metadata
| | 00:28 |
is available for use.
I'm going to allow users to upload cover
| | 00:31 |
images of the back issues.
First, switch to a terminal and navigate
| | 00:37 |
to the root directory of your CodeIgniter
installation, verify that you're in the
| | 00:40 |
right place.
Next, make a directory that you can use to
| | 00:44 |
upload files to.
Mkdir, space, upload.
| | 00:49 |
Next, set the permissions on that
directory.
| | 00:51 |
Chmod 755 is a best practice.
In a worst-case scenario, use 777 but this
| | 00:58 |
is almost never necessary and not
recommended, as it's a big security risk.
| | 01:04 |
Now that the designation exists, I can go
back to the IDE.
| | 01:07 |
Open up the magazine controller, I'm
going to create a configuration array for
| | 01:12 |
file uploads.
This also handles validation so, this part
| | 01:15 |
is fairly important.
There's a comprehensive list of all the
| | 01:18 |
options in the user guide at ellislab.com.
So, starting with configuration array,
| | 01:24 |
config equals array.
The first step is the upload
| | 01:29 |
underscore_path which is just upload.
Next, specify the allowed file extension types.
| | 01:37 |
Allowed_types and we'll set that to gif,
jpg and png.
| | 01:43 |
Then, the maximum file size in kilobytes,
max_size I'll set it to 250.
| | 01:53 |
The maximum width and pixels max_width
1920 and maximum height max_height and
| | 02:04 |
we'll set that to 1080.
Finally, the upload library can be loaded
| | 02:09 |
with a configuration, this, load, library,
upload and pass it to config.
| | 02:17 |
Then navigate to the form validation.
The form validator doesn't actually check
| | 02:26 |
file uploads, which is a bit goofy.
Instead, I'm going to have to explicitly
| | 02:30 |
specify a file upload check, using
do_upload and the name of the form element.
| | 02:35 |
If you're uploading multiple files, you
will have to do multiple do_uploads.
| | 02:40 |
If you leave out the name of the form
element, it won't work.
| | 02:44 |
Finally, I'm going to make file upload
optional, by checking the files array,
| | 02:48 |
then preforming validation.
As ugly as this looks, this is the
| | 02:51 |
recommended method.
So, I'm going to navigate to the form
| | 02:55 |
validation run.
I'll start with check_file_upload equals false.
| | 03:03 |
if is set, the FILES super global,
issue_cover error and files issue_cover
| | 03:13 |
error not equals 4, check_file_upload
equals true.
| | 03:20 |
Then, we'll change the if on the
validation run.
| | 03:26 |
If the form validation fails or
check_file_upload and not this, upload,
| | 03:36 |
do_upload using the key issue_cover, we'll
wrap this whole section in parenthesis and save.
| | 03:49 |
The last piece of the puzzler for the
controller, is what to do with the
| | 03:52 |
uploaded file.
Just before issue_save, get the uploaded
| | 03:58 |
file metadata, upload_data equals this,
upload_data.
| | 04:04 |
If it exists, set the issue_cover to the
file name.
| | 04:07 |
If is set, upload_data, key, file_name,
issue, issue_cover equals upload_data, file_name.
| | 04:21 |
Save the controller, then go to the
magazine form view.
| | 04:26 |
Immediately following the echoed
validation errors, I'll need to explicitly
| | 04:29 |
display the upload errors.
Yes, it's separate from the form upload.
| | 04:33 |
PHP echo, this, upload, display_errors.
And it's going to take two arguments which
| | 04:43 |
is the opening, div, class, equals alert,
alert-error and close and followed by the
| | 04:52 |
closed div.
Close the PHP tag, and then I will need to
| | 04:58 |
switch the form open to a form open multi
part to handle the uploaded files.
| | 05:05 |
Before the Submit button, let's create the
form element for the file upload.
| | 05:10 |
Div, PHP echo form_label, cover scan, then
issue_cover is the name.
| | 05:19 |
Close the PHP.
And PHP echo.
| | 05:23 |
Then I'm going to use the form helper,
form_upload, with the name of the field as
| | 05:28 |
an argument.
form_upload, issue_cover.
| | 05:34 |
Save, then go back to the browser.
Let's click, Add, to see the new file form.
| | 05:39 |
Let's create issue number five of Sandy
Shores, with a publish date of 2013-06-01.
| | 05:46 |
Click save and it should be successful as
the file upload is optional.
| | 05:51 |
Let's go back to Add, and add issue number
two of Sandy Shores with a date
| | 05:57 |
2013-02-01, but this time I'll upload.
Go to Assets > NotAnImage.txt.
| | 06:06 |
Click Open, and Save.
It'll be correctly rejected as disallowed.
| | 06:11 |
Finally upload the JPEG version of issue
number two And that should work, success.
| | 06:19 |
Check the upload directory as well.
Now, if I go back to the magazine list, I
| | 06:28 |
can see that there's a duplicate entry for
issue number two and I can't see the covers.
| | 06:32 |
Mm-hm, maybe I should do something about
that.
| | 06:35 |
| | Collapse this transcript |
| Viewing and deleting magazines| 00:00 |
I've been making solid progress but it's
time to focus, and put some final touches
| | 00:04 |
on this application.
There's two major pieces missing.
| | 00:06 |
The ability to view magazines, and delete
an individual magazine.
| | 00:11 |
In some ways, the two pieces of
functionality are very similar.
| | 00:14 |
In that they both require something to get
an issue_id then some kind of action on a
| | 00:18 |
loaded model.
I'm going to start by adding links to view
| | 00:22 |
and delete from the magazine list.
Edit the magazine controller and at the
| | 00:26 |
top of the index function add a load
helper to load the URL helper.
| | 00:34 |
This load, helper, URL.
It would be helpful to see whether a
| | 00:39 |
magazine has a cover associated with it.
So at the end of the 4H loop lets add a
| | 00:44 |
column with a simple Y or N if there is a
cover Issue issue_cover switch yes or no.
| | 00:53 |
I'm going to use the anchor helper
function to generate links based on the
| | 00:58 |
local URL as a final column in the magaine
table.
| | 01:01 |
I'll make links to both view and edit.
The first argument f anchor is the path
| | 01:06 |
which will be magazine/view.
And then I'm going to pass it the issue.
| | 01:12 |
Issue_id.
The second is the text view.
| | 01:18 |
I'll separate them with a simple pipe.
Anchor magazine/delete and then add the
| | 01:26 |
issue, issue_id" then delete.
Save the controller, then switch to the
| | 01:34 |
magazine's view.
Add the additional headings Cover and Actions.
| | 01:38 |
Cover, Actions.
Save the view.
| | 01:43 |
Then let's take a look at the browser.
Refresh the magazines list and it looks a
| | 01:48 |
little bit more functional.
Cool, I can see whether or not a cover is
| | 01:52 |
associated with a magazine now.
And there's links to delete and view.
| | 01:55 |
Let's make those functional.
Switch back to the id.
| | 02:00 |
Go back to the magazine controller.
I'm going to start with a new method for view.
| | 02:06 |
Public function view.
We'll take one argument, the issue_id.
| | 02:12 |
And documentation, view a magazine.
Type will be an integer.
| | 02:23 |
The routing system will automatically pass
the argument so I don't need to make any
| | 02:27 |
additional changes on that side.
I'll start by loading the HTML helper,
| | 02:31 |
I'll need it in a moment,
this->load->helper, html.
| | 02:37 |
Then I'll load the header itself,
this->load->view, bootstrap/header then
| | 02:45 |
the models for issue and publication,
this->load->model pass it an array
| | 02:53 |
containing issue, publication.
I'm going to try to load an issue by its id.
| | 03:02 |
Issue equals new Issue.
Then issue load issue_id.
| | 03:13 |
if an issue can't be loaded show a 404
error using one of the common functions
| | 03:17 |
show_404 which will does just that and
exit.
| | 03:20 |
If not, issue, issue_id, show_404.
Otherwise, we have an issue so load the publication.
| | 03:34 |
Publication equals new Publication, then
publication->load the issue, publication_id.
| | 03:46 |
I'm going to pass both to the magazine
view created earlier.
| | 03:50 |
This, load->view, magazine, pass in an
array.
| | 03:59 |
The key issue and publication.
Finally show the footer, let me copy the
| | 04:13 |
header, make a small change, footer.
Save the controller then edit the magazine view.
| | 04:23 |
Right before the closing div, I'm going to
add some logic.
| | 04:27 |
Php, if, issue as a issue_cover and we'll
post the php, show a div with class cover,
| | 04:44 |
close the div, indent, php.
I'm going to use a function from the html
| | 04:56 |
helper called image, which will generate
an image tag based on a path.
| | 05:01 |
So echo Image, upload/.and then
issue->issue_cover.
| | 05:08 |
Make sure the if is closed out, and save.
I'm going to switch to the browser to see
| | 05:17 |
the view in action.
Click View on the item with the cover.
| | 05:22 |
Neat, the cover is now rendered.
Now to clean it up a bit, I'll implement
| | 05:26 |
the last missing functionality, a delete.
Go back to the magazine controller.
| | 05:30 |
Start a new method called delete.
Public function delete, which takes one
| | 05:36 |
argument, an issue_id.
Always remember the documentation.
| | 05:42 |
Delete a magazine which takes an integer.
I don't need any helpers so I'll just
| | 05:49 |
start off with loading the header.
This load->view bootstrap/header then the
| | 05:58 |
model for the issue only.
This->load model->array issue, instantiate
| | 06:08 |
a new issue, issue equals new Issue and
try to load it, issue load issue_id.
| | 06:20 |
Again if the issue can't be found show
404, otherwise delete the issue using the
| | 06:27 |
common method delete, issue delete.
Show a success message by using a new view
| | 06:34 |
magazine deleted which I will create it in
just a moment passing just the issue_id,
| | 06:40 |
this->load->view magazine deleted an array
containing issue_id, issue_id.
| | 06:53 |
Finally show the footer, save the
controller then create a new view Named magazine_deleted.
| | 07:06 |
This is going to be a one liner, div class
equals alert, alert-success magazine
| | 07:19 |
number then php echo html_escape Issue_id.
Close that out and then the verb which
| | 07:33 |
will be deleted.
Save the new view and let's test it.
| | 07:40 |
From the browser go back to the list of
magazines.
| | 07:43 |
And delete the first one without a cover.
I get a message that the magazine one was deleted.
| | 07:49 |
If I go to the home screen, there's one
less magazine to show.
| | 07:53 |
That wraps up the base functionality for
the magazine catalog system.
| | 07:57 |
In this chapter, I discussed how to use a
helper to perform tasks, then demonstrated
| | 08:02 |
how to use the form helper to save a lot
of time by generating HTML forms.
| | 08:07 |
I then delved into uploading images using
the File Uploading class.
| | 08:11 |
Then finally viewed and deleted magazines.
That's a lot of functionality that I've
| | 08:15 |
covered throughout this course.
So, where to go from here?
| | 08:18 |
| | Collapse this transcript |
|
|
ConclusionWhere to go from here| 00:00 |
Throughout this course, I've covered a lot
of base functionality.
| | 00:03 |
Starting with the what and why of
CodeIgniter, then explored models, views,
| | 00:08 |
controllers, libraries and helpers.
I'll be honest.
| | 00:11 |
It was kind of difficult to hold back and
focus.
| | 00:14 |
There's a lot that can be done in the
magazine catalog system.
| | 00:17 |
Here's some ideas that can be used to
extend this application, in three categories.
| | 00:21 |
Starting with, Usability Ideas, such as
adding a validator that prevents duplicate
| | 00:28 |
magazines and publications.
Highlighting erroring fields, which is
| | 00:31 |
supported by Twitter bootstrap.
Adding a confirmation step to deletion and
| | 00:36 |
sorting magazines.
Then, you could do some changes to the
| | 00:40 |
look and feel, including adding pagination
using the pagination library.
| | 00:46 |
Making a thumbnail upon upload, maybe for
inclusion in the list of magazines.
| | 00:50 |
Formatting dates using the date helper so,
it excludes the day.
| | 00:54 |
Styling magazine covers and lists, maybe
using a Hero header or three abreast
| | 00:58 |
instead of a table.
And then finally, configuring the url
| | 01:02 |
without index.php with web server rewrites
to make it much cleaner.
| | 01:07 |
Then I have a few functional ideas,
including a comprehensive much more
| | 01:11 |
flexible navigation system that's
configurable.
| | 01:14 |
A less manual templating system, which
will save code and make it harder to forget.
| | 01:18 |
Editing magazines instead of deleting and
creating them manually.
| | 01:21 |
Publication management, because currently
there's no interface for it.
| | 01:25 |
Summary reports, such as, you have 13
issues of Sandy Shore magazine.
| | 01:29 |
And users sessions and security.
Because it would be optimal if access
| | 01:34 |
could be controlled.
This might seem like a lot, but code
| | 01:37 |
igniter is a very flexible framework.
And each of these thing I know, can be done.
| | 01:41 |
And these are real world tasks that I'd
like to see in an application for a client.
| | 01:45 |
| | Collapse this transcript |
| Farewell| 00:00 |
Codelgniter is an exciting framework, that
I've enjoyed working with.
| | 00:03 |
Of course, it's not the only framework out
there, but it's one of the fastest ones available.
| | 00:08 |
Codelgniter's ease of use is bolstered by
it's flexibility.
| | 00:11 |
While I will admit I was a little
frustrated by it's approach to models, I
| | 00:15 |
got around it in moments and bent the
framework to my will without breaking it.
| | 00:18 |
That's fantastic and that's really what
developers need.
| | 00:21 |
There's no one right path, and if our
framework will get you most of the way,
| | 00:25 |
use it.
I appreciate your time and your interest
| | 00:28 |
in this subject.
I'd also like to thank the fantastic
| | 00:30 |
production team at lynda.com, for all
their hard work behind the scenes.
| | 00:34 |
Please take a moment to give feedback
through the course home page.
| | 00:37 |
It'll help make future courses better.
Thanks for watching.
| | 00:40 |
| | Collapse this transcript |
|
|