Learning by Example

At the end of each chapter, I will dip you into variety of examples. Some examples are short and easy to understand. Throughout this book I will be helping you to build a "DVD Rental" application and many examples and excercises will be related to that application.

Putting Agile into Toolkit

Agile Toolkit is inspired by the flexibility and power of desktop UI frameworks, but it is also specifically designed to be lightweight enough for high performance on the web. For many years the PHP community hasn't seen frameworks using the full potential of object oriented design, primarily due to restrictions of older PHP versions, compatibility with legacy systems, as well as the general development mindset of the community.

Using the following example we will demonstrate some of the UI capabilities which apply to absolutely ALL objects in the Agile Toolkit. It will also demonstrate a typical work-flow and how being "Agile" can save a great deal of time for you.

The Job: a "Slot Machine"

Imagine a client, who shows up and wants to put your skills to the test by asking you to develop a simple "slot machine". The client is not yet sure of what he needs, but he says he'll figure it out once he gets his hands on a first prototype. His requirements is to make a web page display 3 random digits to the visitor.

"Simple enough", you say, and write some HTML for this curious task - putting it into templates/default/view/slotmachine.html

 <div id="<?$_name?>" style="border: 2px solid black; padding: 10px; width: 100px; margin: 10px;">
   <p>Slot Machine</p>
   <div style="padding: 4px; border: 1px solid red"><?$slot1?></div>
   <div style="padding: 4px; border: 1px solid red"><?$slot2?></div>
   <div style="padding: 4px; border: 1px solid red"><?$slot3?></div>
 </div>

Next, you need to generate random numbers and place them into the template slots. This logic should be contained inside a new class file, which must be created inside lib/View/SlotMachine.php:

class View_SlotMachine extends AbstractView {
    function 
init(){
        
parent::init();
        
$this->template->set('slot1',rand(1,9));
        
$this->template->set('slot2',rand(1,9));
        
$this->template->set('slot3',rand(1,9));
    }
    function 
defaultTemplate(){
        return array(
'view/slotmachine');
    }
}

Excitedly you call your client and tell them that you have finished the job, and ask him in which page you need his View added. "Add it to the index page" he says, "Let me know when you are done, so I can see it"

You follow his instructions: you open page/index.php and type the following inside the init() method:

Result

Slot Machine
6 6 6
 

Code

$page->add('View_SlotMachine');

"Yeah, YEAH!, good start. How about having 3 of them?""No problem" you reply, and add 2 more lines

Result

Slot Machine
7 8 4
Slot Machine
7 2 5
Slot Machine
7 1 4
 

Code

$page->add('View_SlotMachine');
$page->add('View_SlotMachine');
$page->add('View_SlotMachine');

"Naaaw, make it two. But put them next to each other" — he says. "OK"

Result

Slot Machine
8 2 7
Slot Machine
8 4 8
 

Code

$col=$page->add('Columns');
$col->addColumn(2)->add('View_SlotMachine');
$col->addColumn(2)->add('View_SlotMachine');

"Now make the left one react to the mouse. When I click on it, I want the background to change."

Result

Slot Machine
4 2 9
Slot Machine
8 4 4
 

Code

$col=$page->add('Columns');
$left=$col->addColumn(2)->add('View_SlotMachine');
$left->js('click')
    ->
animate(array('background-color'=>'#F82'));
$col->addColumn(2)->add('View_SlotMachine');

"Hmm.. How about if it changes the color of the one on the right, instead of its own?"

Result

Slot Machine
6 4 2
Slot Machine
1 5 9
 

Code

$col=$page->add('Columns');
$left=$col->addColumn(2)->add('View_SlotMachine');
$right=$col->addColumn(2)->add('View_SlotMachine');
$left->js('click',$right->js()
    ->
animate(array('background-color'=>'#F82')));

"I think this is getting us nowhere. Let's go back and try something else. Can you add a button to refresh the numbers?"

Result

Slot Machine
6 2 5
Slot Machine
2 9 4
 

Code

$col=$page->add('Columns');
$left=$col->addColumn(2)->add('View_SlotMachine');
$right=$col->addColumn(2)->add('View_SlotMachine');

$page->add('Button')->setLabel('Pull')
    ->
js('click',
      
$left->js()->reload());

"Awesome. But why the machine on the right is not refreshing?"

Result

Slot Machine
5 6 5
Slot Machine
1 4 6
 

Code

$col=$page->add('Columns');
$left=$col->addColumn(2)->add('View_SlotMachine');
$right=$col->addColumn(2)->add('View_SlotMachine');

$page->add('Button')->setLabel('Pull')
    ->
js('click'$col->js()->reload());

"You make changes faster than I can think them! I bet you can even put one machine into the other!"

Result

Slot Machine
4 2 7
Slot Machine
2 1 2
 

Code

$slot=$page->add('View_SlotMachine');
$slot->js(true)->css('width','150px');
$slot->add('View_SlotMachine',null,'after_slots');

$page->add('Button')->setLabel('Pull')
    ->
js('click'$slot->js()->reload());

"Oh, you didn't need to actually do that, I was just kidding! Let me get back to you when my designer finishes the HTML. Great Job!"

Making them happy

Most clients are demanding. If yours are not, you are lucky, but more often than not you will find yourself implementing something first, then adjusting it again and again. Some would call it "agile software development", others call it "a client being picky".

How Agile Toolkit saves your day

As a forward-thinking developer, you are probably interested in getting "the most" for "the least" amount of code. Without using Agile Toolkit, you may find yourself either spending too much time implementing a widget, or being unable to implement all of your client requests quick enough.

Even the simplest View in Agile Toolkit has very sophisticated capabilities:

  • The ability to be displayed absolutely anywhere on the page, inside other objects or in global templates
  • It can have a default template, or can be used with another template, specified when adding the object
  • It will have its own globally unique name in $object->name
  • It can memorize properties on the object level, and then recall them: $object->memorize()
  • It can apply jQuery actions immediately, or on a specific event: $object->js('click')->hide('slow');
  • It allows you to insert other objects into your view object
  • It allows you to link a controller or model with setController or setModel
  • You can access the view's template directly, through $object->template->set();
  • You can define object-level hooks (callbacks)
  • It can raise object-specific exceptions, through throw $object->exception('ouch')
  • You can remove and destroy an object without rendering: $object->destroy()
  • You can manipulate elements such as $object->getElement('foo');
  • You can reload an object through AJAX, with $object->js()->reload();

All that you have seen happening here can be done with ANY view. This is the power of good Object-Oriented design.