The examples on this site are currently tested to work on Phalcon V3.4 and Phalcon Devtools V3.2 Some issues may arise when using later versions.

Please get in touch or post a comment below the post if you encounter a problem.

Database First vs Code First

Many MVC frameworks allow the programmer to either auto-generate the Classes from the SQL tables or to auto-generate the SQL tables from the classes. This is called scaffolding. The debate rages as to which of these approaches is better. As yet, Phalcon does not allow for the generation of SQL tables from PHP classess. Personally, I'm more of a database first kindof guy so this suits me fine.

If you're not that familiar with SQL or relational databases you may struggle a bit with this step. On the other hand it may help you gain a better understanding. This really depends on what point of the curve you are on regarding understanding of databases in general.

In addition to generating classes the scaffold process will generate code for a Controller class and a range of View classes. The Controller will contain actions associated with Creating, Reading, Updating and Deleting an item from the system. An associated View will be created for each of the Create, Read, Update and Delete functions. Bear in mind that there may well be two actions associated with each of these. For example, updating details on an Order requires that the particular order's details be obtained and sent to the view and when the update has been completed the view will send the updated information back to the Controller for processing and persisting to the database.

Enough waffle. Lets build an app.

The following script will create a new database called tennisClub with associated tables and data. I generally use HeidiSQL but any any good SQL client or phpMyAdmin should work fine.

drop database if exists tennisClub;
create database tennisClub;
use tennisClub;

Create table Member(
	id integer auto_increment,
	firstname Varchar(30),
	surname Varchar(30),
	membertype Varchar(6),
	dateofbirth date,
	Primary Key(id)
);

Create table Court
(
	id integer auto_increment,
	surface varchar(30),
	floodlights boolean,
	indoor boolean,
	Primary Key(id)
);

Create Table Booking
(
	id integer auto_increment,
	bookingdate Date,
	starttime time,
	endtime time,
	memberid Integer,
	courtid Integer,
	fee Decimal(18,3),
	Primary Key(id),
	Foreign Key(MemberID) references Member(id),
	Foreign Key(CourtID) references Court(id)
);


INSERT INTO Member (Firstname,Surname,MemberType,DateOfBirth) VALUES ('Oliver','Kerr','Senior','2000-01-31');
INSERT INTO Member (Firstname,Surname,MemberType,DateOfBirth) VALUES ('Morgan','Bartlett','Senior','1985-10-28');
INSERT INTO Member (Firstname,Surname,MemberType,DateOfBirth) VALUES ('Rebecca','House','Senior','1993-08-01');
INSERT INTO Member (Firstname,Surname,MemberType,DateOfBirth) VALUES ('Leslie','Hammond','Senior','1999-03-03');
INSERT INTO Member (Firstname,Surname,MemberType,DateOfBirth) VALUES ('Axel','Gibson','Senior','2007-09-29');
INSERT INTO Member (Firstname,Surname,MemberType,DateOfBirth) VALUES ('Bo','Bradshaw','Senior','1979-12-19');

Insert into Court(Surface, Floodlights, Indoor) Values('Savannah',1,1);
Insert into Court(Surface, Floodlights, Indoor) Values('Grass',1,0);
Insert into Court(Surface, Floodlights, Indoor) Values('Savannah',1,1);
Insert into Court(Surface, Floodlights, Indoor) Values('Savannah',1,1);
Insert into Court(Surface, Floodlights, Indoor) Values('Grass',0,0);
Insert into Court(Surface, Floodlights, Indoor) Values('Grass',0,0);

INSERT INTO Booking (BookingDate,StartTime,EndTime,MemberID,CourtID,Fee) VALUES ('2017-01-07','09:00:00','11:00:00',2,3,10.00);
INSERT INTO Booking (BookingDate,StartTime,EndTime,MemberID,CourtID,Fee) VALUES ('2017-02-11','16:00:00','17:00:00',5,3,10.00);
INSERT INTO Booking (BookingDate,StartTime,EndTime,MemberID,CourtID,Fee) VALUES ('2016-11-16','10:00:00','12:00:00',4,2,20.00);
INSERT INTO Booking (BookingDate,StartTime,EndTime,MemberID,CourtID,Fee) VALUES ('2017-04-06','14:00:00','16:00:00',2,5,10.00);
INSERT INTO Booking (BookingDate,StartTime,EndTime,MemberID,CourtID,Fee) VALUES ('2017-01-17','17:00:00','18:00:00',5,6,10.00);
INSERT INTO Booking (BookingDate,StartTime,EndTime,MemberID,CourtID,Fee) VALUES ('2017-05-06','15:00:00','17:00:00',3,6,15.00);
INSERT INTO Booking (BookingDate,StartTime,EndTime,MemberID,CourtID,Fee) VALUES ('2017-04-27','09:00:00','11:00:00',2,3,10.00);
INSERT INTO Booking (BookingDate,StartTime,EndTime,MemberID,CourtID,Fee) VALUES ('2016-05-05','16:00:00','17:00:00',5,3,10.00);
INSERT INTO Booking (BookingDate,StartTime,EndTime,MemberID,CourtID,Fee) VALUES ('2017-03-23','10:00:00','12:00:00',4,2,20.00);

After you have created the database you need to return to the Command Line Interface (hereafter referred to as the CLI) to scaffold your first table.

First change directory into the project folder you created.


Then copy phalcon.bat from the htdocs folder into your project folder (if you've added the developer tools folder to the search path environment variable you don't need to do this).

Before we attempt to scaffold, there are a number of changes we must make to the project structure we created in the last post.

Firstly, we must make sure that the new tennisClub project has the correct database credentials. The scaffolder has created a config (\tennisClub\app\config\config.php) file which, by default, is set to connect to a database called "test". Edit this file and change the database to the one you have just created - "tennisClub".

   

Namespaces

Next we need to add register a namespace in the project. In Phalcon, if your database has Foreign Keys, your models must be placed into a namespace and our tennisClub database has Foreign Keys. In case you're not familiar with namespaces in PHP they have a number of advantages but the main one is that they help prevent collisions when two classes have the same name. Prior to version 3.4, you could get away without creating namespaces but now this rule is enforced in the devtools. Luckily, Phalcon's loader provides the ability to register namespaces thereby ensuring the files from these namespaces are automatically loaded - this removes any requirement for includes and requires with tricky relative paths. To register a namespace edit /app/config/loader.php and add the following code

$loader->registerNamespaces(
    [
        "tennisClub"    => $config->application->modelsDir
    ]
);

Place this code just after the loader object has been instantiated like this


You're now ready to scaffold a SQL table. Let's start with the Member table. By default, the scaffolder does not create getter and setter methods but I like my Classes to be properly encapsulated so I use the --get-set switch.

phalcon scaffold Member --get-set ns-models=tennisClub

To see your tennisClub app working visit the following link:

http://localhost/tennisClub/member/search


In the next step I'll show you how to make some minor modifications to make your app richer in terms of the information it yields for the user.

https://youtu.be/IWN8Vb803oo