Phiz3 Tutorials

... working towards sustainable software

Configuring Phiz3 Objects

(for PHP, Javascript Server Side and Javascript Browser Side)

Phiz3 supports both PHP and Javascript object configuration. In each language implementation there are four ways to configure a Phiz3 object. If you are working with PHP server side and Javascript clients side Phiz3 provides two additional PHP methods, toJSON() and toJavascript(), to assist in configuring your Phiz3 object client side. Here's the basics for Phiz3 objects server side —

The basic configuration file formats

Simple configuration format

Phiz3 provides a simple configuration file format to configure objects or applications. Configuration files are very helpful in making web applications portable between hosts. Phiz3's configuration format supports key value pairs and comments. The key and value is delimited by a colon and the value is terminated by a new line. A hash mark is used to start a comment which is terminated with a new line. Here's a simple example.

JSON configuration format

Phiz3 also supports using a JSON base configurations. It's relatively to type the above configuration in JSON format:

Type these two examples up and save them as myapp.conf for the simple configuration and the JSON version save as myapp.json. Either could be used to initialize a Phiz3 PHP or Javascript object.

Configuring Database connections

A cool thing about using Phiz3 objects with a configuration file is the ability to switch between SQLite and MySQL as the database target server side. Here's an example of going from SQLite to MySQL using the simple configuration markup.

SQLite version —

MySQL version —

Whether you're working server side with Javascript via Jaxer or with PHP switching between targets is easy as updating your configuration file.

Putting the pieces together

Integrating your configuration with your application code requires two things —

  1. Read your configuration file from disc as a string.
  2. Pass the string to the constructor of the Phiz3 object.

We're going to do this below and print out the results (NOTE: I've assumed your configuration files are in /www) —

PHP version

