Skip to end of metadata
Go to start of metadata

<ac:macro ac:name="note"><ac:parameter ac:name="title">Under Construction</ac:parameter><ac:rich-text-body>
<p>Please edit this page and add your ideas about how to "fix" Zend.php. Ideally, the resulting architecture would support extensibility without sacrificing the hallmark simplicity of Zend Framework.</p></ac:rich-text-body></ac:macro>

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

Zend Framework: What to do with Zend.php Component Proposal

Proposed Component Name What to do with Zend.php
Developer Notes http://framework.zend.com/wiki/display/ZFDEV/What to do with Zend.php
Proposers Zend Framework community
Revision 0.8 - 26 February 2007: Created from community discussion on fw-general and ZF-958.
0.8.1 - 28 February 2007: Trying to outline various possible solutions
0.8.2 - 6 March 2007: Add option E (wiki revision: 33)

Table of Contents

1. Overview

There has been a long discussion going on about the Zend.php file, and what should happen with it. Apparently, TIMTOWTDI!

Need to distill the following into explicit requirements .. feel free to volunteer

Splitting up Zend.php does not necessarily require creating a bunch of tiny classes.

However, consider proposals like Zend Core include path utilities - Aleksey V. Zapparov, where some developers might like to "include" some useful utility functions from their application bootstrap. Ideally, the ZF would include a mechanism and architecture to facilitate this, without just appending more and more functions to Zend.php

We'll try to put all of the suggestion in line, as it is hard to keep on overview.

