Page 5 of 9

Posted: Mon Apr 16, 2007 3:10 am
by Maugrim_The_Reaper
There is far too much attention focused in /library. As it stands the choice is a) /Zend or b) /library/Zend. It's arguing over the addition of 8 additional characters to an include_path in one file. And that's it. There are very few other advantages to adding a /library dir which are not obvious preferences (i.e. they definitely have no logical reason). Over time the addition of more than one library may simply make it more convenient to use a /library, and such a change requires zero real effort. For now there's only one library - Zend.

Are we really going to spend another page arguing over a directory placement? It's not worth the effort - people are free to change this if they want, afterall some people may not need a /library or /Zend at all because they just use a different local copy, maybe through PEAR.
ole wrote:If you are sure you are correct I accept that as a fair and strong point.
It should be in the PHP manual somewhere. Also I forgot another reason - http://httpd.apache.org/docs/2.0/mod/co ... owoverride . It's one of those issues you don't see unless you are running PHP as CGI so that's how I know it.

Posted: Mon Apr 16, 2007 8:27 am
by Maugrim_The_Reaper
Made the next logical step and moved the "Hello World!" text into an HTML view. For those keeping watch, the code is in subversion so be sure to checkout a copy!

zfPetShop/default/views/scripts/helloworld.phtml:

Code: Select all

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Index</title>
</head>
<body>
<p>Hello World!</p>
</body>
</html>
In using Zend_View, the simplest method is now to rely on the Zend_Controller_Action initView() method. It should be noted this is perfectly useless if Zend_View is subclassed. Because of this, Zend_View is instantiated in Zps_Controller_Action where we set some default values - like setting the escape method to htmlentities(), not the only-God-knows-why default of htmlspecialchars(). Did a little refactoring here to split out init phases.

zfPetShop/extends/Zps/Controller/Action.php:

Code: Select all

class Zps_Controller_Action extends Zend_Controller_Action
{

    /**
     * Instance of Zend_Registry passed by Zend_Controller_Front as an
     * invocation argument.
     *
     * @var Zend_Registry
     * @access protected
     */
    protected $registry = null;

    /**
     * init() method called by Zend_Controller_Action constructor to setup
     * this Action (or its subclasses). Used here to assign FC params as
     * class properties.
     *
     * @return void
     * @access public
     */
    public function init()
    {
        $this->initRegistry();
        $this->initView();
        $this->initResponseHeaders();
    }

    protected function initRegistry()
    {
        if ($this->getInvokeArg('Registry') instanceof Zend_Registry) {
            $this->registry = $this->getInvokeArg('Registry');
        }
    }

    public function initView()
    {
        parent::initView();
        $this->view->setEncoding( $this->registry->get('Configuration')->output_encoding );
        $this->view->setEscape('htmlentities');
        $this->view->strictVars(); // elicit Notice level errors if a non-existing value is requested via __get()
    }

    public function initResponseHeaders()
    {
        $charset = $this->registry->get('Configuration')->output_encoding;
        $this->getResponse()->setHeader('Content-Type', 'text/html; charset=' . $charset);
    }

}
There's a spot of fluid interface usage in here if nobody minds... Least it made sense here ;). A Registry value for "application_dir" is now added in the bootstrap.php file. I also modified the default Response headers to pass the output encoding (so we needn't rely on HTML meta-equiv to do it).

In the future, if Zend_View is subclassed the init() method will need to be rewritten (largely because Zend_Controller_Action is coupled to the Zend_View class name) to instantiate the subclass. In that case the parent::initView() line will not be required.

Posted: Mon Apr 16, 2007 2:39 pm
by Christopher
I see where you are going with this. However I have a general reservation about this idea that the Action View should generate the entire response. This is how the Zend guys seem to think and I still see a lot of what I call "serial header/footer output" thinking.

I happen to think that Action Views should really be in the business of generating the minimum unique part of the content possible. That keeps the Action (and the programmer) focused. For most pages in a site ony the content pane changes per page. There may be section layouts, sidebars, or menu variations, but again I think they should be handled outside the View -- perhaps requiring some data generated by the View. I think this would promote modularization and reuse of interface components, even if only for simple things like maintaining main navigation state. We may enable programmers to build more powerful interfaces if we encourage modularity.

