Skip to end of metadata
Go to start of metadata

<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: Zend_Uri Improvements Component Proposal

Proposed Component Name Zend_Uri Improvements
Developer Notes http://framework.zend.com/wiki/display/ZFDEV/Zend_Uri Improvements
Proposers shahar.e@zend.com
Revision 0.1 - 13 October 2007: Initial Proposal (wiki revision: 16)

Table of Contents

1. Overview

Zend_Uri is a component designed to represent and ease up the use of Uniform Resource Identifiers (URIs) of various schemes. It's current implementation (it is one of the least-modified and earliest components of ZF) is somewhat lacking - providing very little benefit besides validation (which might already be provided as part of Zend_Validate) and parsing, which can be done using native PHP functions such as parse_url(). Additionally, it does not support the representation of abstract (non scheme specific) or partial URIs.

The aim of this proposal is to describe a set of changes to Zend_Uri that will improve the ability to represent abstract URIs and new scheme-specific URIs, as well as add some required functionality, without minimal API changes, while maintaining as much backwards compatibility as possible.

2. References

3. Component Requirements, Constraints, and Acceptance Criteria

  • This component will allow the programmatic construction of URIs from scratch, as well as construction by string parsing
  • This component will allow reading and modifying each part of the URI, except for the scheme in scheme-specific subclasses
  • This component will provide part or URI validation where applicable, relying on Zend_Validate where possible
  • This component will allow the retrieval of the full URI as a string
  • This component will allow the representation of abstract generic URIs
  • This component will be fully extensible to allow specific URI schemes
    • The following scheme-specific URI classes will be implemented as part of the component:
      • Zend_Uri_Http - HTTP / HTTPS scheme
      • Zend_Uri_Mailto - Mailto scheme
      • Zend_Uri_File - File scheme (optional)
    • This component will allow the easy use of user-defined classes for other URI schemes
  • This component will allow the representation of partial or relative URIs
  • This component will provide a method to use an absolute URL as the base URL for a relative or partial URI, translating it into an absolute full URL.
  • This component will allow automatic instantiation of different URI subclasses through a factory pattern.
  • This component will aim to be as lightweight as possible, not adding more logic than required by this proposal, following the assumption that Zend_Uri will mostly be used as an underlying helper class
  • This component will not provide part-specific validation functions (as the old implementation did) as those seem redundant and are probably rarely used directly by the end-user.
  • The changes to this component will try to break backwards compatibility with the old implementation only when necessary

4. Dependencies on Other Framework Components

  • Zend_Loader
  • Zend_Validate
  • Zend_Exception

5. Theory of Operation

Instantiation and manipulation

When parsing string representation of URIs into Zend_Uri objects, one will usually either instatiate a specific Zend_Uri_Xxx() object, passing the string to the constructor, or use the generic Zend_Uri::factory() method, which will decide which specific class to instantiate. If no specific class exists for this URI, or the scheme is unknown, the generic Zend_Uri class will be used to represent the scheme. In any case all parsing will be based on the internal parse_url() function, which seem to be good enough for all the current needs.

One could also instantiate an empty Uri object and construct a URI programmatically, either by manually setting each one of the parts or by passing an array (similar in structure to the return value of parse_url()) to the constructor of the class.

When manually constructing, classes should validate that the parts are well formed. Additionally, when stringifying a URI object, required parts must exist (for example if the scheme is 'http' but there is no host, an exception should be thrown).

The generic factory method will try to match the scheme (if available) to one of it's subclasses. A static method must be provided to allow the user to define additional classes for specific schemes - these classes must extend Zend_Uri. Once a class is matched to the scheme, a new object of this class will be returned. If no class is matched, or if the URI has no scheme (as is the case in relative URIs) an instance of Zend_Uri will be returned.

Subclassing

The basic Zend_Uri will no longer be abstract (as it is now) but will be a real class, with minimal URI representation (scheme, user, host, port) and manipulation capabilities for generic purpose. In order to provide scheme-specific functionality, this class will be extended by several subclasses - for example Zend_Uri_Http will allow HTTP specific functionality such as manipulation of the HTTP query string or fragment representation.

In addition to the provided subclasses, the user will also be able to extend Zend_Uri in order to represent other specific schemes, and will be able to register his specific classes in Zend_Uri so that they could be used by it's factory pattern.

Merging and Reference Resolution

One of the biggest additions to be added on top of the old implementation will be the ability to merge two partial URIs or an absolute and relivate ones into a single new URI, using one URI as the base URI for the second one. This will be done in accordance to the 5. Reference Resolution chapter in the URI RFC. Currently, two methods are proposed to handle this functionality:

  1. Passing a base URI object to the URI constructor in addition to the new URI string (or array), allowing the constructor to use this base URI if needed when creating the new URI.
  2. Through a static merge() method which will clone and return a new URI object merged from two passed URI objects.

6. Milestones / Tasks

  • Milestone 1: design notes will be published here
  • Milestone 2: Working prototype passing all unit tests of previous versions checked into the incubator
  • Milestone 3: Additional unit tests added for new functionality
  • Milestone 4: New functionality (merging, subclassing) committed to repository
  • Milestone 5: Initial documentation exists.

7. Class Index

  • Zend_Uri
  • Zend_Uri_Http
  • Zend_Uri_Mailto
  • Zend_Uri_File
  • Zend_Uri_Exception

8. Use Cases

UC-1: Instantiating
UC-2: Setting and getting URI parts
UC-3: Part validation
UC-4: Merging URIs using a base URL
UC-5: Merging URIs using the static merge method
UC-6: Support for abstract and user defined URI schemes

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. Dec 16, 2007

    <p>Shahar- do you think this is ready for core team review at this point? If I'm not mistaken it's been available for community review for a couple of weeks now- sometimes the community just doesn't have much to say about a proposal. <ac:emoticon ac:name="smile" /> If the intention is to get this in to 1.5, we'll need to approve it soon.</p>

    1. Dec 16, 2007

      <p>The proposal has been up for quite a while (Since ZendCon AFAIK). As far as I am concerned it is ready for core team review. If you review it soon, I might be able to write it in a few days and make it ready for 1.5 - perhaps <ac:emoticon ac:name="wink" /></p>

      1. Dec 19, 2007

        fc

        <p>A few days, that's the spirit <ac:emoticon ac:name="smile" /> Sounds like you are going need some help, a project manager to whip you while you code maybe?</p>

  2. Jan 11, 2008

    <p>Some first impressions:</p>

    <p>Document the impact of these changes to existing ZF components, and how they will be handled. The changes should not break existing components or their unit tests for the upcoming 1.5 release.</p>

    <p>Any backward compatibility breaks should be documented in a "migration guide" (or similarly named) section of the documentation for this component. What backward compatibility issues are known at this time?</p>

    <p>In UC-05, "This is different from passing a BaseURL to the constructor, which simply silently fails". The meaning of this is unclear to me. Could this be illustrated a bit more or differently, (e.g., using code)?</p>

    <p>In UC-06, "<code>Zend_Uri::addSchemeClass('myscheme', 'Myproj_Uri_Myscheme');</code>" implies that either:</p>
    <ul>
    <li>Zend_Uri knows where to pick up this class (e.g., using <code>include_path</code>?) and loads it automatically, or</li>
    <li>that the class is already loaded,</li>
    </ul>

    <p>but how this works is unclear.</p>

    <p>Naming conventions include that protected member names begin with an underscore character.</p>

    <p>Other than these minor issues, this proposal has what look to me like some great improvements. Thanks, Shahar! <ac:emoticon ac:name="smile" /></p>

  3. Jan 11, 2008

    <ac:macro ac:name="note"><ac:parameter ac:name="title">Zend Comments</ac:parameter><ac:rich-text-body>
    <p>This proposal is approved for development in the incubator. Upon completion, including implementation, coding standards compliance, passing unit tests with LOC coverage of >=80%, documentation updates (as needed to document the new API), and the items below, the work can be merged to core (i.e., <code>/trunk</code>):</p>

    <ul>
    <li>ZF components using Zend_Uri must be updated as needed to comply with the new API.</li>
    <li>Backward compatibility issues for developers should be deprecated (with {{@deprecated} phpdoc tag} where possible, or clear migrations path must be documented where deprecation is not reasonably possible.</li>
    <li>Consider use of the plugin loader for adding ability to load scheme-specific classes with short names without requiring <code>include_path</code> pollution (see <ac:link><ri:user ri:username="matthew" /></ac:link> for details).</li>
    </ul>
    </ac:rich-text-body></ac:macro>

  4. Apr 15, 2008

    <p>Hello Shahar</p>

    <p>A Zend_Uri component was just I was looking for. Thanks for developing it.<br />
    I hope that this will be a very important one in future releases, here is why (unfortunately these are further improvements):</p>

    <p>There is already a lot of important url handling going on where I would like to have Zend_Uri suporting me:</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    $this->headLink()->appendStylesheet('/styles/basic.css');

    $this->headScript()->appendFile('/js/prototype.js')
    ]]></ac:plain-text-body></ac:macro>
    <p>lets first look al the ezComponent URL component on: <a href="http://ezcomponents.org/docs/tutorials/Url">http://ezcomponents.org/docs/tutorials/Url</a><br />
    There have something wonderfull, appending a suffix to a url:</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    // register an url under the alias 'map'

    ezcUrlCreator::registerUrl( 'map', '/images/geo?xsize=450&ysize=450&zoom=4' );// display the the url prepended to map_sweden.gif
    var_dump( ezcUrlCreator::prependUrl( 'map', 'map_sweden.gif' ) );

    // display the stored url under the alias 'map'
    var_dump( ezcUrlCreator::getUrl( 'map' ) );

    //outputs:
    "/images/geo/map_norway.gif?xsize=450&ysize=450&zoom=4"
    "/images/geo/map_sweden.gif?xsize=450&ysize=450&zoom=4"
    "/images/geo?xsize=450&ysize=450&zoom=4"
    ]]></ac:plain-text-body></ac:macro>
    <p>Now think about what a solution like this could mean to the flexibility of Zend Framework.<br />
    Example for using the yahoo user interface library (yui):</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    ezcUrlCreator::registerUrl( 'yui', 'http://yui.yahooapis.com/2.5.1/build/?' );
    $this->headLink()->appendStylesheet('reset-fonts-grids/reset-fonts-grids.css ', 'yui');
    ]]></ac:plain-text-body></ac:macro>
    <p>This would link to a css on: <a href="http://yui.yahooapis.com/2.5.1/build/reset-fonts-grids/reset-fonts-grids.css">http://yui.yahooapis.com/2.5.1/build/reset-fonts-grids/reset-fonts-grids.css</a></p>

    <p>a possible img helper could look like this:</p>

    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    ezcUrlCreator::registerUrl( 'icons', 'img.myserver.com/icons/?' );
    echo $this->img('silk/edit.png', 'icons' );
    ]]></ac:plain-text-body></ac:macro>
    <p>For me this would increase the frameworks power even more. It's now possible to run all css, scripts, images from a local installation with changing just one line, instead of going through all view scripts. Or being able to go to the next version just by changing the version number in one place.</p>

    <p>So I think you can see now why I would like a to see a powerful Zend_Uri component used by all view helpers handling urls.</p>

    <p>Regards<br />
    Daniel</p>

  5. May 25, 2008

    <p>Note that Zend_OpenId has an absoluteUrl method (and several other URL manipulation methods I believe), so that component might do with some updates when this component is ready, and this component could probably borrow some from Zend_OpenId <ac:emoticon ac:name="wink" /></p>

  6. Dec 18, 2008

    <p>How about changing the Zend_Uri_Mailto interface to this (in accordance to Zend_Uri_Http interface)</p>

    <ac:macro ac:name="code"><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
    $mailto = new Zend_Uri::factory( 'mailto' );

    // set host of mailto uri
    $mailto->setHost( 'example.com' );

    // a map of username => realname
    $usernames = array(
    'foo.bar' => 'Foo Bar',
    'bar.baz' => 'Bar Baz',
    'baz.foo' => 'Baz Foo'
    );

    foreach( $usernames as $username => $realname )
    {
    // set username of mailto uri
    $mailto->setUsername( $username );

    $mailto->setQuery(array(
    'subject' => $realname . ': You rock!'
    ));

    echo '<a href="' . $mailto . '">' . $realname . '</a>';
    }

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

  7. Mar 18, 2009

    <p>Shahar, any chance you will move this forward for 1.8? If not, it's better to archive it.</p>

  8. Dec 11, 2009

    <p>Shahar, any updates on this?</p>

    <p>I'd be interested in helping out. I'm also in the early stages of developing a S3 URI class (<a class="external-link" href="http://gist.github.com/254572">http://gist.github.com/254572</a>). This could use the updates you've proposed here.</p>