Posted: November 30th, 2011 | Author: tolleiv | Tags: extbase, pattern, typo3 | 3 Comments »
A nice thing to have at hand is definately Signal and Slots. I heard Felix talking about them quite often and I finally found a nice usecase and came to play with them a little bit this afternoon. And just to avoid that others have to look around too much to find how they can get them to work here’s how it’s working for me.
First of all you should understand the concept. This nice little “definition” (from flow3.typo3.org) sums it up pretty well:
A signal, which contains event information as it makes sense in the case at hand, can be emitted (sent) by any part of the code and is received by one or more slots, which can be any function in FLOW3 in extbase.
To get this running in extbase, you’ve to get hold of the Tx_Extbase_SignalSlot_Dispatcher, which is the central instance to manage all of it. Within Extbase that’s done easily with this snippet within your classes:
...
/**
* @var Tx_Extbase_SignalSlot_Dispatcher
*/
protected $signalSlotDispatcher;
/**
* @param Tx_Extbase_SignalSlot_Dispatcher $signalSlotDispatcher
*/
public function injectSignalSlotDispatcher(Tx_Extbase_SignalSlot_Dispatcher $signalSlotDispatcher) {
$this->signalSlotDispatcher = $signalSlotDispatcher;
}
...
Next thing is to make use of it. The Slot (listener) part could look like one of following blocks. In all cases you define the Signal by it’s class (not necessarily a PHP Class) and it’s name. Next to that the Slot can either be defined by a Closure, an object with a method name or a PHP-Class and a method name.
...
// Using a closure
$this->signalSlotDispatcher->connect(
'Crunching', 'emitDataReady', function($data) { crunch($data) }, NULL, FALSE
);
...
// Using a method of the current object
$this->signalSlotDispatcher->connect(
'Crunching', 'emitDataReady', $this, 'crunch', FALSE
);
...
// Using a method of the specified class
$this->signalSlotDispatcher->connect(
'Crunching', 'emitDataReady', 'Cruncher', 'crunch', FALSE
);
...
To trigger the Signal which invokes the Slots registered above, you’ve to run the following code.
$this->signalSlotDispatcher->dispatch('Crunching', 'emitDataReady', array($data));
One thing I found was that by default the Tx_Extbase_SignalSlot_Dispatcher it not a Singleton in older extbase versions. Bastian fixed that already in the master and 1-4 branches and lucky enough this change was part within the TYPO3 4.6.1 release. But I think it’s still important to mention that this wasn’t the default from the beginning on.
Even if AOP is a nicer way to implement this feature, the extbase backport still works pretty straigh forward.
Edit: One thing I’ve to add – Felix is not “just” talking about Signal/Slots – he’s the one to thank for the backport. And now that his blog is running again – this post seems like a summary
A nice thing to have at hand is definately Signal and Slots. I heard Felix talking about them quite often and I finally found a nice usecase and came to...
Posted: July 7th, 2008 | Author: tolleiv | Tags: behavioral, iterator, pattern, php, spl | Comments Off
Lot’s of people like to write down things into lists, so that they can go through that list later and check whether everything was fine. Normally every recipe has a list ~ there’s always a list of ingredients at the beginning of the recipe.
This short example shows how such a list can be processed in PHP. So why would you want to have something else than a array to hold your objects? – My example still uses a array to hold the objects (uni- or bidirectional lists would also be possible) but it adds a kind of a facade to the array so that the common managements-tasks are handled within the List-Object. Everything you need for this example is present in PHP since version 5.0. The basic steps you need to do is to provide a “Object” and an “ObjectList” which implements the native “Iterator” interface and then you’re able to have very handy lists 
class Incredient {
public $name,$amount;
public function __construct($name,$amount) {
$this->name = $name;
$this->amount = $amount;
}
}
class Recipe implements Iterator {
public $title;
private $ingredients;
public function __construct ($title) {
$this->title = $title;
}
public function addIncredient(Incredient $in) {
$this->ingredients[] = $in;
}
public function current () { return current ($this->ingredients); }
public function key () { return key($this->ingredients); }
public function valid () { return current ($this->ingredients); }
public function rewind () { return reset ($this->ingredients); }
public function next () { return next ($this->ingredients); }
}
$cookieRecipe = new Recipe(“Chocolate Cookie”);
$cookieRecipe->addIncredient(new Incredient(‘Flour’,’2.5 cups’));
$cookieRecipe->addIncredient(new Incredient(‘Baking soda’,’1 teaspoon’));
$cookieRecipe->addIncredient(new Incredient(‘Salt’,’0.5 teaspoon’));
$cookieRecipe->addIncredient(new Incredient(‘Butter’,’1 cup’));
$cookieRecipe->addIncredient(new Incredient(‘Sugar’,’1 cup’));
$cookieRecipe->addIncredient(new Incredient(‘Brown Sugar’,’0.5 cup’));
$cookieRecipe->addIncredient(new Incredient(‘Vanilla extract’,’1 teaspoon’));
$cookieRecipe->addIncredient(new Incredient(‘Egg’,’1-2′));
$cookieRecipe->addIncredient(new Incredient(‘Chocolate chips’,’2 cups’));
// process recipe:
foreach($cookieRecipe as $inc) {
echo $inc->name.“ => ”.$inc->amount.“<br/>”;
}
As you see it’s pretty easy to have lists of objects in PHP. You might also think that always creating to some list-object over and over again is very odd and you’re right. For the most common tasks like iterating through arrays, directory-lists and a few more task you can use objects which are shipped with the Standard PHP Library ,which is also part of PHP since version 5 and mandatory in 5.3. So the example shown above could also look like this:
$recipe = array();
$recipe[] = new Incredient(‘Flour’,’2.5 cups’);
$recipe[] = new Incredient(‘Baking soda’,’1 teaspoon’);
$recipe[] = new Incredient(‘Salt’,’0.5 teaspoon’);
$recipe[] = new Incredient(‘Butter’,’1 cup’);
$recipe[] = new Incredient(‘Sugar’,’1 cup’);
$recipe[] = new Incredient(‘Brown Sugar’,’0.5 cup’);
$recipe[] = new Incredient(‘Vanilla extract’,’1 teaspoon’);
$recipe[] = new Incredient(‘Egg’,’1-2′);
$recipe[] = new Incredient(‘Chocolate chips’,’2 cups’);
$recipeIncObj = new ArrayObject($recipe);
$ingredientsIt = $recipeIncObj->getIterator();
foreach($ingredientsIt as $inc) {
echo $inc->name.“ => ”.$inc->amount.“<br/>”;
}
As I said at the beginning, there are lots of situations where you might want to have a list for something and if you store that list in PHP the Iterator-pattern can keep your code clean and tasty
Lot’s of people like to write down things into lists, so that they can go through that list later and check whether everything was fine. Normally every recipe has a...
Posted: July 1st, 2008 | Author: tolleiv | Tags: behavioral, null, pattern, php | 1 Comment »
Very often you create a object with a factory and before you really start using it, you check if your factory really created a object or returned NULL. Or maybe you have a method where a object is passed in and in this situation you’ll have to do this check also.
Instead of typing the “if(object == null)” phrase again and again, you could use the Null-Object pattern, you’ll see that this can make some situations much clearer.
Basically Null-Object ensures that the client always receives a valid object for it’s interaction, so that there’s no need to do the check shown above again and again. This happens since your concrete Null-Object just shares the interface, or inherits from the same class as it’s effective counterpart, but it’s implementation just leaves out any effectiveness.
So a code-example could look like this:
class CookieFactory {
public function makeInstance() {
if(date(‘l’)==‘Monday’) return new NullCookie();
return new RealCookie();
}
}
interface iCookie {
function getCalories();
}
class RealCookie implements iCookie {
protected $calories=250;
public function getCalories() {
return $this->calories;
}
}
class NullCookie implements iCookie {
public function getCalories() {
return 0;
}
}
I think you can imagine what happens when you make use of the CookieFactory - diet on monday
There’re also some disadvantages, your clients normally don’t have a chance to react that there’s something special happening, also the clients must “share” the same expectation what “do nothing” means, the number of required Null-Objects might be very large and unhandy and the Null-Object shares a very deep knowledge with the real one, so that it might be a large effort to create it if the real object is complex too.
I’m so glad that today is tuesday
Very often you create a object with a factory and before you really start using it, you check if your factory really created a object or returned NULL. Or maybe...
Posted: June 20th, 2008 | Author: tolleiv | Tags: creational, database, factory, pattern, query, specification | Comments Off
Maybe you remember the Specification Pattern I explained some weeks ago. It enabled a easy and intuitive searching within large object-collections. A drawback of my example was that I stored the objects in the memory. This can be really ineffective if you want a single object out of hundreds, because you have to create all of them to see which one fits the specification.
Normally you want to limit the number of objects and you also don’t store large datasets in memory. The idea of the Query Object pattern is that it enables a usage, comparable to the specification pattern, for objects which are persisted in a database. The benefit is that it creates a query to exclude objects which won’t satisfy your needs and therefore you wont mess up the memory anymore.
Once you have a query-object in place you should not get in touch with SQL anymore because it can encapsulate SQL completely, at least if you also have some kind of data mapping (coming soon), which is a great benefit for everyone who is not so familiar with SQL. (But don’t forget, regarding performance, SQL-optimization is a very important thing).
So what we need for the Query Object in first place is a object, I’ll use the Cookie out of the specification pattern post again. Then we need criteria-objects which hold the information for a single criteria, (determined by “database-field”, “operator” and “value”) and we also need the Query Objects itself to wrap up the SQL-querying and the object creation somehow.
A very simple example could look like this:
interface Critera {
public function getWhereClause();
}
class CookieCriteria implements Critera {
private $operator,$field,$value;
protected function __construct($operator,$field,$value) {
$this->operator=$operator;
$this->field=$field;
$this->value=$value;
}
public function getWhereClause() {
return implode(” “,array($this->field,$this->operator,$this->value));
}
public static function matches($field,$value) {
return new CookieCriteria(“LIKE”,$field,‘”‘.$value.‘”‘);
}
public static function greaterThan($field,$value) {
return new CookieCriteria(“>”,$field,$value);
}
}
class CookieFinder {
protected $criterias;
public function addCriteria(Critera $criteria) {
$this->criterias[] = $criteria;
}
public function generateSQL() {
$sql = “SELECT * FROM cookies”;
if(sizeof($this->criterias)) {
$where=array();
reset($this->criterias);
while(list(,$criteria)=each($this->criterias)) {
$where[] = $criteria->getWhereClause();
}
$sql.= sizeof($where)?” WHERE “.implode(” AND “,$where):“”;
}
return $sql;
}
public function find() {
$collection = array();
if(!$result = mysql_query($this->generateSQL())) {
throw new Exception(mysql_errno());
}
while($row = mysql_fetch_assoc($result)) {
$collection[] = new Cookie($row['name'],$row['flavor'],$name['size']);
}
return $collection;
}
}
Possible client code could look like this:
$finder = new CookieFinder();
$finder->addCriteria(CookieCriteria::matches(“name”,“Granny%”));
$finder->addCriteria(CookieCriteria::greaterThan(“size”,100));
$cookies = $finder->find();
We just pick up the Query Object, add one or more criteria and ask it to create the objects which fit them.
So this example is not as powerful as the one I used for the Specification pattern, but it should be a easy task to create some kind of “nested criteria objects”.
Query objects normally make use of data-mapping so that you can handle various classes, stored in different tables/databases, with a single and generic Query Object. This also enables to avoid SQL-Injection, since you’re able to validate the fields and values before you sent them to your database, also some kind of database abstraction would be possible.
With the “Query Object by example“, which requires to build up a single object which is used as blueprint for the required objects, exists another flavor of this pattern which is very handy to use and more descriptive.
But no matter which flavor you prefer, Query Objects bring some real benefits when you’ve to handle complex datasets – for smaller projects the effort might be to much so be careful where you use it.
Maybe you remember the Specification Pattern I explained some weeks ago. It enabled a easy and intuitive searching within large object-collections. A drawback of my example was that I stored...
Posted: June 5th, 2008 | Author: tolleiv | Tags: creational, factory, pattern, plugin | Comments Off
I’m sure you’re pretty often in the situation that you have to switch something depending on the context you’re currently in. For example most people change their eating habits before summer – I also do
Sometimes this is what you also want to have in your software. To achieve different behaviour you normally just implement two different classes or aggregates and since they have the same “meaning” they normally share a interface (a.k.a Separated Interface). But who decides which implementation fits into the current environment/context?
The easiest way is to have a Factory Method with a small condition to decide this, but this method might grow very fast if you have various options. In this situation its also a matter of form to move this decision into some kind of configuration(-file) so that there’s only on file which differs in various environments.
Martin Fowler suggests to place some kind of mapping into the configuration-file, so that your Factory knows which implementation to instantiate in the current context. The key for the mapping in this case is the name of the Separated Interface.
As you see in the example code below, there are Cookie Tins which create contain Cookies and depending on the current month you want to use a more or less restrictive Cookie Tin. In May, June and July you restrict your application to create max. 5 cookies, the rest of the year you don’t care
// The Separated Interface
interface CookieTin {
public function getCookieInstance();
}
class NormalTin implements CookieTin {
public function getCookieInstance() {
return new Cookie();
}
}
class DietTin implements CookieTin {
protected $i=0;
public function getCookieInstance() {
return ($this->i++ < 5)?new Cookie():new NullCookie();
}
}
// The Factory which supports Plugin-Creation
class CookieTinFactory {
public static function getPlugin( $class ) {
try {
return new $GLOBALS['Plugins'][$class]();
} catch( Exception $e) {
// maybe call some default implementation if the mapping is wrong
}
}
}
class Cookie {
public function printCalories() {
echo ’200 ‘;
}
}
class NullCookie extends Cookie{
public function printCalories() { }
}
// This is usually in a configuration-file, normally this should
// also sit in a XML structure….
// That’s what it would be in 300 days/year
$GLOBALS['Plugins']['CookieTin'] = “NormalTin”;
// That’s what we have to turn it to before summer
if(in_array(date(‘n’),array(5,6,7))) {
$GLOBALS['Plugins']['CookieTin'] = “DietTin”;
}
$tin = CookieTinFactory::getPlugin(‘CookieTin’);
$i=10;
while($i–) {
$cookie = $tin->getCookieInstance();
$cookie->printCalories();
}
A very common use-case for this is the changed behaviour in a testing-environment compared to the production-environment.
There's something else in the example beside the Plugin Pattern - I also made use of the Special Case (the NullCookie) pattern which I'm going to show in a future post....
I’m sure you’re pretty often in the situation that you have to switch something depending on the context you’re currently in. For example most people change their eating habits before...