So if possible I would like to try a hierarchical system, even if it is only three layers: HTML header, layout, Action content. If we can do sub-Views in a clear clean way all the better.

So I would rather move the headers and layout to a higher level where they can be modularized. It probably needs to be Lazy Loaded since the Action obviously needs to set values needed by the higher levels. That means the code should run after dispatch returns the Response object. I should note that in cases where there is a redirect or a non-HTML response was generated (e.g., data feed or download) then the Response can choose to only do the minimum needed.

Posted: Mon Apr 16, 2007 4:04 pm
by Maugrim_The_Reaper
arborint wrote:I see where you are going with this. However I have a general reservation about this idea that the Action View should generate the entire response. This is how the Zend guys seem to think and I still see a lot of what I call "serial header/footer output" thinking.
The way I've started just goes with the ZF practice - which I don't agree with either ;). I definitely prefer subclassing Zend_View since it let's me add rebellious features like automatic output escaping si I don't need to type "$this->escape($this->var);" everywhere. I never liked that approach - we have automatic escaping in prepare statements for the DB, why not the view? Enforce it consistently and programmers will have fewer opportunities to introduce mistakes.

The serial nature is pretty common, which explains the approach - the ZF follows the 80/20 rule, so those of us in the 20% where the framework proves imperfect resort to subclassing to make the necessary modifications. I do think they underestimated this in the View - they reverted from a decoupled class, to a set of helper methods in Zend_Controller_Action (like initView()) which adds coupling to Zend_View. That pretty much rules out using them in our scenario - it's poor practice to couple unrelated classes just to save a few lines of code. Adding a Zps_View subclass would force the needed refactoring.
arborint wrote:For most pages in a site ony the content pane changes per page. There may be section layouts, sidebars, or menu variations, but again I think they should be handled outside the View -- perhaps requiring some data generated by the View.
The appropriate method advocated in the framework is the View Helper. It has a few issues however, it's rutted in a convention which only allows for one public method. There's no defined convention for attaching sub-templates (e.g. the skeleton layout for a static navigation menu). Recently they modified this (not sure if documented in the manual which is a bit out of date) where the View Helper can access the entire View object to use the View's model. I don't think there's a method for passing in a modified model the View itself creates except through the single public method allowed.

The other thing here is that sub-Views should avoid becoming a mess of additional dispatch runs into separate controllers. Dispatching is pretty expensive just to grab a tidbit of data for static elements on a page. So part of the problem is getting enough data to a helper/other to create a static element without intervening from the level of a controller action method (at the risk of duplicating code).
arborint wrote:I think this would promote modularization and reuse of interface components, even if only for simple things like maintaining main navigation state. We may enable programmers to build more powerful interfaces if we encourage modularity.
Looking at Zend_View, assuming it's the basis for subclassing, do you want to suggest a barebones system or interface to hook into from the View?
I should note that in cases where there is a redirect or a non-HTML response was generated (e.g., data feed or download) then the Response can choose to only do the minimum needed.
I'm thinking of all the neat RESTful paths I have in an application kicking out JSON and XML ;). I don't typically add any specialised AJAX handling inside my apps. The fact the paths are unique is good enough to organise the appropriate responses - though I think the ZF had something a while back (maybe just a mailing list suggestion I passed over) about dynamically detecting AJAX requests and handling them as a special case. Sounded a bit too complex so I wasn't paying attention.

Posted: Mon Apr 16, 2007 4:17 pm
by John Cartwright

Code: Select all

protected function initRegistry()
    {
        if ($this->getInvokeArg('Registry') instanceof Zend_Registry) {
            $this->registry = $this->getInvokeArg('Registry');
        }
    }
Maugrim, in the code you posted in your last code, more speficially the code shown above, I think you should throw an exception if an invalid registry object was passed. Currently, if an invalid registry object was not passed it will simply not set the registry var, however, you are still calling $this->registry throughout the rest of the action controller even though it won't neccesarily exist.

