SitePoint Sponsor

User Tag List

Page 1 of 4 1234 LastLast
Results 1 to 25 of 100

Hybrid View

  1. #1
    SitePoint Zealot codezilla's Avatar
    Join Date
    Nov 2002
    Location
    upstairs
    Posts
    110
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Front Controllers, Page Controllers, Intercepting Filters

    I think I've come up with a relatively simple (and hopefully elegant) way to combine a FrontController using Intercepting Filters for handling basic pre/post-processing logic common to all pages (output buffering, script timing, page caching, logging, etc.) and URL-based PageControllers (1 URL = 1 Command/Action) for page-specific logic.

    Code posted below. Hopefully this will be of use to someone out there.

    example_page.php:
    PHP Code:
    <?php

    include_once('frontcontroller.inc.php');

    // do page specific stuff (e.g. PageController), for example:
    $user =& new User($_GET['id']);

    ?>
    <html>
    <head><title>User Info</title></head>
    <body>
        <h1><?=$user->getName()?></h1>
        <p><?=$user->getProfile()?></p>
    </body>
    </html>
    (You could also leave out the include_once('frontcontroller.inc.php') part if you are using Apache and instead use the auto_prepend_file directive in a .htaccess file.)

    Yes, I am combining the Controller and the View (which is perfectly acceptable). This is on purpose. You could put the $user =& new User($_GET['id']); line (and anything else) in its own UserController class if you'd like to acheive better separation, but simplicity is one of my design goals here.

    frontcontroller.inc.php:
    PHP Code:
    $t microtime();

    require_once(
    'FilterChain.class.php');
    $fc =& new FilterChain();

    require_once(
    'OutputBufferingFilter.class.php');
    $fc->addFilter(new OutputBufferingFilter());

    require_once(
    'TimingFilter.class.php');
    $fc->addFilter(new TimingFilter($t));

    require_once(
    'PageControllerFilter.class.php');
    $fc->addFilter(new PageControllerFilter());

    $fc->process();
    exit; 
    Notice the exit; line? PageControllerFilter (see below) will include() the originally requested page. This facilitates having Filters that have pre-processing AND post-processing.

    You can put any other stuff that should be global to your application in frontcontroller.inc.php (like define()'s, ini_set()'s, etc.)

    FilterChain.class.php:
    PHP Code:
    class FilterChain
    {

        var 
    $filters;

        function 
    FilterChain()
        {
            
    $this->filters = array();
        }
        
        function 
    addFilter(&$filter)
        {
            
    $this->filters[] =& $filter;
        }
        
        function 
    next()
        {
            
    $f =& next($this->filters);
            if (
    is_a($f'InterceptingFilter'))
            {
                
    $f->run($this);
            }
        }
        
        function 
    process()
        {
            
    $f =& reset($this->filters);
            
    $f->run($this);
        }
        

    InterceptingFilter.class.php:
    PHP Code:
    class InterceptingFilter
    {

        function 
    InterceptingFilter()
        {
        }
        
        function 
    run(&$filterChain)
        {
            
    $filterChain->process();
        }
        

    OutputBufferingFilter.class.php:
    PHP Code:
    class OutputBufferingFilter extends InterceptingFilter
    {

        function 
    OutputBufferingFilter()
        {
            
    parent::InterceptingFilter();
        }
        
        function 
    run(&$fc)
        {
            
    ob_start();
            
    $fc->next();
            
    ob_end_flush();
            echo 
    '<div id="outputbufferingfilter">buffered</div>';
        }
        

    TimingFilter.class.php:
    PHP Code:
    class TimingFilter extends InterceptingFilter
    {

        var 
    $t;
        
        function 
    TimingFilter($t NULL)
        {
            
    parent::InterceptingFilter();
            
    $this->$t;
        }
        
        function 
    run(&$fc)
        {
            
    $t0 explode(' ', (is_null($this->t) ? microtime() : $this->t));
            
    $fc->next();
            
    $t1 explode(' 'microtime());
            
    $t  sprintf('%.6f', ($t1[1]-$t0[1])+($t1[0]-$t0[0]));
            echo 
    '<div id="timingfilter">'$t'</div>';
        }
        

    PageControllerFilter.class.php:
    PHP Code:
    class PageControllerFilter extends InterceptingFilter
    {

        function 
    PageControllerFilter()
        {
            
    parent::InterceptingFilter();
        }
        
        function 
    run(&$fc)
        {
            include(
    $_SERVER['PATH_TRANSLATED']);
        }
        

    PageController include()'s the originally requested page, then the post-processing for each of the filters occurs (the stuff after $fc->next() in the run() methods).

    BTW, the echo lines in the run() methods are just for testing and can be commented out or deleted.

    That's it, there's not much to it (less than there appears anyway), any feedback would be greatly appreciated.

  2. #2
    PHP manual bot bronze trophy Gaheris's Avatar
    Join Date
    Oct 2003
    Location
    Germany
    Posts
    2,195
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Nice, interesting idea and code.
    I'm pretty new in this OOP business so I like example code, thanks for sharing.

  3. #3
    SitePoint Zealot ZangBunny's Avatar
    Join Date
    Jul 2003
    Location
    Mainz, Germany
    Posts
    119
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    (Post removed to protect the innocent...)
    Last edited by ZangBunny; Oct 29, 2003 at 17:48.

  4. #4
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Could it be possible, on the page that is including FrontController.class.php to have a class declaration, without being declared twice? I like this idea a lot, but my pages all use a class, with an interface that the front controller knows, and the fron controller executes the page controller class.

    Matt

  5. #5
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think i figured out how to make it possible to have a class be your command. If you want your index.php page to use one anyway:

    PHP Code:
    class PageControllerFilter extends InterceptingFilter
    {
        function 
    PageControllerFilter ()
        {
            
    parent :: InterceptingFilter ();
        } 

        function 
    run (& $fc )
        {
            if( 
    class_exists('command') )
            {
                
    $cmd =& new Command;
                
    $cmd->execute();
                return;
            }
            
            include( 
    $_SERVER ['PATH_TRANSLATED' ]);
            if( 
    class_exists('command') )
            {
                
    $cmd =& new Command;
                
    $cmd->execute();
            }
        }

    This lets you also extend a BaseCommand class if you wanted. This is exactly what I've been looking for in a FrontController/PageController! You don't have to use a prepend to execute your command class!

    Matt

  6. #6
    SitePoint Member
    Join Date
    Oct 2003
    Location
    constance, germany
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Certainly some nice piece of code. But obviously it is not satisfactory to echo that execution time in the Filter - class.

    How would one be able to rather return this value and then have it stored in a variable so that you can output it later wherever you want?

  7. #7
    SitePoint Zealot codezilla's Avatar
    Join Date
    Nov 2002
    Location
    upstairs
    Posts
    110
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    janosch,

    One possible solution requires using output buffering in the TimingFilter and placing a marker in your html. For example:

    TimingFilter.class.php:
    PHP Code:
    class TimingFilter extends InterceptingFilter
    {

        
    // . . .
        
        
    function run(&$fc)
        {
            
    $t0 explode(' ', (is_null($this->t) ? microtime() : $this->t));
            
    ob_start();
            
    $fc->next();
            
    $ob ob_get_clean();
            
    $t1 explode(' 'microtime());
            
    $t  sprintf('%.6f', ($t1[1]-$t0[1])+($t1[0]-$t0[0]));
            echo 
    str_replace('{TIME}''<div id="timingfilter">'.$t.'</div>'$ob);
        }
        


  8. #8
    SitePoint Member
    Join Date
    Oct 2003
    Location
    N/A
    Posts
    2
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You should try the Mojavi PHP MVC framework. It has filter chaining already implemented, as well as a built-in security system and validation system.

  9. #9
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Very interesting. I like the minimalism.

    I think that the [PRE]$t = microtime()[/PRE] in the frontcontroller.inc.php file breaks the encapsulation of the timing filter. Shouldn't this go into the construction of the timing filter? (preprocessing in the constructor, post processing in the run) I realize that this would slightly reduce the reported time, but then I always thought it was unseemly for scripts to report their own execution time, anyway.

    I don't think the "include back"/exit technique is a good idea.

  10. #10
    SitePoint Zealot codezilla's Avatar
    Join Date
    Nov 2002
    Location
    upstairs
    Posts
    110
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Selkirk
    Very interesting. I like the minimalism.
    Selkirk, I have a great deal of respect for your opinions, so I'm very pleased by your comments -- I was secretly hoping you'd contribute to this thread.
    As an aside, I've got to say that I consult your WACT documentation frequently to aid in the development of my own framework.

    Quote Originally Posted by Selkirk
    I think that the $t = microtime() in the frontcontroller.inc.php file breaks the encapsulation of the timing filter.
    You're right, but I did it purposefully so I could have an more accurate estimation of execution time. However, passing an argument to the TimeFilter constructor is optional, and if no argument is passed, the initial time ($t0) is calculated during preprocessing (see the first line of the run() method).

    Quote Originally Posted by Selkirk
    Shouldn't this go into the construction of the timing filter? (preprocessing in the constructor, post processing in the run)
    I agree that it makes more sense to set the initial time in the TimingFilter constructor. However, I disagree that preprocessing should (in general) occur in the constructor. This would result in preprocessing happening for all the filters in the FilterChain, whether they are executed or not. If, for example, there were an AuthenticationFilter (high in the FilterChain) that determined the user should be redirected to a login page, it would be a waste for the PageCachingFilter (lower in the FilterChain) to perform pre-processing since it would never be executed. In other words, each filter should have the ability to cease execution of the FilterChain and commence post-processing (by not calling $fc->next()), therefore preprocessing should only occur if it needs to.

    Quote Originally Posted by Selkirk
    I realize that this would slightly reduce the reported time, but then I always thought it was unseemly for scripts to report their own execution time, anyway.
    Yeah, I agree -- it's really just intended for testing, and I thought it would be good as an example. I also have an XdebugFilter for more informative profiling (thanks to your recommendation in the WACT documentation).

    Quote Originally Posted by Selkirk
    I don't think the "include back"/exit technique is a good idea.
    Could you expand on this? I know it's not the most efficient way of doing things, but it was the best method I could come up with to get post processing to happen after normal page execution.

  11. #11
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by codezilla
    Selkirk, I have a great deal of respect for your opinions, so I'm very pleased by your comments -- I was secretly hoping you'd contribute to this thread.
    As an aside, I've got to say that I consult your WACT documentation frequently to aid in the development of my own framework.
    Thanks. I've been meaning to get into this thread sooner or later. I'm glad someone uses the documentation. I've been working on the Front Controller / Page Controller / Intercepting Filter / Application Controller aspects of WACT. I've been slowly writing things out. I just did the first draft of Intercepting Filter.

    However, I disagree that preprocessing should (in general) occur in the constructor.
    Oops. You are right. I didn't look carefully enough at what was going on. One thing, though. I would hate to see filter classes being included and instantiated, but never called. Seems like a waste.

    I also have an XdebugFilter for more informative profiling (thanks to your recommendation in the WACT documentation).
    Thats probably Harry's recommendation. I haven't used it yet, but I am interested in it.

    Could you expand on this? I know it's not the most efficient way of doing things, but it was the best method I could come up with to get post processing to happen after normal page execution.
    I guess I can't really say much about this other than double declarations (includes) are bad, m'kay.

    I wrote about some alternate methods on the wiki.

    Here is what I've done so far on the intercepting filters in WACT. These are untested proofs of concept. I've tried to start minimally with just straight includes.

    undomagic.inc.php (request filter):
    PHP Code:
    /**
    * Acts as filter for incoming HTTP variables, eliminating magic_quotes if found
    */
    set_magic_quotes_runtime(0);

    function 
    UndoMagicSlashing(&$var) {
        if(
    is_array($var)) {
            while(list(
    $key$val) = each($var)) {
                
    UndoMagicSlashing($var[$key]);
            }
        } else {
            
    $var stripslashes($var);
        }
    }

    if(
    get_magic_quotes_gpc()) {
        
    UndoMagicSlashing($_GET);
        
    UndoMagicSlashing($_POST);
        
    UndoMagicSlashing($_COOKIES);
        
    UndoMagicSlashing($_REQUEST);

    Its hard to pass an "out of band" parameter to one of these filters...
    pathparam.inc.php:
    PHP Code:
    /**
    * Filters incoming requests moving parameters passed in the path into the standard
    * _GET superglobal.
    * This makes urls like:
    *     [url]http://domain/index.php/extra/parameter?otherparam=yes[/url]
    * equivelent to:
    *     [url]http://domain/index.php?otherparam=yes&path=extra/parameter[/url]
    * The name of the parameter to use is defined via a Config option, or the
    * PATH_PARAM_NAME define, or will default to 'path'.
    */
    function MovePathParamToGetParam() {
        if (
    $_SERVER['REQUEST_URI'] == $_SERVER['SCRIPT_NAME']) {
            return;
        }
        
    $param substr($_SERVER['REQUEST_URI'], strlen($_SERVER['SCRIPT_NAME']));
        
    $querypos strpos($param'?');
        if (
    is_integer($querypos)) {
            
    $param substr($param0$querypos);
        }
        if (
    $param !== '') {
            
    $param substr($param1);
            if (
    defined('PATH_PARAM_NAME')) {
                
    $name PATH_PARAM_NAME;
            } else {
                
    $name getConfigOption('config''request''path_param_name');
                if (empty(
    $name)) {
                    
    $name 'path';
                }
            }
            
    $_GET[$name] = $param;
        }
    }

    MovePathParamToGetParam(); 
    An finally an output filter using PHP's output buffering callbacks:

    contentlength.inc.php
    PHP Code:
    /**
    * Filters the output request to add a Content-Length header.
    * @See [url]http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13[/url]
    * @See [url]http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4[/url]
    */

    function AddContentLengthHeader($buffer) {

        
    $size strlen($buffer);
        
    header("Content-Length: $size"); 
        
        return 
    $buffer;
    }

    ob_start("AddContentLengthHeader"); 
    I've been trying to decide whether or not to make the jump from a simple "procedural" include style designed to work with auto_prepend_file to a class oriented style.

    Opinions?

  12. #12
    SitePoint Zealot codezilla's Avatar
    Join Date
    Nov 2002
    Location
    upstairs
    Posts
    110
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Selkirk, still working through your response but I had a quick question:

    Quote Originally Posted by Selkirk
    I don't think the "include back"/exit technique is a good idea.
    Quote Originally Posted by Selkirk
    I guess I can't really say much about this other than double declarations (includes) are bad, m'kay.
    In your opinion, would it still be bad to have exit; in frontcontroller.inc.php if it were called using the auto_prepend_file mechanism instead of include()'ing it at the top of every page?

  13. #13
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by codezilla
    In your opinion, would it still be bad to have exit; in frontcontroller.inc.php if it were called using the auto_prepend_file mechanism instead of include()'ing it at the top of every page?
    If you require the use of auto_prepend_file, why not just also also require the use of auto_append_file and eliminate the tricky code altogether?

  14. #14
    My precious!!! astericks's Avatar
    Join Date
    Mar 2002
    Location
    Vancouver, BC
    Posts
    1,971
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    PHP Code:
    $user =& new User($_GET['id']);
    $user->getName(); 
    from this, if someone plays with the url [esp the id= part of it] they would be changing the names and info being displayed too, right?

  15. #15
    SitePoint Zealot codezilla's Avatar
    Join Date
    Nov 2002
    Location
    upstairs
    Posts
    110
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by astericks
    if someone plays with the url [esp the id= part of it] they would be changing the names and info being displayed too, right?
    That's correct. My example is a bit over-simplified, by you've got the idea I was trying to convey.

  16. #16
    My precious!!! astericks's Avatar
    Join Date
    Mar 2002
    Location
    Vancouver, BC
    Posts
    1,971
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    oh ok...lol i thought that was an integral part of your final solution. my bad.

  17. #17
    PHP manual bot bronze trophy Gaheris's Avatar
    Join Date
    Oct 2003
    Location
    Germany
    Posts
    2,195
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    but it was the best method I could come up with to get post processing to happen after normal page execution.
    What about destructors in PHP 5 and register_shutdown_function in PHP 4?

  18. #18
    SitePoint Zealot codezilla's Avatar
    Join Date
    Nov 2002
    Location
    upstairs
    Posts
    110
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Gaheris
    What about destructors in PHP 5 and register_shutdown_function in PHP 4?
    PHP4 support is one of my design requirements, so I'm not considering any PHP5-specific functionality, although I suppose using destructors may be an alternative if I could use them.

    The problem with register_shutdown_function is this:
    Quote Originally Posted by PHP Manual
    Multiple calls to register_shutdown_function() can be made, and each will be called in the same order as they were registered.
    But I need them to be called in the opposite order as they were registered because the first filter to do pre-processing should be the last to do post processing, the second should be next to last, etc. Like so: Decorator sequence diagram [microsoft.com]

    Also:
    Quote Originally Posted by PHP Manual
    The registered shutdown functions are called after the request has been completed (including sending any output buffers), so it is not possible to send output to the browser using echo() or print(), or retrieve the contents of any output buffers using ob_get_contents().
    (Emphasis added.)
    I don't like that last part either since it detracts from the power of the Intercepting Filter pattern.

  19. #19
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Opinions?
    Still digesting Some great idea here folks... Keep them flowing

  20. #20
    SitePoint Wizard gold trophysilver trophy
    Join Date
    Nov 2000
    Location
    Switzerland
    Posts
    2,479
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    codezilla - think you may be onto the perfect solution here.

    How about some guesses at requirements for how intercepting filtes / controllers should work in PHP?

    1. Should not restrict the use of URLs / tie people to a specific URL convention (e.g. http://www.example.com/index.php/module/page)

    2. (Addition to #1) Should be possible to use Apache forcetype / re-writing tricks so URLs like http://www.example.com/index.php/module/page are possible (but not required)

    3. Should be possible to execute a page controller without the frontcontroller. In other words if you remove the;
    PHP Code:
    include_once 'frontcontroller.inc.php'
    from the page controller, the page contoller still "works". This rule should help make the front controller / intercepting filters re-usable. Also (in theory) if should be possible to take an existing project like phpBB, strip out all it already has for front contoller / incepting filter type logic while preserving the existing page controllers.

    4. Does does not depend on any Apache specific features or php.ini settings. Although auto_prepend is nice not all hosts give users the ability to change such settings (plus not everyone is using Apache so need to be careful of which $_SERVER variables are used).

    There's probably some more but just kicking off - anyone with more please add them.

    On the exit() issue, that also makes me nervous somehow but right now don't have a specific reason. My guess is it may limit flexibility in some situations but don't have a specific example.

    An alternative approach may be to wrap the example_page.php in a function which is called from PageController but if this needs to be hard coded into example_page.php, it's already violating point #3 above. Not sure...

  21. #21
    SitePoint Zealot codezilla's Avatar
    Join Date
    Nov 2002
    Location
    upstairs
    Posts
    110
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by HarryF
    How about some guesses at requirements for how intercepting filtes / controllers should work in PHP?

    ...
    Harry, I like the rules you came up with. In fact, they are all design requirements that I imposed on the solution I came up with.

    Quote Originally Posted by HarryF
    An alternative approach may be to wrap the example_page.php in a function which is called from PageController but if this needs to be hard coded into example_page.php, it's already violating point #3 above. Not sure...
    I like what you trying to do, but I don't like the added complexity it creates. Personally, I'd rather have one naughty exit() call, than require that every page is wrapped inside a function.

    Quote Originally Posted by HarryF
    If example_page.php is placed somewhere outside of the web root, for example, then "deployed" into the web root with some script which can either be manually executed by a developer or the Apache 404 trick.
    Again, for my needs at least, I think this creates unnecessary complexity. Plus it violates your rule #4.

    Quote Originally Posted by HarryF
    What if the page controllers in their "pre-deployed" state are required to have an associated unit test of some sort? They are only "deployed" if the test passes.
    Unit testing is something I'd certainly like to explore more, but I'm a bit intimated by it all (probably with poor reason).

  22. #22
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by HarryF
    How about some guesses at requirements for how intercepting filtes / controllers should work in PHP?

    1. Should not restrict the use of URLs
    2. Should be possible to use Apache ... tricks
    3. Should be possible to execute a page controller without the frontcontroller.
    4. Does does not depend on any Apache specific features or php.ini settings.
    A requirements list is a good idea. I was orginally going to suggest making two seperate lists. One for Intercepting Filters and one for Controllers.

    Then, I saw where you were going with this in your next post...

    Quote Originally Posted by HarryF
    Think it can be done automatically (fully automatic on Apache by using the 404 trick).
    This is basically a front controller, right? I think any implementation of front controller would be able to support an implementation of intercepting filters.

    Quote Originally Posted by HarryF
    The basic problem is how do we centralize some logic (e.g. logging, authentication) without requiring all PHP scripts be included by some central PHP script.
    Or requiring each script to include a centralized PHP script?

    Quote Originally Posted by HarryF
    My fundamental opinion is Apache itself is the Front Controller when working with PHP, as opposed to a Java Servlet, where you'd implement a Front Controller with Java itself.
    I don't see Apache as a front controller. I see PHP/Apache as a container. Just like Java Servlets are run in a container.

    Quote Originally Posted by HarryF
    When an HTTP request comes into a Java Servlet, the servlet needs to select which code gets executed next.
    It does this via a web.xml file which contains a line which maps the url to a "logical page:"
    Code:
    <servlet-mapping>
    <servlet-name>FrontController</servlet-name>
    <url-pattern>*.do</url-pattern>
    </servlet-mapping>
    Quote Originally Posted by HarryF
    When an HTTP request comes into Apache + PHP, Apache effectively selects the PHP script to execute for you (if one exists for the requested URL).
    PHP uses a physical file mapping technique, rather than a logical class mapping technique. In many ways this is easier when that is what you want. (put the file in a directory. No config file to edit.) However, in a FrontController situtation, you want to map many requests to a single php script. There is no sanctioned way to do this with a physical mapping. Thus, we have to resort to tricks because the "PHP Container" is not flexible.

    In Java, Intercepting Filters are built into the container as well. Servlets are not aware of when they are being filtered. Filters are registered in the same web.xml file that the container uses to decipher urls. Define a filter:
    Code:
    <filter>
      <filter-name>Compression Filter</filter-name>
      <filter-class>CompressionFilter</filter-class>
      <init-param>
        <param-name>compressionThreshold</param-name>
        <param-value>10</param-value>
      </init-param>
    </filter>
    Call a filter for a specific servlet:
    Code:
    <filter-mapping>
      <filter-name>Compression Filter</filter-name>
      <servlet-name>FrontController</servlet-name>
    </filter-mapping>
    The servlet in the previous example is naive. It has no idea that it is being filtered.

    To do the equivalent naive filtering in PHP/apache, I believe that you must use the auto_prepend_file and auto_append_file directives in the php.ini file. doing this via php.ini file is NO different than the doing the same thing in the web.xml file in java, except that you have to add apache configuration in order to achieve more fine grained targeting:
    Code:
    <Files ~ "*.do">
    php_value auto_prepend_file /path/filter.php
    </Files>
    This type of config file editing is par for the course in java web applications.

    So why is it that we have no .htaccess/.ini dependencies on our requirements list?

    Take a look at the include based filters in my previous post. Everyone who has responded with an answer has suggested that I should use classes in that implementation.

    However, if the requirement is to wrap "naive" code, I do not see the value of wrapping the filters in classes. Please enlighten me.

    Quote Originally Posted by Resolution
    Question is, why are you tring to tackle this puzzle without a central connecting php script?
    Indeed. I believe that this is one of codezillas requirements. I can understand why one would want to support wrapping "naive" scripts.

    However, in WACT, I don't think we will really have any "naive" scripts. Thus, I think for WACT an interceptor implementation could rely on a Front Controller or Page Controller doing a little bit of filter management on the behalf of the application logic.

    So for implementing a Front Controller in PHP, we have a few tricks to overcome physical mapping of urls:

    get parameter
    path after url
    mod rewrite
    404 tricks

    My thought is that a Front Controller implementation for WACT should really be independent of which url mapping "trick" was used. In otherwords, the trick would not be defined inside the front controller, but inside the PHP/apache container before the front controller was called.

    In my previous filter post, I had a filter which mapped a "path after url" into a get parameter. What do you think of that, Harry. As opposed to the request/uridata technique?

    In a way, this makes the Front controller a container within a container.

  23. #23
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    One more thing, Codezilla. Because your include back takes place inside of a method, any global variables defined in the filtered file will no longer have global scope.

  24. #24
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Selkirk
    One more thing, Codezilla. Because your include back takes place inside of a method, any global variables defined in the filtered file will no longer have global scope.
    unless specifically designated as global, they will just not accidentally end up as global becuase you started using them in the global scope.
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  25. #25
    SitePoint Zealot codezilla's Avatar
    Join Date
    Nov 2002
    Location
    upstairs
    Posts
    110
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Selkirk
    Quote Originally Posted by Resolution
    Question is, why are you tring to tackle this puzzle without a central connecting php script?
    Indeed. I believe that this is one of codezillas requirements. I can understand why one would want to support wrapping "naive" scripts.
    Exactly. My whole focus is simplicity and flexibility. However, I am opting for at least a little bit of complexity by using the class based Intercepting Filter approach, in order to leverage some of the power of OOP, but I very much like the idea of "naive" scripts, as Selkirk puts it. My background and skills aren't sophisticated enough to come up with a full-blown, robust app framework like Selkirk's WACT. And when I have tried using some of the other various php frameworks out there, my experience has been similar to escape164's:

    Quote Originally Posted by escape164
    On the one hand, [FrontControllers are] great. But, on the other, it really forces my development into a box that does not allow easy change. I have used a pageController in the past as well, and that has worked very effectively for me.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •