Tutorial de CodeIgniter

You might also like

Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 27

CodeIgniter Tutorial Learn

CodeIgniter in 40 minutes
http://www.revillweb.com/tutorials/codeigniter-tutorial-learn-
codeigniter-in-40-minutes/
* can also be renamed or relocated anywhere on your server. If
* you do, use a full server path. or more info please see the user
guide:
* http://codeigniter.com/user!guide/general/managing!apps.html
*
* "# $%&I'I"( )'&)*+
*
*/
,application!folder - .application./
$system_path and $application_folder is where codeigniter will look for the
respective folders, you need to update this file so that it is pointing to where you
moved the application and system folder. Change this file to read the
following:
/*
*---------------------------------------------------------------
* )0)$12 #'31% "&21
*---------------------------------------------------------------
*
* $his variable must contain the name of your 4system4 folder.
* Include the path if the folder is not in the same directory
* as this file.
*
*/
,system!path - .../codeigniter/system./
/*
*---------------------------------------------------------------
* &55'I6&$I#" #'31% "&21
*---------------------------------------------------------------
*
* If you want this front controller to use a different 4application4
* folder then the default one you can set its name here. $he folder
* can also be renamed or relocated anywhere on your server. If
* you do, use a full server path. or more info please see the user
guide:
* http://codeigniter.com/user!guide/general/managing!apps.html
*
* "# $%&I'I"( )'&)*+
*
*/
,application!folder - .../codeigniter/application./
To remove index.php from the URL we also need to create a .htaccess file
with the following contents:
%ewrite1ngine on
%ewrite6ond ,7 +89inde:;.php<images<robots;.t:t=
%ewrite%ule 89.*=, /inde:.php/,7 >'?
Save the .htaccess file within the we root !pulic"html, www# with
the index.php file.
$inally we need to tell codeigniter to auto%load the dataase lirary so we don&t
have to ask for it every time we want to do a dataase 'uery. (pen the
file /codeigniter/application/config/autoload.php. $rom line )* you should
see the following:
/*
<
-------------------------------------------------------------------
< &uto-load 'ibraries
<
-------------------------------------------------------------------
< $hese are the classes located in the system/libraries folder
< or in your application/libraries folder.
<
< 5rototype:
<
< ,autoload>.libraries.? - array9.database., .session.,
.:mlrpc.=/
*/
,autoload>.libraries.? - array9=/
+ll you need to do as add database to the array as a string, change the aove
code to match the code elow:
/*
<
-------------------------------------------------------------------
< &uto-load 'ibraries
<
-------------------------------------------------------------------
< $hese are the classes located in the system/libraries folder
< or in your application/libraries folder.
<
< 5rototype:
<
< ,autoload>.libraries.? - array9.database., .session.,
.:mlrpc.=/
*/
,autoload>.libraries.? - array9.database.=/
,ow the dataase lirary will always e loaded and availale.
That is the first it done- .roviding you have a we server running, if you now
go to your we root with a rowser you should e greeted with the following
message:
/t is worth mentioning that we have moved the codeigniter files to outside the
we root for security reasons, ensuring noody will e ale to access or view
your system code.
MODELS
01C stands for 0odel, 1iew and Controller. +s previously mentioned, this
article will not go into a great amount of detail regarding 01C, 2ust know that
01C is a way of segregating your code to make development easier and to
make your code more scalale.
Model 3 + model is a representation of a dataase row. 0odels should
e the only part of your application that interacts directly with the
dataase
View 3 + view is the user facing 4T0L and server side code. There
should e no usiness logic or dataase interactions within a view. 1iews
are dum and should 2ust render and display data to the user
Controller 3 + controller 5controls6 all the data that is either re'uested y
the user or data that is retrieved from the dataase via a model. +ll
usiness logic should e within the controllers
/f you would like to go eyond this codeigniter tutorial and know more aout
01C, please find more information and resources here and here.
7efore we create our first model, we need to create a dataase. (n your we
server, create a myS8L dataase called tutorial and import the following S8L:
--
-- $able structure for table @user@
--
6%1&$1 $&A'1 I "#$ 1BI)$) @user@ 9
@id@ bigint9C0= unsigned "#$ "D'' &D$#!I"6%121"$,
@username@ varchar97CE= "#$ "D'',
@password@ varchar97CE= "#$ "D'',
5%I2&%0 F10 9@id@=
= 1"(I"1-Inno3A 31&D'$ 6*&%)1$-latin7 &D$#!I"6%121"$-7 /
I")1%$ I"$# @user@ 9@id@, @username@, @password@= G&'D1) 9"D'',
.(andalf., .iamwhite+.=, 9"D'', .Ailbo., .bagginses+.=, 9"D'',
.(ollum., .precious.=, 9"D'', .arwen., .tolodannangalad.=/
The aove S8L will create a very simple user tale that will represent a user.
7efore we can create a model, we need to tell codeigniter which dataase to
use and how to access it.
/n your te9t editor, navigate
to /codeigniter/application/config/database.php and from line :; you should
see the following code:
,db>.default.?>.hostname.? - .localhost./
,db>.default.?>.username.? - ../
,db>.default.?>.password.? - ../
,db>.default.?>.database.? - ../
,db>.default.?>.dbdriver.? - .mysHl./
,db>.default.?>.dbprefi:.? - ../
,db>.default.?>.pconnect.? - $%D1/
,db>.default.?>.db!debug.? - $%D1/
,db>.default.?>.cache!on.? - &')1/
,db>.default.?>.cachedir.? - ../
,db>.default.?>.char!set.? - .utfE./
,db>.default.?>.dbcollat.? - .utfE!general!ci./
,db>.default.?>.swap!pre.? - ../
,db>.default.?>.autoinit.? - $%D1/
,db>.default.?>.stricton.? - &')1/
The only lines we need to change are the username, password and dataase.
The dataase should read tutorial as this is the name of the dataase you 2ust
created. +nd the username and password will e the ones you use to access
your myS8L management tool, such as .4.0y+dmin. Change this code to
look like the following. Replace 5<.+SS=(R>?6 and 5<US@R,+0@?6 with your
own.
,db>.default.?>.hostname.? - .localhost./
,db>.default.?>.username.? - .>D)1%"&21?./
,db>.default.?>.password.? - .>5&))I#%3?./
,db>.default.?>.database.? - .tutorial./
,db>.default.?>.dbdriver.? - .mysHl./
,db>.default.?>.dbprefi:.? - ../
,db>.default.?>.pconnect.? - $%D1/
,db>.default.?>.db!debug.? - $%D1/
,db>.default.?>.cache!on.? - &')1/
,db>.default.?>.cachedir.? - ../
,db>.default.?>.char!set.? - .utfE./
,db>.default.?>.dbcollat.? - .utfE!general!ci./
,db>.default.?>.swap!pre.? - ../
,db>.default.?>.autoinit.? - $%D1/
,db>.default.?>.stricton.? - &')1/
,ow that Code/gniter knows how to access our dataase and user tale, we
can no go ahead and create a model which will represent a user.
/**
* Includes the Dser!2odel class as well as the reHuired sub-classes
* JpacKage codeigniter.application.models
*/
/**
* Dser!2odel e:tends codeigniters base 6I!2odel to inherit all
codeigniter magic+
* Jauthor 'eon %evill
* JpacKage codeigniter.application.models
*/
class Dser!2odel e:tends 6I!2odel
L
/*
* & private variable to represent each column in the database
*/
private ,!id/
private ,!username/
private ,!password/
function !!construct9=
L
parent::!!construct9=/
M
/*
* )1$.s N (1$.s
* )et.s and get.s allow you to retrieve or set a private
variable on an obOect
*/
/**
I3
**/
/**
* Jreturn int >,this-P!id? %eturn this obOects I3
*/
public function getId9=
L
return ,this-P!id/
M
/**
* Jparam int Integer to set this obOects I3 to
*/
public function setId9,value=
L
,this-P!id - ,value/
M
/**
D)1%"&21
**/
/**
* Jreturn string >,this-P!username? %eturn this obOects
username
*/
public function getDsername9=
L
return ,this-P!username/
M
/**
* Jparam string )tring to set this obOects username to
*/
public function setDsername9,value=
L
,this-P!username - ,value/
M
/**
5&))I#%3
**/
/**
* Jreturn string >,this-P!password? %eturn this obOects
password
*/
public function get5assword9=
L
return ,this-P!password/
M
/**
* Jparam string )tring to set this obOects password to
*/
public function set5assword9,value=
L
,this-P!password - ,value/
M
/*
* 6lass 2ethods
*/
/**
* 6ommit method, this will comment the entire obOect to
the database
*/
public function commit9=
L
,data - array9
.username. -P ,this-P!username,
.password. -P ,this-P!password
=/
if 9,this-P!id P 0= L
//Ie have an I3 so we need to update this
obOect because it is not new
if 9,this-Pdb-Pupdate94user4, ,data, array94id4
-P ,this-P!id=== L
return true/
M
M else L
//Ie dont have an I3 meaning it is new and not
yet in the database so we need to do an insert
if 9,this-Pdb-Pinsert94user4, ,data== L
//"ow we can get the I3 and update the
newly created obOect
,this-P!id - ,this-Pdb-Pinsert!id9=/
return true/
M
M
return false/
M
M
Save the aove code as a file called user_model.php within
the /codeigniter/application/models directory.
+nd that is all there is to a model- The aove code is well commented and
should make sense ut lets go over it section y section. Lets start with the
private variales.
.R/1+T@ 1+R/+7L@S
private ,!id/
private ,!username/
private ,!password/
These variales simple provide a place for us to store the data from their
matching column in the dataase, you can call them anything you like ut it
makes sense to call them the same thing as the dataase column to avoid
confusion.
S@TS A B@TS
public function getDsername9=
L
return ,this-P!id/
M
public function setDsername9,value=
L
,this-P!username - ,value/
M
Cou can look at sets and gets as an interface to the o2ect that the model is
representing. =e have private variales as opposed to pulic so that they
cannot e modified outside the models scope. This allows us to use set and get
methods to control what can e set and what can e got from these private
variales. $or e9ample, you could always cast to integer to ensure that a private
variale would always e so, something you could not do if you were e9posing
the local variales to the outside world. +nother e9ample is if one of these
private variales was a date, you could ensure that a formatted date was
always provided via the get method for this variale, saving formatting the value
every time you needed it.
C(00/T/,B T4@ (7D@CT
public function commit9=
L
,data - array9
.username. -P ,this-P!username,
.password. -P ,this-P!password
=/
if 9,this-P!id P 0= L
//Ie have an I3 so we need to update this
obOect because it is not new
if 9,this-Pdb-Pupdate94user4, ,data, array94id4
-P ,this-P!id=== L
return true/
M
M else L
//Ie dont have an I3 meaning it is new and not
yet in the database so we need to do an insert
if 9,this-Pdb-Pinsert94user4, ,data== L
//"ow we can get the I3 and update the
newly created obOect
,this-P!id - ,this-Pdb-Pinsert!id9=/
return true/
M
M
return false/
M
(viously at some point we are going to want to save the o2ect&s data ack to
the dataase. =e create a method called commit which simply does that. This
method checks to see if it has an />, if it does then an entry for this o2ect
already e9ists within the dataase. /f the o2ect already e9ists in the dataase
then it needs to perform an update. /f the o2ect doesn&t already have an /> then
it does not currently have a dataase entry. /f there is no entry it needs to create
a new one and then, using the myS8L function insert_id !which returns the />
of the last inserted row# to then update the o2ect so it will then only perform
updates and not insert a new entry every time a commit is performed.
0(>@L $+CT(RC
=e are going to create a very simple factory which is asically a collection of
methods within a lirary that we can reuse to create o2ects with our model.
This separates out methods such as getUser, createUser, etc from within the
model, ensuring that the model can strictly represent the dataase row. Take a
look at the following code:
if 9 + defined9.A&)15&$*.== e:it9."o direct script access allowed.=/
class Dseractory L
private ,!ci/
function !!construct9=
L
//Ihen the class is constructed get an instance of codeigniter
so we can access it locally
,this-P!ci -N get!instance9=/
//Include the user!model so we can use it
,this-P!ci-Pload-Pmodel94user!model4=/
M
public function getDser9,id - 0= L
//&re we getting an individual user or are we getting them all
if 9,id P 0= L
//(etting an individual user
,Huery - ,this-P!ci-Pdb-Pget!where94user4, array94id4
-P ,id==/
//6hecK if any results were returned
if 9,Huery-Pnum!rows9= P 0= L
//5ass the data to our local function to create
an obOect for us and return this new obOect
return ,this-Pcreate#bOectrom3ata9,Huery-
Prow9==/
M
return false/
M else L
//(etting all the users
,Huery - ,this-P!ci-Pdb-Pselect94*4=-Pfrom94user4=-
Pget9=/
//6hecK if any results were returned
if 9,Huery-Pnum!rows9= P 0= L
//6reate an array to store users
,users - array9=/
//'oop through each row returned from the Huery
foreach 9,Huery-Presult9= as ,row= L
//5ass the row data to our local
function which creates a new user obOect with the data provided and
add it to the users array
,users>? - ,this-
Pcreate#bOectrom3ata9,row=/
M
//%eturn the users array
return ,users/
M
return false/
M
M
public function create#bOectrom3ata9,row= L
//6reate a new user!model obOect
,user - new Dser!2odel9=/
//)et the I3 on the user model
,user-PsetId9,row-Pid=/
//)et the username on the user model
,user-PsetDsername9,row-Pusername=/
//)et the password on the user model
,user-Pset5assword9,row-Ppassword=/
//%eturn the new user obOect
return ,user/
M
M
(nce more the aove code is well commented and should e easy to follow.
The first thing to notice is as follows:
private ,!ci/
function !!construct9=
L
//Ihen the class is constructed get an instance of codeigniter
so we can access it locally
,this-P!ci -N get!instance9=/
//Include the user!model so we can use it
,this-P!ci-Pload-Pmodel94user!model4=/
M
4ere we are creating a private variale called $_ci, short for codeigniter which
is where we are going to store an instance of codeigniter so we have access to
all its resources. The reason codeigniter is like this is ecause you may want
to create liraries that do not re'uire any of the codeigniter functionality
therefore why include the e9tra ulkE Codeigniter is very lean rememer-
Learn more aout creating liraries in codeigniter here.
Then, within the __construct! of the lirary !which is called when the class is
instantiated# we gra this codeigniter instance and store it in this variale. ,ow
we can access all of codeigniter&s magic, for e9ample: $this"#_ci"#db"
#select$%&!"#from$user&!"#get!'
=e have two methods within our factory, the main method is get user:
public function getDser9,id - 0= L
//&re we getting an individual user or are we getting them all
if 9,id P 0= L
//(etting an individual user
,Huery - ,this-P!ci-Pdb-Pget!where94user4, array94id4
-P ,id==/
//6hecK if any results were returned
if 9,Huery-Pnum!rows9= P 0= L
//5ass the data to our local function to create
an obOect for us and return this new obOect
return ,this-Pcreate#bOectrom3ata9,Huery-
Prow9==/
M
return false/
M else L
//(etting all the users
,Huery - ,this-P!ci-Pdb-Pselect94*4=-Pfrom94user4=-
Pget9=/
//6hecK if any results were returned
if 9,Huery-Pnum!rows9= P 0= L
//6reate an array to store users
,users - array9=/
//'oop through each row returned from the Huery
foreach 9,Huery-Presult9= as ,row= L
//5ass the row data to our local
function which creates a new user obOect with the data provided and
add it to the users array
,users>? - ,this-
Pcreate#bOectrom3ata9,row=/
M
//%eturn the users array
return ,users/
M
return false/
M
M
This method allows us to pass a parameter of $id so we can retrieve a specific
user o2ect, or if we do not provide an /> it will get all of the user o2ects for us.
Lets walk through the more complicated side of this method, getting all users:
//(etting all the users
,Huery - ,this-P!ci-Pdb-Pselect94*4=-Pfrom94user4=-Pget9=/
//6hecK if any results were returned
if 9,Huery-Pnum!rows9= P 0= L
//6reate an array to store users
,users - array9=/
//'oop through each row returned from the Huery
foreach 9,Huery-Presult9= as ,row= L
//5ass the row data to our local function which
creates a new user obOect with the data provided and add it to the
users array
,users>? - ,this-Pcreate#bOectrom3ata9,row=/
M
//%eturn the users array
return ,users/
M
return false/
$irstly we 'uery the user tale and return all rows !$(uery ) $this"#_ci"#db"
#select$%&!"#from$user&!"#get!'#. =e then check to see if there are any
results using the $(uery"#num_rows! method which will return the numer of
results. /f the numer is F then we return false and end e9ecution. /f the numer
of rows is greater than F then we create an array called users and then loop
through every row returned in the 'uery: foreach $(uery"#result! as $row! *.
$or each returned row we then call our local method:
public function create#bOectrom3ata9,row= L
//6reate a new user!model obOect
,user - new Dser!2odel9=/
//)et the I3 on the user model
,user-PsetId9,row-Pid=/
//)et the username on the user model
,user-PsetDsername9,row-Pusername=/
//)et the password on the user model
,user-Pset5assword9,row-Ppassword=/
//%eturn the new user obOect
return ,user/
M
This method takes the row data and creates a new user o2ect using the
user"model class we created earlier. /t then sets the appropriate values from
the dataase row onto this o2ect and then returns the o2ect to the calling
method.
(nce the calling method receives the new o2ect it adds it to the $users array.
(nce it has iterated through each of the returned rows it returns
the $users array. Simple-
,ow we have a way of representing a dataase row using a model and a way to
get a set of o2ects represented y the codeigniter model using a lirary, lets
move on to something you can see-
+lease note that the user factory needs to be sa,ed within
the /codeigniter/application/libraries directory.
CONTROLLERS
+ controller decides what to display and how to display it. =ithin
the /codeingiter/application/controllers create a file called users, which looks
like this:
if 9 + defined9.A&)15&$*.== e:it9."o direct script access allowed.=/
class Dsers e:tends 6I!6ontroller L
public function inde:9=
L
echo 4$his is the inde:+4/
M
public function show9,userId - 0=
L
,userId - 9int=,userId/
echo 4$his is show users+4/
if 9,userId P 0= L
echo 4Dser I3: L,userIdM4/
M
M
M
This is not the final version of our controller, we are 2ust going to use this to
demonstrate and help you understand how the controllers in codeigniter work.
/f you navigate to your site, lets say the URL you are using
is http-//localhost-././/, then navigate to: http-//localhost-././/users and
you should see the following:
The index method within the controller is what the controller will fall ack on if
there has een no other method specified within the URL, so ecause we 2ust
went to /users the inde9 method is called. ,ow, navigate
to: http-//localhost-././/users/show and you should see the following:
4ere you can see that y specifying show as the second URL section we are
calling the show method within the controller. ,ow, navigate
to: http-//localhost-././/users/show/0 and see the following:
=ith the third section we have passed in a user /> which the show method
picks up and displays on the screen. =e can pass any numer of parameters to
a codeigniter controller method. ,ow you understand
how codeigniters controllers work we can move on and make the users
controller a little more practical.
Change the show method to look like elow:
public function show9,userId - 0=
L
//&lways ensure an integer
,userId - 9int=,userId/
//'oad the user factory
,this-Pload-Plibrary94Dseractory4=/
//6reate a data array so we can pass information to the
view
,data - array9
4users4 -P ,this-Puserfactory-PgetDser9,userId=
=/
//3ump out the data array
var!dump9,data=/
M
+s always the code is well commented so it should e easy to follow. The main
thing that this method is doing now, is loading the user factory so we can
retrieve user o2ects using the lirary and model we created earlier. =e store
the results within an array which we will eventually pass to a view and then 2ust
for now we are dumping the results so we can see how they look. Bo ahead
and navigate to: http-//localhost-././/users/show and you should see the
following:
array97= L >4users4?-P array94= L >0?-P obOect9Dser!2odel=QCC 9R=
L >4!id4:4Dser!2odel4:private?-P string97= 474
>4!username4:4Dser!2odel4:private?-P string9S= 4(andalf4
>4!password4:4Dser!2odel4:private?-P string9T= 4iamwhite+4 M >7?-P
obOect9Dser!2odel=QCR 9R= L >4!id4:4Dser!2odel4:private?-P string97=
4C4 >4!username4:4Dser!2odel4:private?-P string9U= 4Ailbo4
>4!password4:4Dser!2odel4:private?-P string970= 4bagginses+4 M >C?-P
obOect9Dser!2odel=QC4 9R= L >4!id4:4Dser!2odel4:private?-P string97=
4R4 >4!username4:4Dser!2odel4:private?-P string9V= 4(ollum4
>4!password4:4Dser!2odel4:private?-P string9E= 4precious4 M >R?-P
obOect9Dser!2odel=QCU 9R= L >4!id4:4Dser!2odel4:private?-P string97=
444 >4!username4:4Dser!2odel4:private?-P string9U= 4arwen4
>4!password4:4Dser!2odel4:private?-P string97U=
4tolodannangalad4 M M M
The aove output is a dump of an array of user models which are presenting
every user within our user tale, if you navigate
to: http-//localhost-././/users/show/0 and view the following output:
array97= L >4users4?-P obOect9Dser!2odel=Q7T 9R=
L >4!id4:4Dser!2odel4:private?-P string97= 474
>4!username4:4Dser!2odel4:private?-P string9S= 4(andalf4
>4!password4:4Dser!2odel4:private?-P string9T= 4iamwhite+4 M M
Cou can see that the results are 2ust for the user with user /> ; as this is what
we have specified within the URL, try changing the user /> and see what
happens.
,ow you should have a pretty good understanding as to how we can re'uest
and retrieve data from the dataase in a complete o2ect oriented manner. Lets
move onto the final section and create some views-
VIEWS
+ view is simple how the data is presented to the user, typically consisting of the
4T0L and other client side code. =e are going to create a view which will take
the data array we created in our controller in the previous section and list out all
the users it is given. =ithin /codeingiter/application/,iews create a file
called show_users.php with the following code:
//6hecK to see if users could be found
if 9,users +-- &')1= L
//6reate the *$2' table header
echo WWW*$2'
Wtable border-.7.P
WtrP
WthPI3 QW/thP
WthPDsernameW/thP
WthP5asswordW/thP
W/trP
*$2'/
//3o we have an array of users or Oust a single user
obOectX
if 9is!array9,users= NN count9,users== L
//'oop through all the users and create a row
for each within the table
foreach 9,users as ,user= L
echo WWW*$2'
WtrP
WtdPL,user-PgetId9=MW/tdP
WtdPL,user-
PgetDsername9=MW/tdP
WtdPL,user-
Pget5assword9=MW/tdP
W/trP
*$2'/
M
M else L
//#nly a single user obOect so Oust create one
row within the table
echo WWW*$2'
WtrP
WtdPL,users-
PgetId9=MW/tdP
WtdPL,users-
PgetDsername9=MW/tdP
WtdPL,users-
Pget5assword9=MW/tdP
W/trP
*$2'/
M
//6lose the table *$2'
echo WWW*$2'
W/tableP
*$2'/
M else L
//"ow user could be found so display an error messsage
to the user
echo WWW*$2'
WpP& user could not be found with the specified
user I3Q, please try again.W/pP
*$2'/
M
7efore we take a look at this code in any detail, we need to update our
controller to load the view and provide it with the user data it needs. Change the
show method within the users controller to e as follows:
public function show9,userId - 0=
L
//&lways ensure an integer
,userId - 9int=,userId/
//'oad the user factory
,this-Pload-Plibrary94Dseractory4=/
//6reate a data array so we can pass information to the
view
,data - array9
4users4 -P ,this-Puserfactory-PgetDser9,userId=
=/
//'oad the view and pass the data to it
,this-Pload-Pview94show!users4, ,data=/
M
+ll we have changed is we are now using this codeigniter load functionality
!$this"#load"#,iew!# to load the view we have created. The first parameter is
the name of the file within the views directory we want to load, the second is an
array of data we want to pass to the view. ,ote that any key within
the $data array will ecome a variale within the view. So in this e9ample to
access the $data12users23 value, we simple use $users within the view.
,ow we have the controller loading the view and we understand how to access
the data we have passed to it from within the view, lets walk through the code.
$irstly we check to see if the Gusers variale is not false, if the factory cannot
find a user with the specified /> then it will return false. =e handle this and then
display an error message to the user: 5+ user could not e found with the
specified user />H, please try again.6.
/f the Gusers variale is not false and has some data we then need to check to
see if it is a single user !an /> has een specified# or it is an array of multiple
users. /f it is multiple users we then loop through each user and create a row
with their data within the 4T0L tale.
if it is 2ust a single user then we 2ust create a single row with the user data.
Simple, as, that-
CONCLUSION
,ow you have completed this codeigniter tutorial you should now have a good
understanding of how codeigniter works. Cou should know how to set%
up codeigniter including all the configuration, create models, views and
controllers along with liraries and know how to load and use them successfully

You might also like