Javascript version (NOTE: I'm assuming this is running server side via Jaxer and myapp.conf is in /www)

A similar approach using a JSON file called myapp.json would be accomplished with —
Javascript with Jaxer works in a similar fashion as before (NOTE: I've assumed the configuration file is at /www/myapp.json).

So why is the useful?

Having a configuration file separate from your code base makes it easy to move your code from host to host (e.g. from your development box to your quality assurance box and finally to production) but more importantly it makes it really easy to move configuration information from server to client between PHP and Javascript. Here's some examples of integrating PHP server side with Javacript client side.

Using toJavascript() approach

In this example I'll read a simple configuration in PHP then construct a Phiz3 Javascript object from PHP which will be used to configure another Phiz3 object in the client page.

Using toJSON() approach

If you don't mind mixing PHP inside Javascript this approach works nicely.

Happy Coding

A Simple JSON API with Phiz3

This is an example of using Phiz3 in PHP to make a simple restful JSON API. The API's goal is to return a representation of the calendar month as a JSON object showing weekday names. The JSON object will be an array structure with the month's day used as a key and each day's value containing the weekday name.

  1. (preparation): Collect some requirements (i.e. the paragraph above has a description of the problem)
  2. (preparation): Jot down some ideas about the parts needed to solve the problem describe
  3. (coding): Now let's translate this into some unit tests
  4. (coding): Write code to pass the unit tests
  5. (accessment): Does this meet the requirements of step 1, if not repeat

Preparation

Restate the problem you're trying to solve

Let's restate the requirements described in our owning paragraph. We want a Web base API that will transform a date request into a representation of the month with corresponding weekday names.

Identify the parts you need to solve the problem and what might be helpful

Coding

Write some unit tests

Phiz3 comes with its own simple unit test object called UnitTest which is in the source file UnitTest.php. Phiz3 also has it's own simple unit test library. Since this is about Phiz3's since this article is about Phiz3's Unit Tests. The there are three things you need to know to use Phiz's unit test object.

  1. How to create your Unit tests sub class create your own test object
  2. How to add your tests
  3. How to instantiate your test object and display results

Creating your own test object

You need to include UnitTest.php and create your own object class by extending UnitTests. You can get a current copy of UnitTest.php here. Here's an example of the code you need to write:

That's it. You've defined your own object called TestsWeekdayAPI as a child of UnitTest. Now let's add some test code. If we look at our requirements list we see that we need to parse the RESTful command line so let's start there. We're going to create a test called testRESTful. It will look at a string like /2009/09/01 and extract the year and month. We add this test as part of our TestsWeekdayAPI.

Let's look at what going in. First a bit of magic. If the method you create in your UnitTest child starts with the word 'test' it will be available to run later. Next we create an instance of our object (don't worry that we haven't written it yet, we'll do that later). We create some test data in this case We're simulating the contents of $_SERVER['PATH_INFO'] as $path_info. We setup some expected results run our method and compare.

Now that we've defined a test let's add the code create an instance of our object and run the test.

There you have it we have a basic unit test written. Now let's run it. Keep in mind it should fail sense we haven't written WeekdayAPI yet. Assuming you saved the code above as /www/TestsWeekdayAPI.php and UnitTests.php is in the same directory you could run the command php TestsWeekdayAPI.php to see the test results. You should get results looking something like this:

Fatal error: Class 'WeekdayAPI' not found in /www/TestsWeekdayAPI.php on line 5

Now we can code first part of our WeekdayAPI object. From our tests we've know we're going to pass in the restful path then return a date. Like creating unit tests we're going to sub class the Phiz3 object. Since we're haven't created the rest of our tests let's put in some place holder code.

We now can run our tests again (e.g. php TestsWeekdayAPI.php). We should get something like:

Fatal error: Class 'WeekdayAPI' not found in /www/TestsWeekdayAPI.php on line 5

Wait that's the error I got before. What I forgot to do is add the line to the top of TestsWeekdayAPI.php to include the new file WeekdayAPI.php that I've just created. Our TestsWeekdayAPI.php should now look like:

Now let's run that again (e.g. php TestsWeekdayAPI.php):

Running testRESTful
Assert Failed: The method RESTful should return a date. ERROR: RESTful() not implemented.
	testRESTful failed.
	0 assertions passed.
	1 assertions failed.

Summary
0 tests passed.
1 tests failed.

Now our unit test is working (i.e. no PHP errors but not yet passing). Let's go ahead and write the rest of our tests we need for WeekdayAPI. We're going to need to test building the JSON for a specific month. Finally we'll need a test for seeing if the whole assembled API is working. We can add place holder code like we did with RESTful method. When we get done we should have unit tests which run but fail for everything.

TestsWeekdayAPI.php should look something like this:

You're skeleton program should look something like this —

Running the command php TestsWeekdayAPI.php should yield something like —

Running testRESTful
Assert Failed: The method RESTful should return a date. ERROR: RESTful() not implemented.
	testRESTful failed.
	0 assertions passed.
	1 assertions failed.
Running testJsonForMonth
Assert Failed: The jsonForMonth should return a JSON representation for Sept 2009
	testJsonForMonth failed.
	0 assertions passed.
	1 assertions failed.
Running testEventloop
Assert Failed: The event loop should return our final results of the API request.
	testEventloop failed.
	0 assertions passed.
	1 assertions failed.

Summary
0 tests passed.
3 tests failed.

Now you're ready to code the API itself.

Coding the API

What we've done with the unit test approach is make the problem less fuzzy and made some decisions early about how things will behave. It's not that everything is fixed in stone yet. At this stage, or even when you start coding your actual program you might find that you're assumptions about the tests were wrong. If so stop coding the solution and write some more tests. The goal of the unit test is to provide you a solid foundation, guide you on implementing your plans and verify that you've met your expectations. If you find your plans need updating (i.e. some of your base assumptions were wrong) feel free to rewrite your tests but be vigilant against two temptations - writing tests to match code you've already written and changing tests simply to have code pass. Both of those are a waste of time and effort. You want the process to flow from writing tests, testing and seeing the tests fail, writing code that passes the tests. Our API is a simple problem so we're probably pretty close our solution already and I don't expect to have to change my tests though I might want to add some more.

Let's implement our RESTful method first and get that working. You're solution might look like —

If we've built this right when running php TestsWeekdayAPI.php should yield —

Running testRESTful
	testRESTful OK
	1 assertions passed.
Running testJsonForMonth
Assert Failed: The jsonForMonth should return a JSON representation for Sept 2009
	testJsonForMonth failed.
	0 assertions passed.
	1 assertions failed.
Running testEventloop
Assert Failed: The event loop should return our final results of the API request.
	testEventloop failed.
	0 assertions passed.
	1 assertions failed.

Summary
1 tests passed.
2 tests failed.

Now let's code jsonForMonth method —

We should have one more test passing then before —

Running testRESTful
	testRESTful OK
	1 assertions passed.
Running testJsonForMonth
	testJsonForMonth OK
	1 assertions passed.
Running testEventloop
Assert Failed: The event loop should return our final results of the API request.
	testEventloop failed.
	0 assertions passed.
	1 assertions failed.

Summary
2 tests passed.
1 tests failed.

And finally our eventloop might look like this —

My final test results run with php TestsWeeklyAPI.php looks like —

Running testRESTful
	testRESTful OK
	1 assertions passed.
Running testJsonForMonth
	testJsonForMonth OK
	1 assertions passed.
Running testEventloop
	testEventloop OK
	1 assertions passed.

Summary
3 tests passed.
0 tests failed.

Notice that I've decided to change what the eventloop returns. That is because we'll want to send output to the browser making the request. So I've decided that I'm returning a HTML div with any errors I've discovered rather then what boolean like I did with RESTful and jsonForMonth methods. It's not a problem because in testing for correct operations I wanted a valid JSON array and that is what I was testing for. Now we're ready to wire this up for an actual API that returns the month with days of the week as a JSON array.

Wiring up the final application

It turns out to be pretty simple. We've modeled how the API is supposed to behave all we need to do is set a content type and return results. Here's what I cam up with —

If you went to a URL where this was installed the output for /2009/09/06 would look like —

{"1":"Tuesday","2":"Wednesday","3":"Thursday", "4":"Friday","5":"Saturday","6":"Sunday", "7":"Monday","8":"Tuesday","9":"Wednesday", "10":"Thursday","11":"Friday","12":"Saturday", "13":"Sunday","14":"Monday","15":"Tuesday", "16":"Wednesday","17":"Thursday","18":"Friday", "19":"Saturday","20":"Sunday","21":"Monday", "22":"Tuesday","23":"Wednesday","24":"Thursday", "25":"Friday","26":"Saturday","27":"Sunday", "28":"Monday","29":"Tuesday","30":"Wednesday"}

Things to improve

First the error messages are pretty bad. Returning something more meaningful would be a big step in the right direction. Also error condition handling is very minimal and in a real API you'd beef that up. Our RESTful request could be simpler if we only required a year and month since the date isn't needed. You could extend the API so that requesting a specific date return that weekday name while specifying the month and year only returns the month with all the weekday labels.

I've tried to keep the unit tests minimal since this is an example. I've only check for correct conditions. You'll get better results if you also test for boundary conditions. This is particularly true as you build more complex API. This helps to prevent changing code in one place which breaks something in another place. Also to keep minimize the length of this article I've not commented my code. In practice I always try to comment at least the functions. I then can use a document generator (e.g. Doxygen) to generate source code level API docs.

Happy Coding

Phiz by R. S. Doiel
Copyright © 2005 - 2009 All rights reserved.

This software is released under the Simplified BSD License as published by the Creative Commons. See http://creativecommons.org/licenses/BSD/ for details.