Hope it helps. Keep up the great work guys.

Posted: Mon Apr 16, 2007 4:49 pm
by Christopher
Maugrim_The_Reaper wrote:The appropriate method advocated in the framework is the View Helper. It has a few issues however, it's rutted in a convention which only allows for one public method. There's no defined convention for attaching sub-templates (e.g. the skeleton layout for a static navigation menu). Recently they modified this (not sure if documented in the manual which is a bit out of date) where the View Helper can access the entire View object to use the View's model. I don't think there's a method for passing in a modified model the View itself creates except through the single public method allowed.
I don have a problem with View Helpers when they are used as helpers. That means within the output of the View. I thinks using the make the View some Super-View is the kind of feature creep we see in ZF where they keep patching rather than reviewing/revising the basic design of the thing.
Maugrim_The_Reaper wrote:The other thing here is that sub-Views should avoid becoming a mess of additional dispatch runs into separate controllers. Dispatching is pretty expensive just to grab a tidbit of data for static elements on a page. So part of the problem is getting enough data to a helper/other to create a static element without intervening from the level of a controller action method (at the risk of duplicating code).
I agree. Sub-Views should not require a Controller if they are attached to a View. I think that anything with a render() method should be able to be attached to a named part of a View and just work -- that should be our goal.
Maugrim_The_Reaper wrote:Looking at Zend_View, assuming it's the basis for subclassing, do you want to suggest a barebones system or interface to hook into from the View?
I think we need to balance the functionality between the View and the Response. I would lean toward having the Response be in charge of "page building" in the sense of keeping track of headers, encodings, scripts, styles, etc. In turn I would lean toward making the View move closer to a Super-Template than it is now. I see the View as the Active Record of Template classes. It allows you to add more logic and smarts (if you want to) to a Template, but at its core it still simply holds and associates content with a named part of the output.
Maugrim_The_Reaper wrote:I'm thinking of all the neat RESTful paths I have in an application kicking out JSON and XML ;). I don't typically add any specialised AJAX handling inside my apps. The fact the paths are unique is good enough to organise the appropriate responses - though I think the ZF had something a while back (maybe just a mailing list suggestion I passed over) about dynamically detecting AJAX requests and handling them as a special case. Sounded a bit too complex so I wasn't paying attention.
Yes exactly (I think ;)). What I am looking for is to be able to define a default Main View so that if an action just has some content to display in a standard layout then it just creates the content and the Response builds the page. So the programmer does the minimum work for the most common task.

For the exceptional stuff, like you RESTful paths, the Action simply gives the Response a Custom Main View, builds the content, and returns. The The default Main View is only Lazy Loaded (after dispatch) if the Action hasn't defined a custom one.

Maybe something between dispatch and send like this:

Code: Select all

$Response = $Front->dispatch();

// if no custom main view defined
if (! $Response->hasView()) {
    // create main view object
    // associate values/renderers in response to parts of main view
}

$Response->render();    // or do we need to render hierarchy?

$Response->sendResponse();

Posted: Mon Apr 16, 2007 4:58 pm
by John Cartwright
In reguards to lazy loading a layout view (sorry you lost me on the terminology of the different views), how would you differentiate between controllers/actions that require a completely seperate layout view or none at all in comparison to the rest of the application?

Posted: Mon Apr 16, 2007 5:36 pm
by Maugrim_The_Reaper
Jcart wrote:Maugrim, in the code you posted in your last code, more speficially the code shown above, I think you should throw an exception if an invalid registry object was passed. Currently, if an invalid registry object was not passed it will simply not set the registry var, however, you are still calling $this->registry throughout the rest of the action controller even though it won't neccesarily exist.
Nice catch!!! Added the exception throw in subversion.

Checking the code, they did add AJAX detection to the Request object - assuming that's the full extent it's a weird little piece of feature creep for a simple one line task. I wonder what the point was?

Code: Select all

/**
     * Is the request a Javascript XMLHttpRequest?
     *
     * Should work with Prototype/Script.aculo.us, possibly others.
     * 
     * @return boolean
     */
    public function isXmlHttpRequest()
    {
        return ($this->getHeader('X_REQUESTED_WITH') == 'XMLHttpRequest');
    }
I think we need to balance the functionality between the View and the Response. I would lean toward having the Response be in charge of "page building" in the sense of keeping track of headers, encodings, scripts, styles, etc. In turn I would lean toward making the View move closer to a Super-Template than it is now. I see the View as the Active Record of Template classes. It allows you to add more logic and smarts (if you want to) to a Template, but at its core it still simply holds and associates content with a named part of the output.
I'd lean towards an intermediary between View and Response leaving Zend's Response class relatively untouched - it's already a complicated piece of code. I'm reaching for a name but it's not coming to me. As things are at the moment the Response and View (outside of ZF's brilliant stroke of introducing coupled Response/View/Action methods in 0.90) are separated well enough. So introducing a middle man wouldn't be that difficult.

It's a question of stating a use case, showing the solution (hence interface) and implementing it with unit tests. Nice neat TDD approach ;). How would this related to the ZF conception of a View? Subclassed Zend_View which applies namespacing with the middle man acting as an abstraction layer to the new interface? Would be really light weight if the existing Zend_View methods were still applied, only to page elements and not the whole thing at once.

Code: Select all

$Response = $Front->dispatch();

// if no custom main view defined
if (! $Response->hasView()) {
    // create main view object
    // associate values/renderers in response to parts of main view
}

$Response->render();    // or do we need to render hierarchy?

$Response->sendResponse();
Getting too late to think straight over here, but what I described would still be handled with the Action init() phase since the Response would still be a typical Zend class, only holding the output of the middle man class which is abstracting to Zend_View (or rather a modified Zps_View subclass with the named section support).

Hopefully some of that makes sense - I think better in the morning ;).

Posted: Mon Apr 16, 2007 5:49 pm
by Christopher
Jcart wrote:In reguards to lazy loading a layout view (sorry you lost me on the terminology of the different views), how would you differentiate between controllers/actions that require a completely seperate layout view or none at all in comparison to the rest of the application?
I get a little confused myself by the terminology. The short answer is that if the Action (View or Controller) wants something different than the default Main View (head and layout) then it gives the response a custom View to use. If you do nothing you get the default Main View. The Action can also just change the layout, or add a script or style to the head -- still using the Main View.

Let me see if I can show some examples. A Main View might render this:

Code: Select all

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title><?php echo $response->view->title; ?></title>
<?php echo $response->view->scripts; ?>
<?php echo $response->view->styles; ?>
</head>
<body>
<div id="mainwrapper">
     <?php echo $response->view->layout; ?>
     <div id="maincopyright">
     Copyright 2007. No rights reserved.
     </div>
</div>
</body>
</html>
Here is a layout:

Code: Select all

<div id="mainlayout">
     <div id="mainmenu">
          Home | Shop | AboutUs | Contact Us
     </div>
     <div id="maincontent">
          <?php echo $response->view->content; ?>
     </div>
     <div id="mainsidebar">
          <?php echo $response->view->sidebar; ?>
     </div>
</div>
The Main View would have defaults and then would get values from the Action from the Response:

Code: Select all

$MainView = new View();
$MainView->title = 'My Site';
$MainView->scripts[] = '<script src="/scripts/common.js" type="text/javascript"></script>';
$MainView->styles[] = '<link rel="stylesheet" href="/styles/main.css" type="text/css">';
$MainView->layout= '';

$MainView->title = $Response->view->title;
$MainView->layout = $Response->view->layout;
I see all sorts of things I don't like already but maybe it gives you an idea of the levels.

Posted: Mon Apr 16, 2007 5:56 pm
by John Cartwright
arborint wrote:The short answer is that if the Action (View or Controller) wants something different than the default Main View (head and layout) then it gives the response a custom View to use. If you do nothing you get the default Main View. The Action can also just change the layout, or add a script or style to the head -- still using the Main View.
Exactly what I wanted to hear, thanks arborint!

Posted: Tue Apr 17, 2007 3:28 am
by Maugrim_The_Reaper
Drew a blank last night but I remember now, this is an example moving in the direction of the Composite View design pattern. Basically separation of concerns again - separating individual elements from the overall layout of the page. I'll now return to my client chasing happy we have a common language name for it at last...;). Note this hints at the name of the class sitting between the Response and Zend_View - I still think we should extract this functionality from the examples which show it embedded in the Response object.

Posted: Tue Apr 17, 2007 10:10 am
by Maugrim_The_Reaper
Playing with the idea of a Composite View, this assumes we have multiple objects of the same interface (typical composite) sharing a render() method - this throws back to arborint's suggestion:
arborint wrote:I agree. Sub-Views should not require a Controller if they are attached to a View. I think that anything with a render() method should be able to be attached to a named part of a View and just work -- that should be our goal.
So rendering any specific class of type (e.g. Zps_View_Interface) will render itself, and obviously call render() on all it's children. Typical Composite pattern really. This removes an arbitrary hierarchy (e.g. header, content, footer) and delegates them to generic classes of implementing the interface, either as composites (seems likely for some) or leafs. Of course each composite is itself a Layout into which its children are rendered.

The question here is what does the actual rendering, and how does it integrate Zend_View? There are two options - firstly and likely the most common, we use multiple Zend_View instances per leaf/composite. A leaf could just be the basic Zps_View subclass (which enforces the refactoring to deny the current Zend_Controller_Action/Zend_View coupling) with the composite being an additional subclass: Zps_View_Composite which is basically the additional code to handle a collection of leafs or other composites.

Code: Select all

interface Zps_View_Interface
{

    public function render();

}

class Zps_View extends Zend_View implements Zps_View_Interface
{

    public function __construct(){}

    public function render(){}

}

interface Zps_View_Composite_Interface
{

    public function attach($tag, Zps_View_Interface $view);

    public function detach($tag);

    public function childExists($tag);

    public function hasChildren();

    public function getChildren();

}

class Zps_View_Composite extends Zps_View implements Zps_View_Interface, Zps_View_Composite_Interface
{

    private $nodes = array();

    private $tag = '';

    public function __construct(){}

    public function render(){}

    public function attach($tag, Zps_View_Interface $view){}

    public function detach($tag){}

    public function isChild($tag){}

    public function hasChildren(){}

    public function getChildren(){}

    public function getTag(){}

}
From there it's a matter of meshing the views. Having each Zps_View render it's assigned template according to whatever model it receives/requests, aggregating those renderings by tag within the parent composite (which becomes a partial model for rendering composite templates for layouts), and so on up the Composite tree until the root parent is rendered and passed into the Response class.

That's a very brief description, so sorry if a few things seem vague - I felt it was better to leave it open ended for discussion before explaining every minute detail. This only addresses the OO part - the templates themselves need to refer to the tags in order for the each composite to correctly put each child's render output in its correct place.

I also haven't addressed getting the model - esp. where it comes from. If there is a re-useable widget which displays a list of News Headlines from the database, then the current controller won't be handling that data - it needs to be drawn into the View (and passed down the chain perhaps?) from another point in the application. Which leads us into whether View Helpers (not necessarily the ZF definition, but the actual pattern) should be brought to bear to allow the View read in a model without relying totally on the controllers.

In other words, Views may have a executable section to make View Helper calls which grab a model (pull, not the ZF's default push system) for the sub-View to use in rendering it's assigned template.

Another thought is how templates are assigned - generic classes given a template name at instantiation, or a single object->template mapping like a traditional Strategy?
hh
P.S. I said I think better in the morning...;)


More questions:

- When are Views pulled into the composite structure? It can be done manually - think PHP DOM approach, or through an automated means based on templates though not sure exactly how. Doing it within templates seems too much, but then one alternative (configuration) is as bad...

- How should the View and Model interface? Assuming we avoid controllers, this would indicate the View needs to have read access to the Model (not controller pass through). Important to note the distinction between ZF view helpers and the View Helper Pattern. I'm starting to wish the ZF paid more attention to how it named those helper classes...