Some example justifications for splitting / cleaning up Zend.php

  • Why is Zend.php called Zend.php? Cleaning up the organization via splitting also helps reduce naming confusion amongst beginners.
  • Solves the svn externals issue described in detail previously.
  • Why should I load a "debug" function with every request?
  • How can I add more debug functions for use when I do want/need it (possibly loaded on-demand, even in my production environment) in a manner consistent with existing debug functions that is "compatible" with other related functions other developers might contribute (i.e. where is the standardization to facilitate community development and enhancement of framework-level "bootstrap" type features?
  • Where is a standard mechanism for developers to add "global" functionality to their ZF app (e.g. "plugins" for Zend.php)
  • Why is the registry accessed via the oddly named functions in Zend.php? (Yes, BC, but it would be nice to switch to something cleaner.)
  • How should developers extend the functionality mixed into the current Zend.php? Need to plan for the long-term here ...

Solution A:

Move Zend.php to <zf-home>/library/Zend/Zend.php. The class name would continue to be Zend, and no methods within the class will be changed.

The only change in your application would be that you need to change this:

To this:

Alternatively, you could add the Zend directory to your include_path.

The benefits

  • Zend Framework files contained in a single directory. This simplifies integration of a Zend Framework tree into an application tree. You could use svn:externals, for instance.
  • No usage of this class would change. Thus, no API change in the 0.9 release.

The disadvantages

  • The disadvantage is that it does not follow the ZF convention that class names always match the physical location of the class file. But this is the only class that needs to be an exception to this convention.
  • Continued use of "bucket class" does not necessarily address future functionality needs

Solution B:

Rename Zend.php to Zend/Core.php or Zend/Utility.php and leave it as a general "core" or "utility" class. Of course, we could mark the original library/Zend.php as {{@deprecated}, having class Zend temporarily proxy to whatever classes we decide for delegation.

The benefits

  • Zend Framework files contained in a single directory. This simplifies integration of a Zend Framework tree into an application tree. You could use svn:externals, for instance.

The disadvantages

  • Continued use of "bucket class" does not necessarily address future functionality needs

Solution C:

Will move to a basic class like Zend/Loader.php, or a more full-fledged class like Zend/FileSystem.php, which could also include recursive directory iterators, regular expressions-based file manipulation, etc.

Will be deprecated (removed).

Will be superseded by Zend/Registry.php.

Will move to Zend/Debug.php, which could include a whole host of additional debugging information, interaction with Zend_Log for trace messages, pseudo-breakpoints, etc.

And last but not least:

Will either be handled by Zend/Environment.php or move to something like Zend/Version.php

The benefits

  • Zend Framework files contained in a single directory. This simplifies integration of a Zend Framework tree into an application tree. You could use svn:externals, for instance.
  • Modular; you don't have to load it if you don't use it
  • Consistent; no confusing exceptions or non-standard practices
  • Easily add additional functionality at a future date without bloating a core class (additional file loading or debugging methods, for example)
  • Eliminates Zend.php class altogether---class is sometimes seen as confusing for new users who think they are including the entire framework or don't understand the purpose of the class

The disadvantages

  • May break backwards compatibility for applications built before 0.9 (beta). (However, it is better to break compatibility now rather than sometime after 1.0.)
  • May need to add one or two additional require_once statements to bootstrap file

Solution D:

We still believe having all the core functionality in one file is beneficial. While we want to keep the framework as loosely coupled as possible there are some key APIs which are pretty much used universally throughout the framework. Breaking them each out into separate classes
and files would probably lead to a real performance hit and would require people to require_once() all those components over and over again (which would also be a PITA).

We therefore suggest that these key classes (previously known as Zend::) all are put in the Zend/Core.php file.

The benefits

  • Zend Framework files contained in a single directory. This simplifies integration of a Zend Framework tree into an application tree. You could use svn:externals, for instance.
  • Simplifies inclusion into applications, with four fewer require_once statements

The disadvantages

  • Multiple classes in one file; non-standard practice
  • May have to load classes that are not ever used (for example, Zend_Registry)
  • Might be premature optimization

Solution E:

Very similar to Solution C, but with minor variation on names of classes.

  • Methods for class-loading move to Zend/Loader.php.
  • Method isReadable() also moves to Zend/Loader.php because it doesn't justify having another class for this one method. If we develop a Zend/Filesystem.php class in the future, we'll move isReadable() and deprecate it in Zend/Loader.php.
  • Redesign Registry methods to store a static object in the Zend/Registry.php class. Allow developer to specify which class to use for this static instance, to allow subclassing. But of course you can also create an instance of Zend_Registry in a traditional manner, with new.
  • Registry also has static methods get() and put(), which correspond to the old Zend::registry() and Zend::register() methods. Internally, thse methods are simply $r = self::getInstance(); return $r[key]; and $r = self::getInstance(); $r[key] = value;.
  • Method and const for version moves to Zend/Version.php.
  • Method dump() moves to class Zend_Debug.
  • Rewrite Zend.php methods to proxy to new classes, and mark them deprecated in ZF 0.9.0. Remove Zend.php in the subsequent ZF 1.0.0 RC1.
  • Rewrite unit tests.
  • Rewrite manual pages.

The benefits

  • Zend Framework files contained in a single directory. This simplifies integration of a Zend Framework tree into an application tree. You could use svn:externals, for instance.
  • Modular; you don't have to load it if you don't use it.
  • Consistent; no confusing exceptions or non-standard practices
  • Easily add additional functionality at a future date without bloating a core class (additional file loading or debugging methods, for example)
  • Eliminates Zend.php class altogether---class is sometimes seen as confusing for new users who think they are including the entire framework or don't understand the purpose of the class
  • Only one class is required – Zend/Loader.php so the bootstrap will not grow.

The disadvantages

  • May break backwards compatibility for applications built before 0.9 (beta).
  • If additional functions are needed, then need to require_once additional classes.

-------- Original Message --------
Subject: Re: [fw-general] Request for feedback: moving Zend.php to Zend/Zend.php
Date: Mon, 26 Feb 2007 12:41:00 -0800
From: Gavin Vess <gavin@zend.com>
To: fw-general@lists.zend.com

I agree completely with Ralf, Simon, Matt R, and others regarding
eliminating the current Zend.php class and splitting it up to achieve
the flexibility and clarity the ZF has become famous for. In fact, I was
pushing for something similar to this in an uncommitted version
pre-0.7. Bill and I brainstormed about these kinds of changes before
0.7, but it was decided to delay consideration until a later date, in
order to get 0.7 done sooner. I've always strongly disliked the old
registry interface currently found in Zend.php. The creation of the
newer Zend_Registry class was a move towards fixing the API without
breaking BC. If we are going to clean things up in time for ZF 1.0, I
certainly vote to do so before ZF 0.9.

Basically, the idea was to have an ultra-light core for "Zend.php"
(really just a minimalistic framework loader / "bootstrap" - not an
application bootstrap), which would then include optional and
non-optional classes necessary for using the ZF. However, these
"pieces" would be grouped under a subdirectory (e.g. "bootstrap")
instead of mixed in with everything else at the top-level.

2. References

3. Component Requirements, Constraints, and Acceptance Criteria

@TODO

Most requirements take the form of "foo will do ...." or "foo will not support ...", although different words and sentence structure might be used. Adding functionality to your proposal is requirements creep (bad), unless listed below. Discuss major changes with your team first, and then open a "feature improvement" issue against this component.

4. Dependencies on Other Framework Components

  • Zend_Exception

5. Theory of Operation

The component is instantiated with a mind-link that ...

6. Milestones / Tasks

Describe some intermediate state of this component in terms of design notes, additional material added to this page, and / code. Note any significant dependencies here, such as, "Milestone #3 can not be completed until feature Foo has been added to ZF component XYZ." Milestones will be required for acceptance of future proposals. They are not hard, and many times you will only need to think of the first three below.

  • Milestone 1: design notes will be published here
  • Milestone 2: Working prototype checked into the incubator supporting use cases #1, #2, ...
  • Milestone 3: Working prototype checked into the incubator supporting use cases #3 and #4.
  • Milestone 4: Unit tests exist, work, and are checked into SVN.
  • Milestone 5: Initial documentation exists.

If a milestone is already done, begin the description with "[DONE]", like this:

  • Milestone #: [DONE] Unit tests ...

7. Class Index

  • Zend_Magic_Exception
  • Zend_Magic (factory class)
  • Zend_Magic_MindProbe
  • Zend_Magic_MindProbe_Intent
  • Zend_Magic_Action
  • Zend_Magic_CodeGen

8. Use Cases

UC-01
UC-02

9. Class Skeletons

]]></ac:plain-text-body></ac:macro>

]]></ac:plain-text-body></ac:macro>

Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Mar 02, 2007

    <p>Here's another option. </p>

    <ul class="alternate">
    <li>Each class in its own file, matching its class name, as nature intended. <ac:emoticon ac:name="smile" /></li>
    <li>Zend_Registry stores an instance of itself and gives you access.</li>
    <li>Zend_Loader contains the load functions.</li>
    <li>Zend::dump() becomes a Zend_Log writer class.</li>
    <li>Zend::VERSION and compareVersion() are the only contents of Zend_Core (for now).</li>
    </ul>

    <ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
    class Zend_Registry
    {
    public static function getInstance();
    public static function init($classname = 'Zend_Registry');
    }
    ]]></ac:plain-text-body></ac:macro>

    <ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
    class Zend_Loader
    {
    public static function loadClass($class, $dirs = null);
    public static function loadFile($filename, $dirs = null, $once = false);
    public static function isReadable($filename);
    }
    ]]></ac:plain-text-body></ac:macro>

    <ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
    class Zend_Core
    {
    public static function compareVersion($version)
    const VERSION = '0.9.0dev';
    }
    ]]></ac:plain-text-body></ac:macro>

    <ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
    class Zend_Exception

    Unknown macro: { ... }


    ]]></ac:plain-text-body></ac:macro>

    <ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
    class Zend_Log_Writer_Dumper extends Zend_Log_Writer_Abstract
    {
    }
    ]]></ac:plain-text-body></ac:macro>

    1. Mar 06, 2007

      <p>The "getInstance()" approach discards the old API for the registry (I'm not expressing an opinion about this).<br />
      Another approach lies with simply merging the registry-related functions in Zend.php into Zend_Registry.php, which would almost preserve the old API, since developers would only need to change "<code>Zend::</code>" to "<code>Zend_Registry::</code>".</p>

      1. Mar 07, 2007

        <p>I'm in favor of C/E approach, since this continues support for subclassing of Zend_Registry, and encourages and supports the well-known traditional array access mechanism offered by ArrayObject, and kills off the old/confusing <code>register()/registry()</code> setter/getter methods in Zend.php, which exist for historical reasons.</p>

        <p>Personally, I almost always just use:</p>
        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
        $registry = Zend::registry(); // becomes "Zend_Registry::getInstance" in E above
        $registry['etc'] = etc. // i.e. standard array access
        ]]></ac:plain-text-body></ac:macro>

  2. Mar 04, 2007

    <p>May I suggest you to read the proposal named 'Proposing PHK as distribution format'. Using PHK would also make it easier to solve most issues identified in this document as, among others :</p>
    <ul class="alternate">
    <li>The main source code wouldn't include Zend.php any more; ZF core features wouldn't have to be explicitely included, and the physical location of class files would become irrelevant.</li>
    <li>PHK provides features specifically intended to build a plugin system, just as we need here. A document at <a class="external-link" href="http://www.tekwire.net/joomla/products/phk/plugin shows">http://www.tekwire.net/joomla/products/phk/plugin&amp;nbsp;shows</a> how to build a plugin architecture based on PHK.</li>
    </ul>

    <p>I didn't detail what PHK would bring to each option you list here. If you read some of PHK documentation, you will quickly see that several issues detailed here just become irrelevant when considering distributing ZF as a PHK package. And most remaining issues (how to provide a way to extend ZF core features) can be solved in a rather elegant and simple way using a PHK-based plugin system.</p>

    1. Mar 04, 2007

      <p>F... editor ! The correct URL is: <a href="http://www.tekwire.net/joomla/products/phk/plugin">http://www.tekwire.net/joomla/products/phk/plugin</a></p>

      1. Mar 06, 2007

        <p>Yes, there are many possible forms of "proxying" from a Zend "core" class to a "plugin" class.<br />
        For example, the replacement for Zend.php (perhaps Zend_Core) could implement the magic method __call(), and automatically load and proxy to default "plugin" classes.</p>

    2. Mar 06, 2007

      <p>The PHK technology is interesting, but it is not something we can adopt for Zend Framework 1.0.</p>

      1. Mar 11, 2007

        <p>Can you tell me why you consider that you cannot switch ZF to PHK before version 1.0 ?</p>

        <p>I thought that, as ZF is still in beta-release state, it was better to adopt PHK now, rather than when it starts being used in production environments, with all BC considerations. PHK is considered stable now and version 1.0 will be released before the end of March.</p>

        <p>Please consider that PHK brings a global solution to the autoload issues. If we adopt it later, it will be a real BC pain.</p>

        1. Mar 11, 2007

          <p>Some of the reasons we cannot switch to PHK before version 1.0 include:</p>

          <ul class="alternate">
          <li>The proposal for using PHK as a distribution technology for Zend Framework has not been reviewed and approved.</li>
          </ul>

          <ul class="alternate">
          <li>From what I see on the PHK website, running code in a PHK archive requires runtime technology that is licensed under the Apache License. The goals of the Zend Framework require that all its required technology be licensed under the New BSD License, either as part of the core PHP distribution or else contributed to the Zend Framework project under the terms of the Contributor License Agreement. The Apache License is pretty close to the New BSD License, but it's not the same. An important goal of the Zend Framework is that it does not rely on any third-party code.</li>
          </ul>

          <ul class="alternate">
          <li>Our schedule requires us to have finished all features for 1.0 by Thursday, March 15. We are focused on finishing functionality for the ZF components. We cannot change the architecture of ZF components to work as PHK packages – including writing installation tests and documentation – by our deadline and still get our other commitments done.</li>
          </ul>

          <ul class="alternate">
          <li>I understand that a lot of work has gone into PHK so far. It seems like really cool technology and I think PHP needs this kind of solution. But nevertheless, PHK is currently an alpha product, which I consider experimental and not stable. It is not widely used yet. I'm not going to support using this technology as the default Zend Framework distribution format until we have had more time to evaluate it.</li>
          </ul>

          <p>The license of the Zend Framework permits users to create a PHK archive and distribute it. I support your efforts to do that. But that is not going to be the default distribution of Zend Framework for the 1.0 release. We can test the technology later. If the technology seems stable and the license issues are resolved, we may consider using it, at least as an optional distribution format.</p>

          1. Mar 12, 2007

            <p>OK. Thanks for your reply. I was not aware of the March 15 deadline. Of course, it is too short now and priority is to stabilize ZF features.</p>

            <p>About license terms, I am not a licensing specialist and I chose the Apache license because I didn't like all this stuff in the GPL/LGPL, but I can probably switch to the new BSD license. Or I can sign a ZF CLA for an unlimited use of PHK_Creator. I don't know exactly what to do but it must not be a problem, as ZF was one of my primary goal when I started PHK.</p>

            <p>Feel free to contact me when you think it's time to work on an (optional) PHK distribution for ZF. In the meantime, I will release PHK version 1.0, as the documentation is now complete.</p>

  3. Mar 07, 2007

    <p>Most of us are alreay using autoload. It would be nice if a new load class gets two more methods.</p>

    <ul>
    <li>One gets called by the autoload mechanism and is similar to loadClass(), but without throwing an exception if the file or class is not found. Otherwise it wouldn't be compatible with other autoload functions.</li>
    <li>An other to register the autoload method.</li>
    </ul>

    <p>The normal bootstrap would than be:</p>

    <p><?php<br />
    require_once 'Zend/Loader.php';<br />
    Zend_Loader::registerAutoload();<br />
    ?></p>

    1. Mar 07, 2007

      <p>I think this is a nice idea to support a registered autoload callback. We have a JIRA issue open for this: <a href="http://framework.zend.com/issues/browse/ZF-981">ZF-981</a></p>

      <p>I did think the autoloader function would be a natural candidate for the Zend_Loader class, but I didn't want to bring it up in this proposal. It's a separate subject from the reorganization of Zend.php.</p>

  4. Mar 08, 2007

    <ac:macro ac:name="note"><ac:parameter ac:name="title">Office Zend Comment</ac:parameter><ac:rich-text-body>
    <p>This change is approved. After due community discussion, the Solution "E" above best meets the requirements.</p>

    <p>Zend_Registry should be implemented based on the code in the class skeletons section above, with two alterations:<br />
    Zend::__unsetRegistry() should become Zend_Registry::_unsetRegistry()<br />
    Zend::isRegistered() becomes Zend_Registry::isRegistered() (this was forgotten in the class skeleton).</p>

    <p>Zend::registry() becomes Zend_Registry::get()<br />
    Zend::register() becomes Zend_Registry::set()<br />
    Zend::initRegistry() becomes Zend_Registry::setClassName()</p>

    <p>Zend::dump() becomes Zend_Debug::dump()</p>

    <p>Zend::loadClass() becomes Zend_Loader::loadClass()<br />
    Zend::loadFile() becomes Zend_Loader::loadFile()<br />
    Zend::isReadable() becomes Zend_Loader::isReadable()</p>

    <p>Zend::VERSION becomes Zend_Version::VERSION<br />
    Zend::versionCompare() becomes Zend_Version::versionCompare()</p>

    <p>Zend::loadInterface() is deprecated and will not be propagated to a new file.<br />
    Zend::exception() is deprecated and will not be propagated to a new file.</p>

    <p>Make all methods in Zend.php proxy to their new equivalents if possible.<br />
    For Zend Framework 0.9.0, all methods in Zend.php should generate an E_USER_NOTICE.<br />
    In a subsequent release, the Zend.php file will be removed.</p>

    <p>Unit tests and documentation should be updated to reflect the new classes.</p>

    <p>Optionally, keep unit tests for the old interface while the Zend.php exists with deprecated methods, just to ensure that the old interface still works, albeit with E_USER_NOTICE errors being thrown. Probably would be good to make these tests not run by default, but instead only if a config variable is set, so the default test run doesn't generate the notices.</p></ac:rich-text-body></ac:macro>

    1. Mar 08, 2007

      <p>One alteration: _unsetRegistry() can be renamed to _unsetInstance() to be consistent with the other method names. This shouldn't be any impact, because the method is used chiefly in unit tests.</p>

      <p>I also thought of changing isRegistered() to isSet(), but the latter method name seems to have special meaning in PHP.</p>

      1. Mar 09, 2007

        <p>Why is _unsetInstance preceded by an underscore? It's not a protected method, so shouldn't it just be unsetInstance()?</p>

  5. Apr 04, 2007

    <p>Hi, all; new to the thread, not to the framework.</p>

    <p>I'd like to know the reasoning behind deprecating the method Zend::loadInterface() in the new Zend_Loader implementation and removing the class constants CLASS_EXT and INTFC_EXT. Personally, I modified Zend::loadClass() and Zend::loadInterface() to properly utilize CLASS_EXT and INTFC_EXT respectively, falling back onto the default '.php' extension before throwing Zend_Exception. </p>

    <p>Since I use the '.class.php' and '.intfc.php' extensions to indicate classes and interfaces, this feature was useful to me. I've already modded Zend_Loader to perform those tasks and added Zend_Loader::loadInterface() back into the class for my use. I'd argue that these customizations should be considered for inclusion back into the framework. Considerations?</p>

    1. Apr 04, 2007

      <p>Hi David,</p>

      <p>You may not be aware that Zend_Loader::loadClass() can load interfaces as of revision 3655, which corresponds to Zend Framework 0.9.0. See <a class="external-link" href="http://framework.zend.com/issues/browse/ZF-937">http://framework.zend.com/issues/browse/ZF-937</a></p>