SitePoint Sponsor

User Tag List

Page 14 of 16 FirstFirst ... 410111213141516 LastLast
Results 326 to 350 of 384
  1. #326
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    OK, I just whipped this up so it's not really spectacular or anything. This is just the way I'd like to work. And from the title of this thread, I have a feeling I'm probably getting off as it doesn't seem what I'm posting is not an application controller!

    I'm not *real* happy with the way the request object is passed to the view controller (i'd like a way to get an instance in there) but that is a different story and I should probably dl the skeleton code and try that out. The other thing is the way that the decorator gets data from it's datasources if there is a reflective property. You'll see what I mean if you have a look. I know that the view controller will look funny extending the view, but it was the fastest way to implement the reflective feature...

    matt
    Attached Files Attached Files

  2. #327
    SitePoint Guru
    Join Date
    May 2005
    Location
    Finland
    Posts
    608
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by mwmitchell
    (...)
    Do forgive me if I'm mistaken, but this looks just like everyone's basic Template view. Where's the catch?

    Nothing prevents you from working like that, of course. It's just that this solution is already known - we're trying to conjure something fancier here. At least I think that's what we're doing.

  3. #328
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hmm, I guess you could be right but I thought this was different from the fact that the data is being pased around rather than rendered content. Do you see what I mean? Which allows you to decorate the page data. Ideally the handling of the decorator would be in some sort of struct or class?

    matt

  4. #329
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The natural conclusion is that the leafs must be rendered before the root (down-up). This is precisly what the examples so far has been doing.
    Yes, that is true. I noted this in an earlier post I made. From what I can make of it there is more benifits to this, rather than the other way around.

    But why you want to do that I can't see ?
    I can't think of any reason either... Puzzled now by this suggestion.

    Matt,

    Not looked at your script yet Matt (going to download it in a moment though) but I too had a look at Decorators, in regards to Composites, and I couldn't find a viable use for them, thus... I stumbled onto the Visitor via a post made by Marcus (see 'Using Composites' thread), and since then I've stuck with it.

    I'll need to look at your script, to hazzard a guess at what your trying to do I suppose.

    There was an off the cuff remark made about the Visitors being useless, which apparently in my view, is not true. The examples I posted basically just recurse and nothing more, but in fact I make use of the Vistor in other ways as well.

    I might just be stuburn in this regard, but I remain happy enough to continue to use Visitors, even if there is now another option?

  5. #330
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    You can convert a hierarical structure to a linear one by simply recursing through and push to a stack. But why you want to do that I can't see ?
    You are correct. What you are doing is traversing the correct way. I do like your code to and am going to try some real-world test on it.

    Looking at the 'skeleton' code I think it would make sense to add these Component features to the Response. That way you could not only gather the rendered content from the tree, but also any headers and redirects that sub views generated.

    Also, following on from my not liking to use Structural pattern names. I would suggest that you change the name of Component to View (or SubView or ViewNode or TreeView or ViewComponent or ViewRender ... you guys will think of something) because the dependency on $this->view->set() and $this->view->set() makes it more than a generic Component.
    Christopher

  6. #331
    SitePoint Guru
    Join Date
    May 2005
    Location
    Finland
    Posts
    608
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by arborint
    Looking at the 'skeleton' code I think it would make sense to add these Component features to the Response. That way you could not only gather the rendered content from the tree, but also any headers and redirects that sub views generated.
    This sounds interesting. Yet again do I ask for a concrete example.
    Also, following on from my not liking to use Structural pattern names. I would suggest that you change the name of Component to View (or SubView or ViewNode or TreeView or ViewComponent or ViewRender ... you guys will think of something) because the dependency on $this->view->set() and $this->view->set() makes it more than a generic Component.
    I thought I did a pretty good job with that a few posts back: IComposite -> Composite -> ViewComposite. Don't you agree? s/Composite/Component should be fine as well, since it's often used in this pattern. The name should communicate the structure, which these two do.

  7. #332
    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 arborint
    Looking at the 'skeleton' code I think it would make sense to add these Component features to the Response. That way you could not only gather the rendered content from the tree, but also any headers and redirects that sub views generated.
    I'm not sure what you mean by this, but instead of a method render() on the components, which returns data, we should probably have the same signature as the IHandler (that is - $request, $response ... or simply $context). We need some sort of buffer on the response, so that a subview will not override the content of other views.

    It could be something like :
    PHP Code:
    class Component
    {
        (...)
        function 
    execute(&$context) {
            for (
    $i=0,$l=count($this->children); $i $l; ++$i) {
                
    $context->response->startBuffer();
                
    $this->children[$i]->execute($context);
                
    $this->view->set($this->children[$i]->getId(), $context->response->flushBuffer());
            }
            
    $context->response->setContent($this->render($context));
        }
    }

    class 
    Response
    {
        var 
    $content;
        var 
    $buffers = Array();

        function 
    setContent($content) {
            
    $this->content $content;
        }

        function 
    getContent() {
            return 
    $this->content;
        }

        function 
    startBuffer() {
            
    $this->buffers[] = $this->content;
            
    $this->content "";
        }

        function 
    flushBuffer() {
            
    $buffer $this->content;
            
    $this->content array_pop($this->buffers);
            return 
    $buffer;
        }

        function 
    out() {
            echo 
    $this->content;
        }


    Quote Originally Posted by arborint
    Also, following on from my not liking to use Structural pattern names. I would suggest that you change the name of Component to View
    Actually, I'd say that Component is clearly a controller, so perhaps it should be renamed to Controller (or perhaps ***Controller, where *** may be something like Hierarichal ?)

  8. #333
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Using output buffering, the buffers can be nested, in the order that you start them, so this is a convienence.

    So... Instead of having the given tag in a template replaced with content, ie <body /> in the examples I posted, the Visitor, the string replacement would take place in the Response instead.

    Therefore this is where the recursion would take place, since as I've already said, the buffers are nested in the correct order for you

    I see the Visitor being the Response anyways, which I've said as much in earlier posts in regards to the use of the Visitor yes?

  9. #334
    SitePoint Guru
    Join Date
    May 2005
    Location
    Finland
    Posts
    608
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    I'm not sure what you mean by this, but instead of a method render() on the components, which returns data, we should probably have the same signature as the IHandler (that is - $request, $response ... or simply $context). (...) Actually, I'd say that Component is clearly a controller
    I thought it was a good idea to separate the tree from the rendering process. I don't quite agree on Component being a Controller, but the Renderer might as well be.
    PHP Code:
    class Renderer implements IHandler
    {
        
    // (...)
        
    public function execute(Context $context)
        {
            
    $this->process($this->composite);
            
    $context->response->setContent($this->render());
        }

    By the way, could you give me some explanation as to why the render process should be bottom-up? I think it'd be great if it were linear, which is kinda top-down, but that would require a compiling stage.
    Last edited by Ezku; Aug 13, 2005 at 04:57.

  10. #335
    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 Ezku
    I don't quite agree on Component being a Controller
    What is it then ? The Component assigns data from the model-layer to the view-layer. Isn't that a controller ?

    Quote Originally Posted by Ezku
    PHP Code:
    (...)
    $this->process($this->composite);
    $context->response->setContent($this->render()); 
    Why would you want to separate process() from render() ? What do you gain by not simply having one call ?

    Quote Originally Posted by Ezku
    By the way, could you give me some explanation as to why the render process should be bottom-up?
    I can hardly be more explicit than in my previous post. I think we are talking by each other here. With bottom-up I mean in respect to the rendering-tree - not the output. Your example which includes a header may confuse this distinction, since in the result (html-output), the header is parent to the content, but in the rendering-tree, the header is a child of content.

    Quote Originally Posted by Ezku
    I think it'd be great if it were linear, which is kinda top-down, but that would require a compiling stage.
    What exactly do you mean by "linear" ?

  11. #336
    SitePoint Guru
    Join Date
    May 2005
    Location
    Finland
    Posts
    608
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    The Component assigns data from the model-layer to the view-layer.
    I don't think it does that; the nodes do. Where does the Component get involved with Model data?
    Why would you want to separate process() from render() ? What do you gain by not simply having one call ?
    Sorry about that. Hadn't anything to do with want, I just built the function on top of what I already had.
    Your example which includes a header may confuse this distinction, since in the result (html-output), the header is parent to the content, but in the rendering-tree, the header is a child of content. (...) What exactly do you mean by "linear" ?
    Perhaps this is best demonstrated with an example:
    PHP Code:
    <div id="header"><?php include 'header.php' ?></div>
    <div id="body"><?php include 'body.php' ?></div>
    This is executed linearly: the parser stumbles upon an include, runs the file and then returns to the flow where it left. I've used the terms "flat" and "compiled" in a sense essentially similar to this. Compare this to the two other types of execution we have here:
    PHP Code:
    <div id="header"><core:import select="Header" /></div>
    <
    div id="body"><core:import select="Body" /></div
    This is parsed top-down: it's first executed as PHP code in its entirety, and then the import statements are replaced with the data that processing the children resulted in.
    PHP Code:
    <div id="header"><?php echo $child->header ?></div>
    <div id="body"><?php echo $child->body ?></div>
    This is parsed bottom-up: the container $child has the results from processing the children, and they're output when the script is parsed as PHP.

    The difference between these three is how shared data flows from parent to children or vice versa. Top-down and bottom-up both share the annoying property of non-linearness, which, if unexpected, can result in funky results when laying out a set of templates.

    I might be horribly mistaken, in which case please do correct me.

  12. #337
    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)
    Calling it linear is a peculiar choice. Example 1 can still split up into seperate paths, so the rendering is a tree-structure. In both examples, the page has a dependency on body and header. Both body and header must be rendered fully brefore the main element can render.
    The difference is who is in control of fulfilling theese dependencies. In the first example the page pulls data in, whereas the second one is passive - the data is pushed. Since the first example is an active player in the execution-chain, the method can be considered as mixing controller with view, where the second example has a waterproof seperation.

  13. #338
    SitePoint Guru
    Join Date
    May 2005
    Location
    Finland
    Posts
    608
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    Calling it linear is a peculiar choice.
    I thought you'd understand that. Although the execution is split into several files, it still progresses in a linear fashion. You could take the scripts from header.php and body.php and place them in index.php, and the result would be identical. Not so with the two other methods.
    The difference is who is in control of fulfilling theese dependencies.
    That's another difference, yes. I don't exactly fancy having a View's relations forced externally, but it seems inavoidable if you want to have a structure like this.

  14. #339
    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 Ezku
    You could take the scripts from header.php and body.php and place them in index.php, and the result would be identical. Not so with the two other methods.
    Why can't that be done in the other example(s) ?

  15. #340
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    I'm not sure what you mean by this, but instead of a method render() on the components, which returns data, we should probably have the same signature as the IHandler (that is - $request, $response ... or simply $context). We need some sort of buffer on the response, so that a subview will not override the content of other views.
    If I follow my idea of merging this and the Response. What if when you passed the Response you instead passed an attached child. I am just thinking out loud here, but something like:
    PHP Code:
    $this->execute($request$response->getAttachedChild('name')); 
    Then the root Response would render the tree after all the Controllers were done.
    Quote Originally Posted by kyberfabrikken
    Actually, I'd say that Component is clearly a controller, so perhaps it should be renamed to Controller (or perhaps ***Controller, where *** may be something like Hierarichal ?)
    I think calling ViewController starts giving me an idea of what it really does.
    Christopher

  16. #341
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    Of course I couldn't resist such a challenge. I'm still a bit puzzled on how it fits with the rest of the skeleton code.
    Just a quicky... If I place the "footer" node in the xml file above the "body" node, the "menu" doesn't get rendered. Is there a reason for this?

    Matt

  17. #342
    SitePoint Guru
    Join Date
    May 2005
    Location
    Finland
    Posts
    608
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    Why can't that be done in the other example(s) ?
    Because of execution order, the result will be different. In those examples it's admittedly not evident, but it gets to that when you introduce shared data.

    I constructed an example using the latest standard Renderer and a ReverseRenderer that renders the tree bottom-up instead of top-down. I think this will make my point clear.

    Index.tpl:
    Code:
    <p>Index.tpl. Rendered: <?php echo ++$vars->rendered; ?></p>
    <core:import select="Foo" />
    <p>Index.tpl. Rendered: <?php echo ++$vars->rendered; ?></p>
    <core:import select="Foo" />
    Foo.tpl:
    Code:
    <p>Foo.tpl. Rendered: <?php echo ++$vars->rendered; ?></p>
    The test setup:
    PHP Code:
    $composite = new ViewComposite(new Template('Index.tpl'));
    $composite->attach(new ViewComposite(new Template('Foo.tpl')));

    $renderer = new (Reverse)Renderer($composite);
    $renderer->setDefaults(array('rendered' => 0));
    $renderer->execute($context); 
    And the results... with Renderer:
    Code:
    Index.tpl. Rendered: 1
    Foo.tpl. Rendered: 3
    Index.tpl. Rendered: 2
    Foo.tpl. Rendered: 3
    And with ReverseRenderer:
    Code:
    Index.tpl. Rendered: 2
    Foo.tpl. Rendered: 1
    Index.tpl. Rendered: 3
    Foo.tpl. Rendered: 1
    Assuming I did the same with a "linear" setup, the results would be the following:
    Code:
    Index.tpl. Rendered: 1
    Foo.tpl. Rendered: 2
    Index.tpl. Rendered: 3
    Foo.tpl. Rendered: 4
    I'll later attach a code package with the working code and demonstration.
    Last edited by Ezku; Aug 13, 2005 at 14:01.

  18. #343
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Just wanted to say thanks to all you guys working out this problem. This is fascinating to watch and read! It's quite a challenge for me to follow but I'm getting it and begining to understand what you're after. Keep up with the great ideas!

    matt

    ps, Where can I get the latest skeleton/application/controller/input/validation code?

  19. #344
    SitePoint Guru
    Join Date
    May 2005
    Location
    Finland
    Posts
    608
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by mwmitchell
    Where can I get the latest skeleton/application/controller/input/validation code?
    There you go. To be honest I think we're sidetracking a bit now, but that isn't necessarily bad. Everyone's learning something here, if you ask me.

  20. #345
    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 mwmitchell
    Just a quicky... If I place the "footer" node in the xml file above the "body" node, the "menu" doesn't get rendered. Is there a reason for this?
    No. That's a bug of some kind.

    Edit : A Working version of XML_Unserializer :
    PHP Code:
    class XML_Unserializer
    {
        var 
    $stack;
        var 
    $arrOutput;
        var 
    $nullToken "null";

        function 
    unserialize($strInputXML) {
            
    $p xml_parser_create();
            
    xml_set_element_handler($p, Array(&$this'startHandler'), Array(&$this'endHandler'));
            
    xml_set_character_data_handler($p, Array(&$this'dataHandler'));
            
    $this->stack = Array(Array('children' => Array()));
            
    xml_parse($p$strInputXML);
            
    xml_parser_free($p);

            
    $root $this->buildArray($this->stack[0]);
            unset(
    $this->stack);
            
    $this->arrOutput $root['root'];
            return 
    $this->arrOutput;
        }

        function 
    getUnserializedData() {
            return 
    $this->arrOutput;
        }

        function 
    buildArray($stack) {
            if (
    count($stack['children']) == 0) {
                return 
    trim($stack['data']);
            }
            if (
    count($stack['children']) == 1) {
                
    $key array_keys($stack['children']);
                if (
    $stack['children'][$key[0]]['name'] === $this->nullToken) {
                    return 
    NULL;
                }
            }
            
    $keycount = Array();
            foreach (
    $stack['children'] as $child) {
                
    $keycount[] = $child['name'];
            }
            if (
    count(array_unique($keycount)) != count($keycount)) {
                
    // enumerated array
                
    $children = Array();
                foreach (
    $stack['children'] as $child) {
                    
    $children[] = $this->buildArray($child);
                }
                return 
    $children;
            } else {
                
    // indexed array
                
    $children = Array();
                foreach (
    $stack['children'] as $child) {
                    
    $children[$child['name']] = $this->buildArray($child);
                }
                return 
    $children;
            }

        }

        function 
    startHandler($parser$name$attribs = Array()) {
            
    $token = Array();
            
    $token['name'] = strtolower($name);
            
    $token['data'] = "";
            
    $token['children'] = Array();
            
    $this->stack[] = $token;
        }

        function 
    endHandler($parser$name$attribs = Array()) {
            
    $token array_pop($this->stack);
            
    $this->stack[count($this->stack) - 1]['children'][] = $token;
        }

        function 
    dataHandler($parser$data) {
            
    $this->stack[count($this->stack) - 1]['data'] .= $data;
        }
    // end class XML_Unserializer 
    Last edited by kyberfabrikken; Aug 14, 2005 at 14:26.

  21. #346
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    No. That's a bug of some kind.
    OK, it has to do with the way the xml parser is handling child nodes. If there is more than one it creates and indexed array with the child nodes within, if only one then it creates an associative (key named 'component') and then the properties of the component node as keys.

    Matt
    Last edited by mwmitchell; Aug 14, 2005 at 06:48.

  22. #347
    SitePoint Wizard DougBTX's Avatar
    Join Date
    Nov 2001
    Location
    Bath, UK
    Posts
    2,498
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @kyberfabrikken: could you edit the the first post in this thread to point to the posts with the latest code in them? I know it would be more helpful to me, as someone who's not been keeping up with development, if I could find all the current code in one place

    Thanks!

    And to see if I can contribute something useful, here is some code to run all the tests in a directory:

    EDIT: nope, I can't: use timvw's code. It is much better!

    70+ lines in the current file, 7 lines in timvw's. And it does more too. Now, apply that to the whole codebase
    Last edited by DougBTX; Aug 16, 2005 at 17:19.
    Hello World

  23. #348
    SitePoint Addict timvw's Avatar
    Join Date
    Jan 2005
    Location
    Belgium
    Posts
    354
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Meaby offtopic, but this is my preferred way to run load all the tests:

    PHP Code:
    $test = &new GroupTest('All file tests');
    foreach(
    glob(dirname(__FILE__) . '/test_*.php') as $testfile)
    {
      
    $test->addTestFile($testfile);

    And this is how i run them..

    PHP Code:
    require_once(dirname(__FILE__) . '/all_tests.php');

    if (
    TextReporter::inCli())
    {
      
    $test->run(new TextReporter());
    }
    else
    {
      
    $test->run(new HtmlReporter());

    I feel this is the easiest setup to run tests from simpletest/eclipse plugin, webpage or cli.

  24. #349
    SitePoint Wizard
    Join Date
    Aug 2004
    Location
    California
    Posts
    1,672
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Not offtopic, that is a really clean way to run all tests. One of my comments on SimpleTest was that there were no standard files like this shipped with it (Marcus noted that he had been keeping the releases minimal during development which makes a lot of sense). But it would be nice to have something like this so that peoples "tests" directory looked similar.

    Is there a reason why you split it into two files instead of all in one?

    all_tests.php
    PHP Code:
    $test = &new GroupTest('All file tests');
    foreach(
    glob(dirname(__FILE__) . '/test_*.php') as $testfile)
    {
      
    $test->addTestFile($testfile);
    }

    if (
    TextReporter::inCli())
    {
      
    $test->run(new TextReporter());
    }
    else
    {
      
    $test->run(new HtmlReporter());

    Christopher

  25. #350
    SitePoint Addict timvw's Avatar
    Join Date
    Jan 2005
    Location
    Belgium
    Posts
    354
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If i use the eclipse plugin to "run" the all_tests.php it would run the tests (html/text reporter) and then the plugin would run them again with a xmlreporter.

    Keeping the "running" outside of the "grouptest building up" seemed the most straight forwarded solution to overcome this issue.

    (Currently i'm using a customized plugin that allows me to choose my own simpletest files instead of those delivered with the plugin, but the author e-mailed me last week that the modifications would be in the next release )


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
  •