- Is it viable to use what amounts to multiple Zend_View objects as the basis of leafs and composites? Is there an alternate strategy relying on namespaces in a single object worth persuing? More a thought for now - if using multiple Zend_Views is easier then that's how it should be done (refactor later if it proves an optimisation stick up).

- Should Views carry a reference to the overall parent view, since that's where controllers end up assigning the current Model? I'm thinking they should have access to at least a copy or read-only version to keep all Views isolated (one not being able to influence another by altering the Model).

- Does any of this paticularly long post make any sense? :)

Posted: Tue Apr 17, 2007 1:24 pm
by Christopher
Maugrim_The_Reaper wrote:Playing with the idea of a Composite View, this assumes we have multiple objects of the same interface (typical composite) sharing a render() method - this throws back to arborint's suggestion:
arborint wrote:I agree. Sub-Views should not require a Controller if they are attached to a View. I think that anything with a render() method should be able to be attached to a named part of a View and just work -- that should be our goal.
So rendering any specific class of type (e.g. Zps_View_Interface) will render itself, and obviously call render() on all it's children. Typical Composite pattern really. This removes an arbitrary hierarchy (e.g. header, content, footer) and delegates them to generic classes of implementing the interface, either as composites (seems likely for some) or leafs. Of course each composite is itself a Layout into which its children are rendered.
Yes, yes, yes ... you zeroed in on the most important thing and found the patterns based solution -- excellent! Now we are going somewhere. Thanks for sorting out my ramblings. :)
Maugrim_The_Reaper wrote:The question here is what does the actual rendering, and how does it integrate Zend_View? There are two options - firstly and likely the most common, we use multiple Zend_View instances per leaf/composite. A leaf could just be the basic Zps_View subclass (which enforces the refactoring to deny the current Zend_Controller_Action/Zend_View coupling) with the composite being an additional subclass: Zps_View_Composite which is basically the additional code to handle a collection of leafs or other composites.
Possibly, but we also may want to make separate, and much more lightweight, objects to the tree nodes -- only using Zend_View where the framework forces us to.

I like you interfaces. However I think rather than the traditional composite naming we should use the more PHP/ZF naming style. I pushed early on for some consistency and Zend have used it. I also think you should be able to attach a string or a child view object to a tag and it should just sort it out.

Code: Select all

interface Zps_View_Composite_Interface
{

    public function set($tag, $view);

    public function get($tag);

    public function has($tag);

    public function hasChildren();

    public function getChildren();

}
Maugrim_The_Reaper wrote:I also haven't addressed getting the model - esp. where it comes from. If there is a re-useable widget which displays a list of News Headlines from the database, then the current controller won't be handling that data - it needs to be drawn into the View (and passed down the chain perhaps?) from another point in the application. Which leads us into whether View Helpers (not necessarily the ZF definition, but the actual pattern) should be brought to bear to allow the View read in a model without relying totally on the controllers.

