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.

Many modern web-based software application are heavily dependent on star rating systems. In a typical scenario users in an online marketplace for a product or service have the ability to rate the product, service or their experience. As more and more ratings are added the "wisdom of the crowd" takes over. Where there are many thousand ratings and the service offered is averaging a 98% rating, users can be almost certain of receiving a positive experience.

In order to deliver this kind of functionality an application needs the following:

The first of these posts will describe how to extend the tennis club application to allow users to rate each tennis court they play on out of 5 stars and to provide an explanation for why they liked or didn't like the court. Subsequent posts will describe how to display an average rating for each court and how to drill down on the information behind the averages. Given that there can be many ratings for each court we will need a new database table to store all of the information related to court ratings. If you don't already have the tennis club database you can get the script to create it from the 3rd post in the getting started section. Once you have created that database you can create the courtRating table using the following database script:

drop table if exists courtRating;
create table courtRating (
	id int auto_increment,
	rating int,
	comment text,
	createdAt datetime,
	courtid int,
	primary key(id),
	foreign key(courtid) references court(id)
);

Once you have created this table in the database you can go ahead and scaffold it

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

You may also need to re-generate the Court.php model class in order for it to have the "has-many" relationship created within the initialize function of the class.

phalcon model court --get-set --force --namespace=tennisClub

In order to rate the courts out of 5 stars we will use a jquery plugin called bootstrap-star-rating by Kartik Visweswaran. You can download this here: https://github.com/kartik-v/bootstrap-star-rating. Download the plugin as a zip file. Take the css and js files from the zip file and place them in the /public/css and /public/js folders of your application.

You will also need font awesome which is a popular set of icons which was designed to work well with Twitter Bootstrap. Font awesome is available here https://fontawesome.com/. Download the archive, find font-awesome.min.css and place it in /public/css.

Edit the file /app/controllers/ControllerBase.php and add the following function.

public function initialize()
{
	$ratingCollection = $this->assets->collection("rating");
	$ratingCollection->addJs('js/star-rating.min.js');
	$ratingCollection->addCss('css/fontawesome.min.css');
	$ratingCollection->addCss('css/star-rating.min.css');
}

All controller classes inherit from the ControllerBase class. This means that this collection of assets will be available throughout the application.

Now replace the newAction() function in /app/controllers/CourtRating.php with the code below.

public function newAction($courtid)
{
	$this->view->courtid = $courtid;
}
The courtid will be passed to the newAction function and in turn passed to the view as a view variable. This can then be hidden on the new.phtml view for the courtRating. In this way the user will not have to set this foreign key when creating a court rating. Along with this the newAction() function will set up a collection of css and js assets called rating which can be used to create appropriate link and script tags on the form.

Next modify the corresponding view /app/views/courtrating/new.phtml

Firstly add the following lines at the top of the form which will pull in the necessary link and script tags for your css and js assets.

<?php
	$this->assets->outputCss("rating");
	$this->assets->outputJs("rating");
?>

Now we need to add the following line inside the form which will store the courtid in a hidden input box. This will then pass the courtid when the user submits the form.

<input type="hidden" name="courtid" id="fieldCourtid" value="<?php echo $courtid; ?>">	

Next remove the block which puts the field on the form for the user to enter the courtid field. Also remove the block which puts a field on the form for the createdAt field. The timestamp for when the rating was created can be set directly in the createAction() function which is called when the form is submitted.

Now find the line which creates an input tag for the rating which looks like the following

<?php echo $this->tag->textField(["rating", "type" => "number", "class" => "form-control", "id" => "fieldRating"]) ?>

Replace it with the following code which will present the user a list of 5 stars which can be set by rolling over them with the mouse

<input id="fieldRating" name="rating" value="0" type="text" class="rating" data-min=0 data-max=5 data-step=1 data-size="sm">

To rate a court the courtid must be passed in the url as follows http://localhost/tennisClub/courtrating/new/3

The form should now look like this

When this form is submitted it will be handled by the the createAction() function in /app/controllers/CourtratingController.php. We need to modify this action so that the date and time that the rating was made will be set using the system clock. Change the following line

So that it uses a system generated date-time stamp as follows

$courtRating->setcreatedAt((new DateTime())->format("Y-m-d H:i:s"));

In the next post I will explain how to get the average rating for a court and display it with other court information.