Re: Namespace issues

From: Date: Fri, 17 May 2002 19:46:01 +0000
Subject: Re: Namespace issues
References: 1  Groups: php.pear.dev 
Request: Send a blank email to pear-dev+get-6207@lists.php.net to get a copy of this message
Kristian Koehntopp wrote:
At the moment, I am testing XML/Transformer.php by implementing a few
Yes, pleaaaseeee!
1. Image namespace issues/URL namespace issues The foldlist requires the use of two URLs for images, the folded and unfolded arrows, denoted [+] and [-] in my ASCII representation. At the moment, I store them as /internal-pear/foldlist/folded.gif and /internal-pear/foldlist/unfolded.gif. That is, as a PEAR global rule, "For the admin/application developer:
    PEAR reserves the right to use the /internal-pear branch in
    your webservers URL namespace tree. Your application must
    not use URLs starting with /internal-pear for its own
    purposes.
    For PEAR developers:
    Any PEAR class that needs URLs may use names below the
    /internal-pear/<classname>/ branch in a webservers URL
    namespace tree."
    What are your opinions on this?
Acceptable, no better suggestion on this. One might change the description slightly to "/internal-pear/<package>/<classname>" but I guess, that's what the original text means already. I'd like to see this parameter configurable by experienced users even in a way that breaks the official suggestions. Why? To keep URL's and by this the generated HTML as compact as possible.
2. GET/POST/COOKIE (GPC) namespace issues
See above and see below.
3. Session storage and session use The foldlist needs to store state, and I want to use sessions to do so. I do not want to interfere with session management of the application, and I want to thread lightly on the need to include class code on every page, which would be necessary when an object becomes part of the session. What is the current way of the PHP session handler regarding the storage of objects in a session? That is, a) what happens when an object is part of the session and
      the class include for that object has not been loaded
      on all pages? Does the object keep its class and methods
      on the following pages?
b) when does the class of an object has to be included for
      such objects are part of the session, i.e. what happens
      when a class include is being loaded after the session_start()
      call? When does a class have to be included when the
      session is auto started in php.ini? Does one have to
      include the class code in auto_prepend_file in such
      cases?
      On a PEAR global scale:
      When a PEAR class needs sessions, what kind of code is
required to check that sessions are not already started, and if not, to start the session? Should PEAR classes start sessions themselves or should the session management configuration be left to the PEAR class user (administrator/developer) and only be noted as a requirement? Should PEAR classes store their objects as part of the session or should they store a classless hash as part of the session and use that hash instead of their object-internal data, in order to keep the size of the session small and in order to save code includes which must be part of each and every page? What is, in your opinion, the correct way to handle this? 4. Namespace in Sessions and in GLOBALS How do we handle namespace issues in sessions? When a PEAR class wants to use variables that have to become of the session, or of the global namespace, what names do we reserve here? Again, I propose internal_pear_<classname> for use by PEAR. What are your opinions on this?
Allow me a private note before I comment on the questions: Kristian and I no longer work for the same company, but I was faced very similar questions during the last months. When I started my freelancing work for aspera.ac on the world's first webbased, industrial strength productlicence management tool (hey, they need customers to pay me... ;)), I did not fully understand why the project leader implemented "persistent page values". Yesterday, almost a month later I copied the concept for my current work. If your're still reading, you're patient enough to read the following. Variables in general have a scope and a lifetime. When I speak about scope issues I referr not only to local (function, class, ...) and global variables but also to "page" and application variables. "Page" variables are bound to an URL, application variables are independent from sessions and pages. The lifetime of a variable is eigther bound to a request or a session. Beside this one might consider variables bound to a user of the application. Having this in mind we get a matrix like this:
             request    session    endless