In other words, Views may have a executable section to make View Helper calls which grab a model (pull, not the ZF's default push system) for the sub-View to use in rendering it's assigned template.
Yes, real View Helpers are what is needed
Maugrim_The_Reaper wrote:- When are Views pulled into the composite structure? It can be done manually - think PHP DOM approach, or through an automated means based on templates though not sure exactly how. Doing it within templates seems too much, but then one alternative (configuration) is as bad...
Let's do manual building to start and then see if we can find some way to automate the associations. Maybe some sort of "include" or Lazy Load system were instead on an actual View/Template, you attach a reference (Dynamic Link) to one.
Maugrim_The_Reaper wrote:- How should the View and Model interface? Assuming we avoid controllers, this would indicate the View needs to have read access to the Model (not controller pass through). Important to note the distinction between ZF view helpers and the View Helper Pattern. I'm starting to wish the ZF paid more attention to how it named those helper classes...
Yes, we need a parallel set of real Helpers.
Maugrim_The_Reaper wrote:- Is it viable to use what amounts to multiple Zend_View objects as the basis of leafs and composites? Is there an alternate strategy relying on namespaces in a single object worth persuing? More a thought for now - if using multiple Zend_Views is easier then that's how it should be done (refactor later if it proves an optimisation stick up).
I think we should go for the simplest and most lightweight replacement for the childeren we can come up with. Maybe only require the Zend_View at the top (if at all).
Maugrim_The_Reaper wrote:- Should Views carry a reference to the overall parent view, since that's where controllers end up assigning the current Model? I'm thinking they should have access to at least a copy or read-only version to keep all Views isolated (one not being able to influence another by altering the Model).
Maybe ... let's start simple/minimal and see what is needed.

Posted: Tue Apr 17, 2007 4:14 pm
by Maugrim_The_Reaper
Yes, yes, yes ... you zeroed in on the most important thing and found the patterns based solution -- excellent! Now we are going somewhere. Thanks for sorting out my ramblings.
I just attached a name ;). One the language was there the implementation was more obvious.
Possibly, but we also may want to make separate, and much more lightweight, objects to the tree nodes -- only using Zend_View where the framework forces us to.
We should be careful here - I know one of the goals here is to see whether the ZF classes need to be replaced, but it's cleaner to start with the available building blocks (less code to write too), assess its impact, and then refactor/replace where needed. Having multiple Zend_View instances may not be as bad as it sounds. There are also few routes which may still be able to leverage off Zend_View, even a single instance - just need the unit tests to backup what we do. Which reminds me to add a /tests directory so I can add tests...

Is everyone alright with using PHPUnit? It's the library used by the ZF so it's a bit easier to work with (if a lot less prettier than SimpleTest). I'll use the current version of PHPUnit 3.x so we do have mock object support when needed.
I like you interfaces. However I think rather than the traditional composite naming we should use the more PHP/ZF naming style. I pushed early on for some consistency and Zend have used it. I also think you should be able to attach a string or a child view object to a tag and it should just sort it out.
Point taken - I'll modify accordingly. I'll look at the objects first, then see how it melds with Strings as an option. Depends how the String is being set?

Posted: Tue Apr 17, 2007 4:53 pm
by Christopher
Maugrim_The_Reaper wrote:
Possibly, but we also may want to make separate, and much more lightweight, objects to the tree nodes -- only using Zend_View where the framework forces us to.
We should be careful here - I know one of the goals here is to see whether the ZF classes need to be replaced, but it's cleaner to start with the available building blocks (less code to write too), assess its impact, and then refactor/replace where needed. Having multiple Zend_View instances may not be as bad as it sounds. There are also few routes which may still be able to leverage off Zend_View, even a single instance - just need the unit tests to backup what we do. Which reminds me to add a /tests directory so I can add tests...
I think my idea was, let's build the render tree and give the nodes the basic capabilities that we want first. Then we can look at the classes and if they are similar to Zend_View we can have multiple extended Zend_Views (Zps_View). If they are not similar then we can hang them off of a Zend_View. But let's determine what we want and build it before we think about integration.
Maugrim_The_Reaper wrote:Is everyone alright with using PHPUnit? It's the library used by the ZF so it's a bit easier to work with (if a lot less prettier than SimpleTest). I'll use the current version of PHPUnit 3.x so we do have mock object support when needed.
As annoying as PHPUnit is, we should probably use it.
Maugrim_The_Reaper wrote:I'll look at the objects first, then see how it melds with Strings as an option. Depends how the String is being set?
Since our render nodes are a wrapper around the code that is actually doing the work I think them as a Component + Value Object + Renderer. So maybe when you call a node's render() function, internally it gives all the tag/value pairs it has to its internal renderer. If a "value" is an object with a render() function it calls it and get the string value before giving it to the renderer. Finally it calls the render function of the internal renderer and returns the resulting string. It's a render tree where each node can have an assignable renderer.

So any of the following should just work:

Code: Select all

$node->set('article_title', '<h1>Foo</h1>');
$node->set('content', new Template('homepage.html'));
$node->set('login_box', new LoginSubView($userModel));