[PHP-DEV] Re: aggregate() und overload()
Andrei Zmievski wrote: Please expound on this. I would like to hear specific problems you see existing with __get_x() callbacks. As of now, this is just an unspecified bad feeling of mine. I only can back up this with the two times we had special names which were variable in PHP: Both attempts at them failed horribly: - We had (have, until ZE 2, if I am not mistaken) variable named constructors (ctors named after the class). These had a number of design flaws in PHP 3, which were fixed in PHP 4, at the cost of an overly complex ruleset for constructor names. Had we chosen stable names for constructors, we'd gotten the same effect with a single rule for ctor names. - We had (until very recently) variable names for imported variables amidst our global namespace. We earned a number of security problems due to admittedly stupid code, which swayed the PTBs to finally disable registering globals by default. I cannot come up with a bomb script right now, but I am reasonably sure that __get_x() will backfire at some time as well. Kristian -- PHP Development Mailing List http://www.php.net/ To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Re: aggergate vs MI
brad lafountain wrote: Unless someone could give me a real reason that aggerate is better than MI. Aggregation does at runtime what MI does at compile time. Delaying the decision to do something is usually an enable for specific applications. Examples are the signal/slot mechanism based call-models in Gnome and Qt vs. virtual function tables in C++. The decision which implementation for a method is being called is delayed to the actual point in time when a call is being made, enabling a much more flexible component model and much better reuse. The cost for doing things late is worse typechecking, errors are potentially caught only at call-time, not at compile-time (with Qt, it probably is link-time, due to the way it is implemented). The same goes with aggregation. Aggregation allows me to write a class Soaping, which implements a SOAP RPC Client and a SOAPFactory class, which manufactures objects of any class and aggregates Soaping into them: I could include_once() any unknown class, create an instance and use PHPs introspective functions to create a list of functions and instance variables in this class. By adding Soaping functionality to the class, and with the help of getters, setters and wrappers provided by overload(), I can intercept all accesses to this instance, turn them into SOAP calls to some remote instance of that object, and marshall the results back into my application. The beauty of this is, that I can do this at run-time, and that I can do this generically with any old class, using two miniscule additions to the system, aggregate() and overload(). Yet for the user this is probably transparent. Class definition is defined at design time not run time! No, it isn't. Unless you are stuck with C++. PHP is for rapid prototyping. That may turn into rabid prototyping (SCNR the pun) if you do not know how to use it, but it may also be an extremely powerful tool as I have shown. Generally speaking, it allows you to design metaclasses and metasystems, which add some general function to the language itself. Kristian -- PHP Development Mailing List http://www.php.net/ To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Re: aggergate vs MI
Stig S. Bakken wrote: Example set of classes using aggregate to customize at runtime: DB_Connection generic connection object DB_Connection_odbc layer interfacing to PHP's odbc functions DB_Connection_oracle ditto for Oracle DB_Connection_mysqlditto for MySQL DB_SQL_oracle SQL portability layer for Oracle DB_SQL_mysql ditto for MySQL If the user requests a connection to an Oracle database, the connect function returns an instance of DB_Connection that has aggregated DB_Connection_oracle and DB_SQL_oracle. But if the user requests a connection to Oracle through ODBC, the connect function returns an instance of DB_Connection that has aggregated DB_Connection_odbc. After connecting to the database, DB_Connection_odbc detects that it is used against Oracle and aggregates DB_SQL_oracle. You can do all this almost the same way you have shown using MI and a factory object. You would premix your classes to get a static (determined at compile time) mix, and have the factory return the appropriately mixed class. That's why I was using a generic RPC proxy and a Soaping mixin in my example. In my example the actual classes being mixed are not fixed, and are in fact not known until include_once() time (runtime). Aggegration allows you to mix functionality into existing classes dynamically, include_once() allows you to load code dynamically. Thus, any attempt to solve this at compiletime is doomed. Generally speaking it is about class and type. A type describes what an object can do, it's signature. The signature is a canonic serialization of all its instance variable names and function signatures. A class is where the object got these instance variables and functions from. In languages where class == type, functionality is either inherited or locally defined. But there are languages where functionality is not restricted to these sources but may be provided in other ways. Aggregation is one way to get functionality besides inheriance, and makes PHP a language where class != type, if desired. Traditionally, PHP always was class != type when it came to instance variables. $this-$b was a valid construct for any $b containing a valid variable name (and many invalid ones as well). Traditionally PHP also was limited in how it could aquire functions in objects, so it was class == type for functions of an object. Aggregate fixed that by providing the missing API. Stig's first attempt at aggregate() broke serialization and thus sessions, because serialze() assumes that is enough to note the class of an object in order to describe its type. That assumption had always been false, but there was no API to break it. For instance variables, serialize() always recorded the type, but for methods it recorded the class as a reasonable shortcut. In fact we could keep Stig's first version of aggregate(), if serialize() recorded the type of an object for its methods, too. It would have to write a log that describes how the object aquired its functionality in order to recreate that upon deserialization() (in PHPLIB terms, change $o = new Class; # aggregate($o, anotherClass); $o-slot = 17; so that the aggregate statement is recorded and generated in the session data) It is only because of the uglyness of this approach that Stig revised his implementation of aggregate() so that it does not break the (actually false) assumption of serialize() that class == type for methods. Kristian -- PHP Development Mailing List http://www.php.net/ To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] classes, instances objects in ZE2
Marcus Börger wrote: - we have private, what about final, public, protected and abstract (can we remove/hide a method from an object)? Do we in ZE2? What use it is? In my book, private is only of very limited use, because there always must be a way around it. Introducing private (in C++) immediately called for the introduction of protected and friend, with protected being a mechanism to break privacy along the lines of the inheritance hierarchy and friend being a mechanism to break privacy across inheritance hierarchies, at compile time. Since PHP does many things at run time which C++ does at compile time, there must be a mechanism to break privacy at run time, which makes it pretty pointless to have private variables in the first place. I'd rather go for a warning that is being triggered whenever I access $a-_slot, but not when I access $this-_slot (Access to private object member). I could suppress this warning by writing $a-_slot as $a-_slot instead. Providing stronger privacy would only force the addition of even more syntactic candy (such as a get_private($o, $slot) and set_private($o, $slot)). Functions to break privacy are needed in order to write Metafunctionality such as a serialization agent, or a RPC proxy like the Soaping mixin class I introduced in another mail to this list. - do we allow to reduce visability (replace protected by private as long as we don't have it): class A { public function f().. } class B extends A { protected function f()... } Same reasoning as above. Make it a warning, do not delve into BD language realms. PHP does things at run time, because we are in the rapid prototyping area and flexibility comes before compile type checking and static bindings. And anyway, class != type in PHP. Kristian -- PHP Development Mailing List http://www.php.net/ To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] aggregate() und overload()
Stig S. Bakken wrote: Well, aggregate and MI are for solving different problems, basically aggregate is for customizing objects at runtime, while MI is done at compile time. You are right, these are different. I had a longer mail on types and classes, and how type == class is not true in PHP, but for example in C++ and how aggregate() made this obvious for methods (it has always been for instance variables). But yours is the much shorter and for the purpose of this discussion relevant summary. Suggestion for new implementation: * Don't create temporary class entries, proxy all calls through PHP's object overloading. * aggregate() will create an instance of the aggregated class and store it in the aggregating object (member __aggregated_objects or something like that), and overload the aggregating object. The __aggregated_objects array is a hash of method = $object. If a method name exists in the hash, issue a warning and keep the old version. * The overloaded function handler looks up undefined methods in __aggregated_objects at runtime. * Properties will not be aggregated * Constructors, destructors and other special methods (__*) will not be aggregated. It should be possible for deserialize() to recreate objects aggregated this way. Do you see any problems with this implementation? Does serialize() and unserialize() handle references properly? I am out of PHP and have been for quite some time now, and last time I looked, it didn't. If it does, your approach should work, and looks sane (aggregation by delegation, instead of aggregation by composition, I think). Allows us to delay or even avoid MI, which I am slightly in favor of (but this is an aquired taste, due to education). I don't particularly mind removing __(set|get)_* and only have __(set|get). +0 on this one too. setters, getters and wrappers are in fact fascinating, because they allow you to - create composite aggregates (instance variables and methods) in userland, if you like to implement them yourself. __call can be used to implement __delegate, which I asked for a long time ago. - enforce $this-_* to be private, if you like to enforce private variables. - enforce class == type for instance variables or methods, if you choose it to be this way. No more spontaneous instance variable creation, if your __put implementation forbids it. In fact, setters, getters and wrappers provide a great policy-agnostic mechanism to introduce policies of the implementors choosing. Kristian -- PHP Development Mailing List http://www.php.net/ To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] aggregate() und overload()
Kristian Köhntopp wrote: In fact, setters, getters and wrappers provide a great policy-agnostic mechanism to introduce policies of the implementors choosing. A final note: Sebastian told me that in ZE 2, constructors and destructors have a fixed name like __construct() and __destruct(). If so, the following breakage cannot be reproduced in PHP with ZE 2, which is good. Example: class __get { function __get() { echo I am the constructor for __get\n; } } class Bomb extends __get { ... } overload(Bomb); $bang = new Bomb; Because Bomb does not have a constructor, the inherited constructor __get() is called. Because Bomb is overloaded, this also is a getter. This is not sane, but hopefully will not be an issue in ZE 2 based PHPs. Shouldn't overload() be enabled on all clases, just as constructors are? This will pretty much avoid the issue, I think. Kristian -- PHP Development Mailing List http://www.php.net/ To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] DB Abstraction
Lukas Smith wrote: I would disagree there. A query builder could do a lot of stuff much nicer than a DB abstraction layer could do. A query builder could make much better use of RDBMS specific features than a DB abstraction layer could. A query builder can build the query from scratch with all given information whereas a DB abstraction layer (unless it parses the actual query) is fairly limited. For example think queries that should work for relational and non relational databases for example. This is what Apple Webobjects use: http://developer.apple.com/techpubs/webobjects/Reference/Javadoc/ This is how it looks like: http://developer.apple.com/techpubs/webobjects/GettingStartedOnWindows/Movies/index.html This is what Sun puts against Apple Webobjects: http://industry.java.sun.com/solutions/products/by_product/0,2348,all-873-99,00.html They even offer a transitional tool that converts Apple EOF into Sun ROF models. I once hacked together a quick study of a ER model representation and SQL generator in the days of PHP3. It was very slow due to object creation overhead: The ER model and access layer abstration use a great number of objects, most of which are only fired once or twice on a page. Using this to model abstract access to a database was not paying off within the deployment model of PHP. I stayed with DB_MySQL in PHPLIB and later ranted about the necessity of an Application server and truly persistent objects on this list. :-) Kristian -- PHP Development Mailing List http://www.php.net/ To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] CLI max_execution_time
Edin Kadribasic wrote: That's ok. Calling function to set it should still work though. We should really get started on the IfModule .. thing for php.ini. Actually, no. A SAPI version of PHP should get configuration values the way a webserver does. It is running in the context of a webserver and should be handling things as webbish as they come. A CLI version of PHP is a kind of scripting shell at the same level as awk, perl and other scripting languages are. It should not behave webbish at all, but shelly instead. It should not output a content type by default (automatic -q option), it should read /etc/php.ini and $HOME/.php.ini. Please get this right the first time you do it. Kristian -- PHP Development Mailing List http://www.php.net/ To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] CLI max_execution_time
[EMAIL PROTECTED] wrote: ANother possibility is to take the CLI out of 4.2.0, +1 from me. We have lived without the CLI for some time now. If we introduce it, it should be done right (correct defaults, reading preferences the right way). Kristian -- PHP Development Mailing List http://www.php.net/ To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Overloading Tags with PHP functions
Sebastian Bergmann wrote: TINX (This Is Not XSP), which I put into PEAR, currently allows for tag-triggered function and method calls. Finde ich wo? In meinem PEAR scheint es nicht zu sein? Pfadname, URL? Kristian -- PHP Development Mailing List http://www.php.net/ To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] To contact the list administrators, e-mail: [EMAIL PROTECTED]
[PHP-DEV] Overloading Tags with PHP functions
After quite some experimentation with XSLT as well as several template packages, I have come to the conclusion that XSLT has several drawbacks. For one, it makes simple things like variable replacement in HTML more complicated, but makes complex things like conversion of a HTML table into a pie chart close to impossible. Also, XSLTs Xpath is a kind of database language for hierarchical data stores (DOM trees), with all the drawbacks of a nonrelational and incomplete (no join, no aggregation) query language. And as a functional language it sucks, too (http://www.kuro5hin.org/story/2002/1/15/1562/95011). Finally, I always liked the ability of the Roxen webserver to bind code to tags. So I wrote a proof of concept class Transform in PHP, with does just that: It binds opening and closing functions to XML tags. With a version of TIDY linked into PHP as a library, one could even do this stunt with improperly nested HTML. What is this? Attached you find a class Transform, which contains some very rough proof-of-concept code. This code defines an output buffer to capture the XML generated by the page. That XML must be nested properly, as no attempt on capturing any errors is being made. I then use expat to parse that XML and look for function callbacks named just like the tags that are being processed: If a function called tag_open_h1 exists, then it is being called whenever a H1 tag is being seen. Same goes for closing tags. The opening tags are fed the Transform object and the attribuites of the tag. Closing tags are fed the content of the tag. Also, closing tags have access to a variable level, the nesting level, and to an element and attribute stack, as well as the output of their opening tag. Closing tags may even generate tags which need further processing, that is, you may define b to be replaced with font and font to be replaced with em and the result of b/ will be an em/. How can this be used for templates? One could use this to define cold fusion and Roxen like tags such as gtextbla/gtext, which will replace itself with an img/ tag to an image containing the word bla. A menu will be inserted where a menu/ tag is shown and so on. Overloading html/ or body/ will define the template for a page. The following code is slow and very ad-hoc. Still, I'd like you to have a look at it and think about it - I'll gather reviews and opinions and probably turn it into C at some later time. Kristian ?php class Transform { var $level = 0; var $elstack = array(); var $atstack = array(); var $cdata = array(); var $style = array(); var $case_folding = true; function Transform($style = ) { if (is_array($style)) $this-style = $style; } function set_style($tag, $open, $close) { $this-style[$this-canon($tag)][open] = $open; $this-style[$this-canon($tag)][close] = $close; } # expat callbacks function startElement($x, $n, $a) { $this-level += 1; $this-elstack[$this-level] = $n; $this-atstack[$this-level] = $a; if (isset($this-style[$this-canon($n)][open])) { $fn = $this-style[$this-canon($n)][open]; $this-cdata[$this-level] = $fn($this, $a); } else { $this-cdata[$this-level] = $n . $this-attr2str($a) . ; } } function endElement($x, $n) { $c = $this-cdata[$this-level]; if (isset($this-style[$this-canon($n)][close])) { $fn = $this-style[$this-canon($n)][close]; $c = $fn($this, $c); # Rekursion: # Wende die xml_transformation noch einmal auf # das Resultat an, um generierte Spezialtags # ebenfalls zu ersetzen. $t = new Transform($this-style); $c = $t-handle_output($c); } else { $c .= /$n; } $this-level -= 1; # bubble transformation result upwards on stack $this-cdata[$this-level] .= $c; } function characterData($x, $data) { $this-cdata[$this-level] .= $data; } # output buffering handlers function handle_output($str) { if (strpos($str, ) === false) return $str; $this-x = xml_parser_create(); xml_parser_set_option($this-x, XML_OPTION_CASE_FOLDING, $this-case_folding); xml_set_object($this-x, $this); xml_set_element_handler($this-x, startElement, endElement); xml_set_character_data_handler($this-x, characterData); if (!xml_parse($this-x, $str, true)) { die(sprintf(XML error: %s at line %d, xml_error_string(xml_get_error_code($this-x)), xml_get_current_line_number($this-x))); } xml_parser_free($this-x); return $this-cdata[0]; } # helper functions function canon($tag) { if ($this-case_folding) return strtoupper($tag); else return $tag; } function attr2str($a) { $r = ; reset($a); while(list($k, $v) = each($a)) { $r .= $k=\$v\; } return $r; } } function tag_open_h1($t, $attrs) { return h2 . $t-attr2str($attrs) . ; }
Re: [PHP-DEV] [NEW EXTENSTION]: templates
Björn Schotte wrote: [1]: anyone has a nice English expression for the german Schlipsträger? The common english expression for Schlipsträger is suit. Kristian -- PHP Development Mailing List http://www.php.net/ To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] To contact the list administrators, e-mail: [EMAIL PROTECTED]
Re: [PHP-DEV] [NEW EXTENSTION]: templates
Daniel Lorch wrote: or the more XML-style my-opinion what follows here is solely my own opinion /my-opinion Will you please pack your private markup into a (DTD-documented!) namespace and properly declare your namespace at the top of your messages? That would then be my:opinion xmlns:my=http://yourhomepage/opinion.dtd; what follows are my follies /my:opinion Thank you, Kris :-) -- PHP Development Mailing List http://www.php.net/ To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] To contact the list administrators, e-mail: [EMAIL PROTECTED]
Re: [PHP-DEV] [NEW EXTENSTION]: templates
Maxx wrote: - unlimited number of template tags (sure, i even shouldn't be saying that) I am fairly sure that someone will come up with the wish to make the {}'s surrounding the name of the template tag configureable. You may be tempted to provide a PHP function template_set_braces() or something like that to implement this. Don't. A template shall contain all information necessary to parse it. Besides the contents for the template tags there shall be no external references. So if you must make the {}'s configureable, do so by providing them within the actual template as a property of the template. I suggest some special configuration tag which must be part of the first line of the template if it shall be present. This way it is possible to execute other peoples templates without having to change ones own code. Also, you'd most likely want to have an escape mechanism which provides you with an easy way to generate {} in your output even if the template tages are currently being frames by {}'s. Finally, do NOT implement conditionals or loops. If you give in to anything that resembles control structures, you'll end up creating a turing complete language. This will sooner or later become a PHP- within-PHP and you'll want to avoid this at all cost. Conditions and loops must always be part of the controlling PHP code, never be part of the template. If a particular application does lend itself well to this kind of structure, then this particular applicastion maybe isn't properly structured for templates to be useful. Use pure PHP then. Kristian -- Kristian Köhntopp, NetUSE AG, Dr.-Hell-Straße, D-24107 Kiel Tel: +49 431 386 435 00, Fax: +49 431 386 435 99 -- PHP Development Mailing List http://www.php.net/ To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] To contact the list administrators, e-mail: [EMAIL PROTECTED]
Re: [PHP-DEV] [NEW EXTENSTION]: templates
Maxx wrote: However, the comment about keeping template's info in the same template (i.e. delimiters, context tag names and probably something else) is a good idea. I think this should be done in the next version. Fear the installed base. Delete NOW all features you do not want to support until the end of your life. As soon as there is code using these parameters to your open call, you'll have to support them for compatibility reasons. You'll almost never get rid of them. Kristian -- Kristian Köhntopp, NetUSE AG, Dr.-Hell-Straße, D-24107 Kiel Tel: +49 431 386 435 00, Fax: +49 431 386 435 99 -- PHP Development Mailing List http://www.php.net/ To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] To contact the list administrators, e-mail: [EMAIL PROTECTED]
Re: [PHP-DEV] bug or feature?
Zeev Suraski wrote: It's good that this question was asked, but really, be prepared to the fact that 'no' can also be an answer. Then let me rephrase the question: What is the recommended way to signal error conditions from the inside of an object constructor? Kristian -- Kristian Köhntopp, NetUSE AG Dr.-Hell-Straße, D-24107 Kiel Tel: +49 431 386 435 00, Fax: +49 431 386 435 99 -- PHP Development Mailing List http://www.php.net/ To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] To contact the list administrators, e-mail: [EMAIL PROTECTED]
Re: [PHP-DEV] Constructor Inheritance
Neil Kimber wrote: Haven't tried it but try: class B extends A { function B(){ A::A(); // do your extra stuff here. } } I have recently updated the PHP manual to reflect the behaviour of PHP 4. Please read http://www.php.net/manual/en/language.oop.php for all of the details. Kristian -- Kristian Köhntopp, NetUSE AG Dr.-Hell-Straße, D-24107 Kiel Tel: +49 431 386 435 00, Fax: +49 431 386 435 99 -- PHP Development Mailing List http://www.php.net/ To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] To contact the list administrators, e-mail: [EMAIL PROTECTED]
Re: [PHP-DEV] bug or feature?
Stig Sæther Bakken wrote: I disagree with your conclusion here. If a side-effect is useful enough and people want to use it, why not document it de-bastardize it? The fact that other OO languages implement this should be a hint that it shouldn't be impossible to do in a different OO model. Also, this is not performance critical. It is usually done in errors handlers in constructors, so PHP engine implementors should be able to emulate it, even if assignments to $this are not a natural side effect in their implementation of a PHP engine. Kristian -- Kristian Köhntopp, NetUSE AG Dr.-Hell-Straße, D-24107 Kiel Tel: +49 431 386 435 00, Fax: +49 431 386 435 99 -- PHP Development Mailing List http://www.php.net/ To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] To contact the list administrators, e-mail: [EMAIL PROTECTED]
Re: [PHP-DEV] bug or feature?
Oyvind Moll wrote: Could the current behaviour be hard to keep in the future, with the $this assignment in constructor syntax? Assignments to self (to $this) are a very useful features and common in other OO languages as well. I'd vote for keeping the feature, document it as such and making it legal. Kristian -- Kristian Köhntopp, NetUSE AG Dr.-Hell-Straße, D-24107 Kiel Tel: +49 431 386 435 00, Fax: +49 431 386 435 99 -- PHP Development Mailing List http://www.php.net/ To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] To contact the list administrators, e-mail: [EMAIL PROTECTED]
Re: [PHP-DEV] Latest commit -- depreciation of call_user_method()
Rasmus Lerdorf wrote: There will be more and more extensions that are not bundled with PHP, and having a standard way to check the version of an extension is going to be required. This should also apply to the bundled extensions. Currently there is a number of self-description functions in PHP, such as the name of the current SAPI, tests for existing (loaded) extensions and similar. I'd second your request for a function or a number of functions that report properties of a loaded extension, and I'd like to see section in a manual that deals with analyzing your PHP environment from a program. So 1. how would I get a list of all currently loaded modules and their version number? 2. how would I get a list of functions names, constants and magic variables and internal objects created by this module? 3. what information can I get about the PHP core (version, SAPI, other information). Question is, would it be possible write phpinfo() as a user function? If yes, the set of self description of PHP would be fairly complete - the list of function names etc actually transcends phpino(). This could be interpreted as a shortcoming of phpinfo(): module names should be clickable in phpinfo() and lead to a page describing that module in detail. Kristian -- Kristian Köhntopp, NetUSE AG Dr.-Hell-Straße, D-24107 Kiel Tel: +49 431 386 435 00, Fax: +49 431 386 435 99 -- PHP Development Mailing List http://www.php.net/ To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] To contact the list administrators, e-mail: [EMAIL PROTECTED]