SitePoint Sponsor

User Tag List

Page 5 of 16 FirstFirst 12345678915 ... LastLast
Results 101 to 125 of 397
  1. #101
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    OK, I just checked the code in as module Skeleton. There's a classdiagram there too, as promised. I'll just repost it here, so you don't have to tinker with cvs to view it.

    I didn't do much of an effort of testing the code. Would some of you other people have a go at dishing some unittests together ?

    Off Topic:

    Weehee ... post # 100
    Attached Images Attached Images

  2. #102
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here's an idea I had for refactoring this:

    "The aim of this refactoring is to allow us to handle clean URLs. Start with the Request class. Assume a mod_rewrite to translate http://www.example.com/foo/bar into http://www.example.com/index.php?s=/foo/bar. Define a set of Rules to parse $s = $_GET['s'] into $_GET['action'], $_GET['page'] etc. Note duplication between these rules and the mapper classes. Refactor to give a master mapper (MM) and a Request class. MM is responsible for parsing $s (passed to an 'execute' method) to create the Request object and using the Rules to create a new Dispatch($request) object."

    This also solves the problem of error handling and internal redirection, all we need to do is call the MM object using a different request path. If MM is a singleton, we can also execute relative URLs internally for finer control, to get from /article/php-howto to /article/not-found without knowing we are inside /article/.

    What do you think?

    Douglas
    Hello World

  3. #103
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It's obvious that there should be some way of building url's. Exactly how is a bit tricky. The best I have been able to come up with so far is a global function (shiver), which may actually just be a proxy for a Singleton. The problem is, that it needs to be very simple to build an url. You don't want to pull an object from some Registry, and call it's method each time.

    You sound like you have something specific in mind, DougBTX - Could you try to stick something together ?
    Last edited by kyberfabrikken; Jun 14, 2005 at 09:01.

  4. #104
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'd embarras myself too much
    Hello World

  5. #105
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    McGruff, Kyber, you appear to be confused huh?

    Sorry, the posting I made was off the top of my head, maybe I didn't make things clear enough or something. What I was suggesting was that you have one service, and you have a series of servicable objects?

    Each servicable object would (could) be seen as being each, given mapper I suppose? The service it's self would have the bulk of the logic, thus reducing the duplication found in the mappers. But in my case, I'm not mapping to objects, but to a configuration instead (thus the suggestion of serveral services you see, as there could be different configuration formats no?).

    Does that help you any? Btw, +1 SweatJe for posting the link, I've bookmarked it (again)

  6. #106
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    Each servicable object would (could) be seen as being each, given mapper I suppose? The service it's self would have the bulk of the logic, thus reducing the duplication found in the mappers. But in my case, I'm not mapping to objects, but to a configuration instead (thus the suggestion of serveral services you see, as there could be different configuration formats no?).
    Hm ... still not sure what you mean. Is the Service equivalent to FrontController ? (the class, not the pattern)

    Could you write some code ? It doesn't have to be working or anything, just as an illustration.

  7. #107
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The service is not the Front Controller, nope. What the (a) service does is basically to provide logic for the servicable, used by a factory. I map a Request to a given row in a database hierarchy for example, which the SQL for this, is in a servicable object.

    A service would query a servicable for the 'expression', and (the service) would pull the data out of the database. In your case, each servicable could be seen as a mapper, of which the service does the mapping?

    What makes it more difficult is that I use a configuration, so maybe the approach is more suitable to my needs than what is being discussed here, but I thought I'd just share it with you all anyways

    Once I've got the complete script working, I'll post some more examples to better explain things...

  8. #108
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If I understand you correct, yoiu are talking about a RequestMapper with some heavier logic within ?
    Until now the requestmappers we have done, have been rather simplistic, but I see no reason why the RequestMapper couldn't contain logic that accessed the Model-layer.
    Something like the following for example :
    PHP Code:
    if (!defined('DIR_WS_ROOT')) {
        
    define('DIR_WS_ROOT'"http://localhost/Skeleton/");
    }
    if (!
    defined('PREG_SPECIALCHARS')) {
        
    define('PREG_SPECIALCHARS'"/.\\+*?[^]\$(){}=!<>|:");
    }
    class 
    RequestMapper_NodeRequestMapper extends RequestMapper
    {
        function & 
    mapRequest() {
            
    preg_match("/^".preg_quote(DIR_WS_ROOTPREG_SPECIALCHARS)."([^\\?\\#]*)/"$_SERVER['REQUEST_URI'], $matches NULL);
            
    $path $matches[1];
            
    $nodeFinder =& new NodeFinder();
            
    $node =& $nodeFinder->selectByPath($path);
            if (!
    is_null($node)) {
                require_once(
    'ServerPage.php');
                return new 
    ServerPage($node->getView());
            }
        }


  9. #109
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    kyberfabrikken, I will take a look at the code.

    DougBTX, I like the refactoring ideas.

    One thing I have been thinking about where the different functionality (mapping, dispatch, default dispatch, error, etc.) should be located. I looked back through the code posted by kyberfabrikken, DougBTX and myself. There are slight differences in organization, but they are functionally the same. One of my goals is that cadmiumgreen can look at the contoller code an clearly understand what the parts do.

    I think moving to using an ObjectHandle (or just Handle?) may clarify things. What would the code look like if the Mapper returned an ObjectHandle?
    Christopher

  10. #110
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If I understand you correct, yoiu are talking about a RequestMapper with some heavier logic within ?
    Yes, that is correct... Finally, there is some sense been made out of this (self imposed?) madness

    Here is what I can post at the moment,

    PHP Code:
    interface IServicable {
            public function 
    __constructIDataSource $ds );
            public function 
    getParameter$parameter );
        }
        
        abstract class 
    AbstractServicable implements IServicable {
            protected 
    $ds;
            
            public function 
    __constructIDataSource $ds ) {
                
    $this -> ds $ds;
            }
            
            public function 
    getParameter$parameter ) {
                return 
    $this -> ds -> getParameter$parameter );
            }
            
            abstract public function 
    getService();
        }
        
        class 
    SqlServicableObject extends AbstractServicable {
            public function 
    __constructIDataSource $ds ) {
                
    parent::__construct$ds );
            }
            
            public function 
    getService() {
                
            }
        }
        
        abstract class 
    AbstractMapperService implements IMapperService {
            abstract public function 
    queryIServicable $servicable );
            
        }
        
        class 
    SqlMapperService extends AbstractMapperService {
            
            public function 
    queryIServicable $servicable ) {
                
            }
        }
        
        class 
    XPathMapperService extends AbstractMapperService {
            
            public function 
    queryIServicable $servicable ) {
                
            }
        }
        
        class 
    ProcessDispatchFactory {
            private 
    $service;
            
            public function 
    __constructIMapperService $service ) {
                
    $this -> service $service;
            }
            
            public function 
    loadIServicable $servicable ) {
                return 
    $this -> service -> query$servicable );
            }
        }

    interface 
    IDataSource {
            public function 
    __construct$row );
            public function 
    getAll();
            public function 
    getInteger$parameter );
            public function 
    getParameter$parameter );
        }

    abstract class 
    AbstractDataSource implements IDataSource {
            protected 
    $parameters = array();
            
            public function 
    __construct$row ) {
                
    $this -> invoke$row );
            }
            
            public function 
    getInteger$parameter ) {
                if( 
    array_key_exists$parameter$this -> parameters ) ) { 
                    if( 
    is_int$this -> parameters[$parameter] ) ) { 
                        return 
    $this -> parameters[$parameter];
                    } else {
                        
    // final resort to determine if parameter is an integer
                        
    if( preg_match'/^[0-9]+$/'$this -> parameters[$parameter] ) ) {
                            return 
    $this -> parameters[$parameter];
                        }
                    }
                }
                return 
    false;
            }
            
            public function 
    getParameter$parameter ) {
                if( 
    array_key_exists$parameter$this -> parameters ) ) {
                    return 
    $this -> parameters[$parameter];
                }
                return 
    false;
            }
            
            public function 
    getAll() {
                return 
    $this -> parameters;
            }
            
            abstract protected function 
    invoke$row );
        }

    class 
    XmlDataSource extends AbstractDataSource {
            
    /**
             * XmlDataSource::__construct();
             * @param DomElement $row row of data
             * @access public
             * @return void
             */
            
    public function __construct$row ) {
                
    parent::__construct$row );
            }
            
    /**
             * XmlDataSource::invoke();
             * Invoke row of data as class properties.
             * @param DomElement $row row of data
             * @access protected
             * @return void
             */
            
    protected function invoke$row ) {
                if( 
    $row instanceof DomElement ) {
                    if( 
    $row -> hasChildNodes() ) {
                        foreach( 
    $row -> childNodes as $key => $parameter ) {
                            if( 
    $parameter -> nodeType == XML_ELEMENT_NODE ) {
                                
    $this -> parameters[strtolower$parameter -> nodeName )] = $parameter -> nodeValue;
                            }
                        }
                    }
                } 
            }
        }

    class 
    ArrayDataSource extends AbstractDataSource {
            public function 
    __construct$row ) {
                
    parent::__construct$row );
            }
            
            protected function 
    invoke$row ) {
                foreach( 
    $row as $key => $parameter ) {
                    
    $this -> parameters[strtolower$key )] = $parameter;
                }
            }
        }

    class 
    SqlDataSource extends AbstractDataSource // ...

    Last edited by Dr Livingston; Jun 14, 2005 at 11:26. Reason: add some script :)

  11. #111
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If I understand you correct, yoiu are talking about a RequestMapper with some heavier logic within ?
    Another functionality that we haven't discussed in the Intercepting Filter concept of Front Controller. For example, say I want to centralize access control by adding a filter in front of the dispatcher. I might make sense to put access information about an action in the map along with the dispatch information. That means the access control filter would need to get to the mapper data too. If this makes sense then having the mapper return an object with both dispatch and other information would be good. Then the mapping only happens once and the information can be passed through the filter chain.

    Conversely, for something like access control we might want more of a Dependency Injection type solution where a method or property is added to the Action so that the Action can internally deal with access control.
    Christopher

  12. #112
    SitePoint Zealot Overunner's Avatar
    Join Date
    Mar 2004
    Location
    Sweden
    Posts
    180
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What I (still) don't get is why we need all these mappers. I'm reffering to Kyber's UML-diagram where we have no less than 5 (?) mappers. What are their responsibilities?
    My current setup consists of a single ActionMapper which looks up what action(s) to execute based on a request which looks something like this: http://www.example.com/index.php?section=foo&action=bar

    Also, if I understand things correct, the ObjectHandle is for Lazy Loading, but in what part(s) of the application will that pattern be applied?

  13. #113
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    McGruff, Kyber, you appear to be confused huh?
    Yes.

    Maybe we should look at something else. Something simpler that works.

  14. #114
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Umm...

    Another functionality that we haven't discussed in the Intercepting Filter concept of Front Controller.
    What I have is that due to the page structure being of a Composite in nature, there are one or more controllers which are used to construct the page yes? So... via a Visitor, which has a series of 'known' filters (available to choose from), the configuration (for each composite node) allows the Visitor to constitute an intercepting filter chain to give pre and post processing instructions per controller, whereby the filters are selectable via the configuration from the selection available in the visitor.

    After the earlier posting I made, and McGruff and Kyber got lost, hope the above statement makes more sense this time around? Anyways, I'm not particularly happy with this, as should intercepting filters be available in this manner?

    What I ask is, that has anyone implemented intercepting filters outside of a front controller? If so, I can rest a bit more then...

  15. #115
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Maybe we should look at something else. Something simpler that works.
    Dot to dot maybe? (http://www.kidsrcrafty.com/dot-to-dot.htm)

  16. #116
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Also, if I understand things correct, the ObjectHandle is for Lazy Loading, but in what part(s) of the application will that pattern be applied?
    I was proposing that the Mappers returned an ObjectHandle.
    Christopher

  17. #117
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    I'm not sure if your high opinion of your own abilities is widely shared. Perhaps I should just leave you to it.

  18. #118
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by arborint
    There are slight differences in organization, but they are functionally the same.
    Which version of my code? The first playing I did with someone elses code in this thread, the second playing around I did with someone's code in this thread, or the other time I reinterprited someone's code in another thread?

    (I also think the lack of TDD here is telling: we have been looking for the most flexable solution, not the most useful solution, so far imo.)

    Douglas
    Hello World

  19. #119
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Which version of my code? The first playing I did with someone elses code in this thread, the second playing around I did with someone's code in this thread, or the other time I reinterprited someone's code in another thread?
    No, I just meant the various versions people have posted. You changed the code a little as I recall.
    I also think the lack of TDD here is telling: we have been looking for the most flexable solution, not the most useful solution, so far imo.
    Well we haven't got there yet, but I think we will. kyberfabrikken has put his latest code on AP3 and I have had a look it and have lots of comments. I think the time has come to escape McGruff and Dr Livingston's bickering and change this discussion to directly discuss the code and not the concepts in general. We can release something and then get comments from the forum. I know kyberfabrikken is active in this. DougBTX are you interested in coding on this as well? Others?
    Christopher

  20. #120
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm still trying to follow here so please bare with me...

    Why not have a base handle object that can return nothing - execute(), can return a string - toString(), AND can return some kind of datasource - getData()?

    toString() and getData() could call it's parent execute() method - parent::execute() or $this->execute() before the return IF needed. If those methods were shared among all handle objects then it seems that there would be much more re-usability thru the application/website?

    There could also be a display() method, which would just be echo'ing toString()

    - matt

  21. #121
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm still trying to follow here so please bare with me...
    You are getting a little ahead of us. We have not gotten to an Application Controller yet, so not Model and no View (and not much Controller).

    The Front Controller does not do much but dispatch Commands or simply include PHP pages. We have a Request object that gets the data sent to us and a Response object that will send data back. But we don't define what the Command contains or does. For the original, long forgotten question that started this post this is probably enough.

    We may get to an base Input Controller eventually, but for now it is just getting a Front Controller that is simple and flexible.
    Christopher

  22. #122
    SitePoint Zealot Overunner's Avatar
    Join Date
    Mar 2004
    Location
    Sweden
    Posts
    180
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by arborint
    The Front Controller does not do much but dispatch Commands or simply include PHP pages.
    I think the whole dispatching process should belong to the Application Controller (AC). Since there are (usually) more than one possible response to a request, it is the AC's responsibility to decide which it should be.
    Quote Originally Posted by McGruff
    If you show a login page when a user isn't authenticated, and the requested page when they are, that's one for the ApplicationController.
    The Front Controller should identify the 'type' of the request and map that to an AC. The AC in turn maps the request to a response.

    Also, the code example in this post by kyberfabrikken is a good starting point for both the AC and FC. Here is however my version in abbreviated pseudo-code-form
    PHP Code:
    class FrontController
    {
      function 
    execute(&$request, &$response)
      {
        
    /* Find out what controller and action is needed to serve the request issued by the client */
        
    $controller $request->get('controller');
        
    $action     $request->get('action');

        if (
    $controller == NULL)
          
    $response->redirect("Error404");

        if (
    $action == NULL)
          
    $action 'DefaultAction';

        
    /* Include the $controller.php, make an instance of it, and execute it */
        
    $appController = new $controller();
        
    $appController->preFilters(); // Authentication checks?
        
    $appController->dispatch($action);
        
    $appController->postFilters();
      }

    I think the FC also could be responsible for executing (global) intercepting filters like Outputbuffering, Debugging, Logging etc whereas authentication filters (which are in some manner local) needs to lie deeper down, specifically at AC level. I think this is how Mojavi also've done it.

  23. #123
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Overunner
    What I (still) don't get is why we need all these mappers. I'm reffering to Kyber's UML-diagram where we have no less than 5 (?) mappers. What are their responsibilities?
    I understand the confusion, an I'll try to clear it up a bit.
    Take the DefaultMapper first. This is the simplest possible implementation of ReuestMapper, since it always maps to one single dispatcher. It should be placed at the end of the chain to ensure that if all the other mappers fail to recognize the request, then DefaultMapper will. It would possibly contain a 404-page. It could ofcourse just be incorporated with one of the other mappers, which would reduce the number of classes (= simplicity) but also entangle responsibilities (=bad thing). I also included it to show how simple a RequestMapper could be.

    That apart, there are in fact only three concrete mappers. The baseclass (RequestMapper) is abstract, and purely organizational. If the code was written in php5, it would likely be an interface instead. I can tell from your post that you already figured that part.
    The ParamMapper is holding the common code between the three concrete decendatds and so is partially abstract. If you have alook at it, you can see that the method mapRequest() does the following ;
    * Look in the request for a certain parameter.
    * If found, call the create() method of it's decendant to create a Dispatcher.

    Each (of the three) concrete mappers then simply provides different implementations of create() to provide different types of Dispatcher. They also have different parameters, to look for.

    The three concrete mappers are ActionMapper, ServerPageMapper and ViewMapper.
    If you don't care about REST, you could do without the Action type of dispatcher. The thought was that Action's would be the target of form's or similar requests. An Action would update the model and then redirect. I believe that the correct pattern-lingo to describe Action is TransactionScript ?

    ViewMapper and ServerPageMapper are two different types of views. The latter (View) is meant to provide a TemplateView type of dispatcher. In retrospect, the class View should probably have been named TemplateView.
    The reason why I included both types was to show how both solutions were possible. Most people wouldn't use both - You would likely use either ServerPages or TemplateView.

  24. #124
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    Yes, that is correct... Finally, there is some sense been made out of this (self imposed?) madness

    Here is what I can post at the moment,
    OK. I had that comming, since I requested some code. Most of it is rather abstract - Could you show some example of how you would use it ?
    Attached Images Attached Images

  25. #125
    Employed Again Viflux's Avatar
    Join Date
    May 2003
    Location
    London, On.
    Posts
    1,127
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What about using your web server as a Front Controller and mapping directly to an Application Controller?

    Sure, you lose of some of the functionality, but you can easily implement it in the Application Controller. It also gives you the ability to modify that funtionality (that you are centralising in the FC) in the AC according to the nature of the AC and the required response.

    Just throwing something out there...


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
  •