The SitePoint Forums have moved.

You can now find them here.
This forum is now closed to new posts, but you can browse existing content.
You can find out more information about the move and how to open a new account (if necessary) here.
If you get stuck you can get support by emailing forums@sitepoint.com

If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

This is an excellent thread! A good part of it is still way above me, but going through a real life situation is really helping me start to get my head around it. Definitely some nifty things floating around here.

Originally Posted by Resolution

Ok,

Here is my solve, a possible solution. It should load from one file.

cheers

I attempted to run it, but is_a() is not defined. I must not have not have 4.2 installed on the server I am using. Maybe it wasn't meant to be run and is just a proof of concept. Either way, I like the code!

codezilla, thank you for taking the time to respond. I realized there may of been a lot of questions!

Basically, I want to be able to easily apply pre-processing and post-processing logic to a simple script without relying on any Apache-specific mechanisms.I'm not talking about specific functionality using an enterprise level web application framework like WACT. I'm talking about general functionality in a typical PHP script.

Exactly what I wanted to know.

I suppose that ideally post processing should occur for any filters that are higher up in the chain

I assumed this in the solve, we may be thinking alike here.

Quote: Resolution

6. What happens if a class that's NOT a filter is included AS a filter?

It won't work. There are an infinite number of "what if" scenarios. What if you pass an array instead of an object? I'm not worried

If a non-filter object or the incorrect version or type of filter is passed to the Intercepting Filter the script could not olny cease to function but HANG the server. Imagine if you are on a shared server and this happens. The load balance spikes because the php hit some internal error and all the other people on the server suffer. Apache may even need to be reset. Which could mean your host might suspend privilages to scripting or even ban your account. Their time is their money. It could all happen if catch nets arn't in place.

This is also the reason I asked question 7.

My solution is a simple, put a check at the AddFilter() for the proper abstract class (filter) before it's added to the array of filters. This simple step could save you much greif and debug time later on when things get more complicated.

Then what do you mean by "central connecting php script"?

I've gotten Fowler's POEAA since that statement, please excuse my lack of description. By central connecting script I mean a central Front Controller that's going to do all the calling of the smaller/child controllers, ie Intercepting Filter, Application Controller and Template View. It's role would be to validate the incoming comands from the Page Controller or other Front Controller and then make sure that those general orders are carried out. It should be VERY thin, only enough to validate, and pass on commands.

Quote: Resolution

10. Ie. Authentication or Pagecaching may not happen on EVERY page so how do you plan to expand on this idea when the site grows in size and Page Controllers? Code morphing?

Good point. Code morphing? What's that? Sounds complicated. I'm not sure how exactly I'm going to handle it. I'll probably either use a central config file, or do something per page.

This seems out of scope based on you saying you want to keep it simple. Code morphing (to me) means having a script that is managed by another script. When conditions or requirments change the controling script will edit the (pagecontroller's)code. It's easier than it sounds. Think of a Template view that saves to file insted of echoing to screen and thats how I would do it.

As far as you design specifications, are you sure you want a Page Controller and a Template View meshed together?

6. What happens if a class that's NOT a filter is included AS a filter

This becomes a critical question after you posted post 27.
How do you know if the filter being added is the correct TYPE or VERSION and not some other type or version?

...

This is also the reason I asked question 7.

You're absolutely correct that my class needs some error handling. I leave it out of the code I post on sitepoint for two reasons: (1) it's ugly, (2) it makes the code harder to understand.

Originally Posted by Resolution

If a non-filter object or the incorrect version or type of filter is passed to the Intercepting Filter the script could not olny cease to function but HANG the server. Imagine if you are on a shared server and this happens. The load balance spikes because the php hit some internal error and all the other people on the server suffer. Apache may even need to be reset. Which could mean your host might suspend privilages to scripting or even ban your account. Their time is their money. It could all happen if catch nets arn't in place.

I think you're overestimating the severity of passing an invalid Filter to FilterChain. The script will probably generate a fatal error, but it certainly won't hang the webserver.

Originally Posted by Resolution

My solution is a simple, put a check at the AddFilter() for the proper abstract class (filter) before it's added to the array of filters. This simple step could save you much greif and debug time later on when things get more complicated.

That's definitely a valid solution and I should probably incorporate it back into my own version. That's what I was originally attempting to do by extending a base InterceptingFilter class and using an is_a() test in FilterChain. I took it out since I decided against extending InterceptingFilter.

Originally Posted by Resolution

By central connecting script I mean a central Front Controller that's going to do all the calling of the smaller/child controllers, ie Intercepting Filter, Application Controller and Template View. It's role would be to validate the incoming comands from the Page Controller or other Front Controller and then make sure that those general orders are carried out. It should be VERY thin, only enough to validate, and pass on commands.

That's basically how I was thinking of all this from the beginning, but I've been persuaded that what I presented is base page controller, not a front controller. However, they're very similar concepts and are somewhat interchangable.

Originally Posted by Resolution

Originally Posted by codezilla

Code morphing? What's that? Sounds complicated. I'm not sure how exactly I'm going to handle it. I'll probably either use a central config file, or do something per page.

This seems out of scope based on you saying you want to keep it simple. Code morphing (to me) means having a script that is managed by another script. When conditions or requirments change the controling script will edit the (pagecontroller's)code. It's easier than it sounds. Think of a Template view that saves to file insted of echoing to screen and thats how I would do it.

IMHO, "having a script that is managed by another script" is way more complicated than having a simple config file (I'm not talking about some crazy XML monster). But we're probably both misinterpretting what the other is thinking so I wouldn't get too hung up over this.

Originally Posted by Resolution

As far as you design specifications, are you sure you want a Page Controller and a Template View meshed together?

Definitely! I'm thinking of the most basic case like my original (slightly modified) example:

Anyone ever decide if the 'exit()' thing was a bad thing? I'm using this same idea in a project, and i like it. I'm not sure if I can see what's wrong with it. Isn't php exiting anyway when the script is done?

I believe you have been too quick to discard a centralized script (a FrontController). A typical FrontController will pass control to one of the actions, and will employ complex logic and a central configuration file to make the decision. But the latter is not a requirement.

The discussion here revolves around including (transparently) PageController code in naive scripts. How about the other way round - including these naive scripts (again, transparently) from a FrontController?

What you gain is the ability to easily add support for filters etc without and prepend/append tricks. What you lose is a... well, what? With this dumb FrontController you don't have a performance hit. The only issue is whether it can be truly transparent.

So I am wondering: if your script (gallery/edit.php) is included from a centralized one instead of being simply run by Apache, does it make a difference for the script? And if it does, can it be easily fixed?

For example, $_SERVER['SCRIPT_NAME'] would be incorrect, but that can be fixed. So, if it turns out there are no differences for the script, then what's the disadvantage of a centralized FrontController?

My (currently under development framework is set up) very much like that. It combines some of the ideas of the FrontController with the PageController pattern, much like you describe. Instead of simply including a PHP script, that script is 'wrapped' into a PageController class (the C in MVC).

It gives you all the advantages that you mentioned in your post, without any disadvantages that I can think of.

My (currently under development framework is set up) very much like that. It combines some of the ideas of the FrontController with the PageController pattern, much like you describe. Instead of simply including a PHP script, that script is 'wrapped' into a PageController class (the C in MVC).

It gives you all the advantages that you mentioned in your post, without any disadvantages that I can think of.

Well Captain, we'll be waiting for that code t show up
( or at least, me ).

I don't really like the FilterChain and addFilter($filter)-command writing (just my personal feelings about it ;)). I have come up with the code below. I tried to follow the Decorator-pattern followed very strictly.

// can also be used whithout initiating a FrontController. If not needed then change function &getCommand(&$request, &$response) {$commandClassName =& $this->getCommandClass($request); return new $commandClassName($request, $response); }

I've finally managed to read this entire thread (while watching an Indiana Jones movie to get twice the entertainment). So now I hope I can say something intelligent.

Originally Posted by HarryF

The other issue with a central script is, unless you're careful (e.g. using the filesystem to check a page controller exists), it leads to slow down while PHP wades through something like a massive switch statement.

I'm not sure I fully understand what you mean, but "wading through a massive switch statement" seems clear enough. I clocked a switch statement with 100 cases and it seems to take about 40 microseconds. That's negligible compared to processing templates and the like.

I was so sure I knew exactly what the difference between a Page Controller and a Front Controller was. After this discussion I'm less sure. My provisional conclusion is that the only substantial difference is that a Front Controller is capable of handling commands or actions more flexibly. It can:

Perform several actions in sequence if necessary

Handle interactions between actions (whatever that means)

Let you keep several actions in one file or class (this is what I've called the Command Group pattern)

Apart from that, they don't seem to satisfy different requirements, which means that most if not all of Fowler's attempts to distinguish them are based on misunderstandings.

Let you keep several actions in one file or class (this is what I've called the Command Group pattern)

I've always understood it to be more simple than that even. Doesn't it only perfom a single action (getting the REQUESTED action or command)? I've always thought that once it does that, it stops doing anything, so as not to handle interactions between actions. Really just the REQUEST gatekeeper.

One thing that has me confused is how, when and where would you actually have the request (url or form) call more than one action? I've never seen a url like: ?action1=doThis&action2=doThat . Seems to me that this only complicates things and that the actions themselves would implement multiple action calls.

Unless the current action gets that info from the url, and then calls that action while executing itself (which in itself is another FrontController). But using the main FrontController (index.php) there, to actually manage multiple actions doesn't seem practical. How do the multiple REQUEST actions interact when being called from the main FrontController?

I can place as may of these module calls as needed inside whatever current fuseaction is being executed.

The point here I guess in relation to the quote above is that while, in Fusebox you don't pass multiple actions in via the URL, you can chain call them from inside a Fuseaction. Indeed in a forum application I am writing right now, I do that to create certain parts of the forum layout.

Fusebox also allows me to break an application into sub-circuits (sub-components if you will)... So you don't necessarily end up with a massive switch with 100 cases. The forum I am writing is broken up into three sub-circuits at the moment, and each switch has ~20 options.

Harry sites the case of integrating phpBB with his ezPublish. Anyone who has worked with these frameworks go to pain staking tasks to perfectly object orient the framework (just like this thread is trying to accomplish), but it still doesn't solve the question:

I have this great framework, classes all well encapsulating their tasks, but how in the world do I apply that at an integration level? You would almost have to re-write (or significantly modify) any of these other scripts. Do you really want to re-write forum code? I think not...

Harry sites the case of integrating phpBB with his ezPublish. Anyone who has worked with these frameworks go to pain staking tasks to perfectly object orient the framework (just like this thread is trying to accomplish), but it still doesn't solve the question:

I have this great framework, classes all well encapsulating their tasks, but how in the world do I apply that at an integration level? You would almost have to re-write (or significantly modify) any of these other scripts. Do you really want to re-write forum code? I think not...

Why, my original post was tackling this very issue: whether you can use naive scripts (for example, phpBB) with a simple FrontController.

I've always understood it to be more simple than that even. Doesn't it only perfom a single action (getting the REQUESTED action or command)? I've always thought that once it does that, it stops doing anything, so as not to handle interactions between actions. Really just the REQUEST gatekeeper.

You're right. You've summed it up very well. I was being too creative too late in the evening. I was trying to dream something up which would be a clear advantage of using a Front Controller. But Front Controllers as generally defined are too dumb to do what I suggested and probably should be.

So I'm left with just the last of my points: A front controller allows you to group several actions together in one file or one class. (See this thread.)

Harry sites the case of integrating phpBB with his ezPublish. Anyone who has worked with these frameworks go to pain staking tasks to perfectly object orient the framework (just like this thread is trying to accomplish), but it still doesn't solve the question:

I have this great framework, classes all well encapsulating their tasks, but how in the world do I apply that at an integration level? You would almost have to re-write (or significantly modify) any of these other scripts. Do you really want to re-write forum code? I think not...

The way I've solved similar integration problems (though probably smaller ones) is by having two controllers at work at the same time in the same script. Let the script you're trying to integrate do whatever it usually does to generate and interpret HTTP requests. Then add your own controller and make sure it knows what requests to handle, by marking the requests or by some other kind of logic.

That goes into notions Selkirk has raised before about central config files.

I was re-reading this thread when I found this comment, and I can't fully understand what's going on without knowing what these "notions" are. Can you or Selkirk provide a pointer or URL to them? All I've found is an essentially empty document on the WACT Wiki.

I've just tried it out and well happy that it works, though can I ask a few questions ?

1) You have each filter extend to the Intercepting Filter. Looking now, at the pattern - link provided by Harry on his site leading to objectmonkey - and then at your script I cannot understand why the need to extend to the InterceptingFilter class ?

The class method Run() isn't executed Is it an Abstract method by any chance.

Could you safely do without this class altogether w/out breaking the Pattern ?

2) How'd for example, you work a View Layer into the Intercepting Filter Pattern, or maybe that should be the other way around - not sure.

I'm looking at the Composite View pattern just now as well, I believe I have something just now that could represent this pattern, but I need to look more at the pattern again.

I'm just looking to clear these points up, so anyone care to help me out ?

1) You have each filter extend to the Intercepting Filter. Looking now, at the pattern - link provided by Harry on his site leading to objectmonkey - and then at your script I cannot understand why the need to extend to the InterceptingFilter class ?
...
Could you safely do without this class altogether w/out breaking the Pattern ?

Yes! InterceptingFilter is not strictly necessary. It's really just an abstract class that (theoretically) describes how its subclasses should work. The idea (in this case) is that all subclasses of InterceptingFilter should have a run() method.

Originally Posted by Widow Maker

The class method Run() isn't executed Is it an Abstract method by any chance.

When the FilterChain object is process()'d it calls the run() method of all the registered filters (refer to the code from frontcontroller.inc.php).

Originally Posted by Widow Maker

2) How'd for example, you work a View Layer into the Intercepting Filter Pattern, or maybe that should be the other way around - not sure.

The way I'm handling it, the last filter to be executed (PageControllerFilter in my example) does an include() on the requested page (using $_SERVER['PATH_TRANSLATED']). That page, let's call it index.php, contains all your control and view logic (which can be plain old procedural PHP if you want).

That's just my approach -- it works well for my needs. Many people handle it very differently.