page         PHP var      n.a.      n.a.
application   n.a.     PHP sess     n.a.
Why should one need one of the none available (n.a.) variables? Guess we have two pages "/admin/edit_logins.php" and "/admin/edit_synonyms.php". Both of them are invoked using a GET-parameter view_row_id which referr to a view (HTML table) on login and synonyms data. When "/admin/edit_logins.php" get called programmer Joe registers a session variable "view_row_id" and presents a form to edit the data of the view. Programmer Dolittle does the same on "edit_synonyms.php". Both of them code something like: $view_row_id = NULL; if (!session_is_registered('view_row_id')) { if (isset($_GET['view_row_id']))
    $view_row_id = $_SESSION['view_row_id'] = $_GET['view_row_id'];
else
    redirectIllegalPageCall();
} else { $view_row_id = $_SESSION['view_row_id']; } On the first view this looks like pretty good code. The HTML form on both pages may use GET-parameters without inteferring the link of the page to a row in the login/synonyms data view. And: the page can't be initally called without a GET-parameter 'view_row_id'. If it's called without a parameter redirectIllegalPageCall() will stop the user from getting the application into an undefined state. But what if the user calls "/admin/edit_logins.php" and switches to "/admin/edit_synonyms.php"? Well, he "hacked" the application. How comes? "/admin/edit_logins.php" and "/admin/edit_synonyms.php" both register a session variable "view_row_id" hoping that no one else will uses this name. Now, exchange the term "page" with "package" or "application" and we're back on PEAR. To prevent the name kludge I've introduced page-variables to my application. I used some, very simple function to implement them, here's a sketch that demonstrates the idea: function initPageVariables($page) { if (session_is_registered('__pv')) {
     $_SESSION['__pv'] = array(
                             'last_page' => $page,
                             'pages'     => array( $page => array() );
} if (!isset($_SESSION['__pv'][$page])) {
     $_SESSION['__pv']['last_page'] = $page;
     $_SESSION['__pv']['pages'] = array();
} } function &getPageVariables() { initPageVariables($_SERVER['PHP_SELF']); return $SESSION['__pv']['pages'][$_SERVER['PHP_SELF']]; } $sess =& getPageVariables(); $sess['view_row_id'] = 'my one - baaah!'; Let's beautify the code and translate it into the PEAR context. A PEAR-application does: $sess =& PearInternalSessions::get('<mypackage>.<myclass>'); This suggestions gives an answer to the namespace problem by the cost of several internal hash table lookups and some additional function calls. By the way: the GPC issue might be solved in a similar way. The "incomplete class" problem is still unsolved. To be honest I doubt that there is an elegant solution to this but waiting for more application servers like SRM, but Zeev does not see the need; Zeev stop coding C, try PHP instead ;). One hack might be to register required includes using a PearInternalSessions object and pointing the end user to the fact that he must use PearInternalSession::Start() to call session_start(). PearInternalSession::Start() is able to read out the php.ini and expand the unserialize_callback_func setting to call __pear_internal_session_inc() which reads the list of required files from a file. Those who think of implementing a PEAR session class migth consider to implement all kind of session variables shown in the matrix above. It's pretty cool to have persistent variables which are eigther bound to a page, a group of pages, a session or the application (which is a group of sessions). This sounds complicated to you? No, it's not(yet). Imagine we'd have PHP-Entity-Objects, PHP-Form-Objects, PHP-Visualizer-Objects, PHP-XML-Schema-Parser-Objects, PHP-XML-Schema-Validator-Objects and finally PHP-SuperSession-Objects to build a bunch of administration webpages. Administration pages that all have a very similar workflows: read data, dump it into a HTML table which offers links for editing, show the editing form, validate the input, write it back. Now, the PHP-Entity-Objects read the entire data from an arbitrary data-source. The PHP-Visualizer-Object presents the data using a HTML table which offers search, page-flipping and editing links. The edit links throws an event which makes the PHP-Form-Object present the data for editing. The user hits save which causes the PHP-XML-Schema-Validatior-Object to validate the input according to the informations it recieves from the PHP-Entity-Object. If everything is fine you're using the PHP-Entity-Object to save the data. Hmm, pretty complicated way to create some HTML? Yes, in doubt but it saves you lots of time during development. Bear in mind I'm dreaming and I'm talking of administration (low traffic) pages. It would not even be that slow if there'd be no need to rebuild a dozen of objects on every request. As I like the vision very much I'm pointing my applications step by step into this direction. Doing so, I came to a point when put a very large "PHP-Visualizer-Objects" into my session. This made my cry and pray for an application server. As there was no such one I started with a sketch of the PHP-SuperSession-Object:
            request    session    endless
page         PHP var      n.a.      n.a.
application   n.a.     PHP sess     n.a.
It helps me to share "PHP-Visualizer-Objects" beetween pages and garbage collect them whenever the user leaves the group of pages that can legally access the PHP-Visualizer-Object. I also needed some protection against name clashes. The heavy use of cut&paste when writing edit_xy, create_xy and present_xy pages makes clashes very likely. Nonetheless I don't wanna miss this way of coding. So if PEAR could benefit from "page variables" (class of a package) and "page-group variables" (package) why not using the idea shown in my code sketch? Ulf

« previous php.pear.dev (#6207) next »