Zend Weekly Summaries Issue #364

December 21, 2007

Uncategorized

TLK: Class resolution [continued]
TLK: Exception policy [continued]
TLK: T_IMPORT vs T_USE [ad infinitum]
TLK: Interbase and PDO_FIREBIRD fixes
REQ: Extension versioning information
REQ: Autoloaded constants and functions
BUG: pack/unpack (again)
REQ: PDO::ATTR_PERSISTENT warning
CVS: ZEND_MM_COMPACT env var
PAT: FastCGI in Russian

21st October – 27th October 2007


TLK: Class resolution [continued]

Stas Malyshev had come up with a new idea. How about some syntax to tell
autoload to use a particular namespace? Something like:


namespace Test;
throw new
this::Exception();


- only with something new to replace this – would then mean
Test::Exception throughout. Would that help?

Chuck Hagenbuch didn’t think it would, since it wouldn’t mean you could just
import a class once and forget about it. It also didn’t solve the problem of
having to qualify names from the global namespace if your own namespace
included a potential clash. All in all, Chuck concluded, the current
behaviour was ‘unpredictable‘.

Stas wondered why anyone would define a local name when they intended to use
something with the same name from the global namespace. He asked Chuck to be
very specific about what he wanted, since the use of unqualified names has to
work in a consistent manner. It wasn’t possible to satisfy all possible
scenarios, given that they are contradictory.

Chuck reiterated the main points he made href="http://devzone.zend.com/article/2778#Heading9">last week, that
in his view an
unqualified name should always be relative to the namespace and that
importing global classes into the namespace should mean you don’t need to
qualify them. He went on to demonstrate what he meant about unpredictability:


<?php
// file1.php

style="color: #0000BB">namespace Test;
import Test::Exception style="color: #007700">;

throw new Exception();

?>

style="color: #0000BB"><?php
// file2.php

namespace
Test
;
throw new
style="color: #0000BB">Exception();

?>

style="color: #0000BB"><?php
// demo.php

function
__autoload($class style="color: #007700">) {
    include style="color: #DD0000">'./test_exception.php'; // defines Test::Exception
}

try {
    include 'file2.php';
} catch
(
Exception $e) {
    echo
get_class style="color: #007700">($e style="color: #007700">) . "\n";
}

try {
    include 'file1.php';
} catch
(
Exception $e) {
    echo
get_class style="color: #007700">($e style="color: #007700">) . "\n";
}

?>


demo.php would first throw an Exception, and then a
Test::Exception. Reversing the include order, on the other hand,
would make the script throw a Test::Exception twice. To Chuck,
having the include order capable of changing the way otherwise identical code
behaves constituted unpredictability. True, he could resolve the issue by
always having import Test::Exception at the head of the file,
but if he actually wanted to use the built-in Exception class
the only way to enforce it was to always refer to it as
::Exception. He had tried import Exception, which
failed due to a naming conflict; import Exception as Error,
which threw a fatal error with a bizarre and untrue message about the import
name conflicting with a defined class; and import ::Exception as
Error
, which threw a parse error because it’s not possible to import a
top-level class name in this way. The only way to write code guaranteed not to
break, regardless of the classes future developers might define or import, was
to always prefix built-in PHP class names with ::. Chuck believed
that, once he’d declared a namespace or import, he should be able to rely on
any short name he chose to refer to it; he should have complete control over
the meaning of the names within that file. The current implementation had too
many ‘ifs’ in it; ‘look inside the namespace, UNLESS there’s a built-in
class with the same short name and the namespaced version hasn’t been
autoloaded yet, or there’s an explicit import…
‘. He found it
unintuitive that short names within a namespace don’t necessarily refer to
elements within that namespace; it was also out of step with implementations
in other languages.

Stas argued that having unqualified names always relative to the namespace
would make the common case harder to implement, that being internal classes
that are used directly. Upgrading old code would mean having to go through
every namespaced file and adding explicit imports for every built-in class.
He also disagreed that there was anything unpredictable about the current
behaviour, since it had rules that would allow prediction; and he
still didn’t understand why anyone would want to define and include a
class with the same name as an existing built-in class. Did Chuck want
unqualified internal names to work, or not? Stas didn’t understand how Chuck
managed to get a name conflict message out of import Exception,
and asked for more details about this. Importing a top-level class name might
be allowed in future, if there was a need for it, but the whole thing about
other developers defining or importing classes made no sense to him.

Chuck tried again with a clean PHP
snapshot
and found that the fatal naming conflicts only occurred when
Greg Beaver’s initial patch – the one fixing multiple uses of import
Test::Exception – was applied. Without that patch, there was
merely a weird warning:


The import statement with non-compound name 'Exception' has no effect
in...

He felt that either import ::Exception should work, or
import Exception shouldn’t issue a warning. On the subject of
what other developers may or may not do, Chuck suggested that Stas envision
large teams working on large projects. He went on to recommend that the Zend
team consult the development teams behind a range of large PHP projects
regarding the difficulties or otherwise of the upgrade path.

Stas explained that the warning is there because import with a
single-term argument is, and will remain, a no-op (read: does nothing).
However, he agreed to reconsider the possibility of allowing global imports
when prefixed, assuming that anyone else had need of them. The ‘large team’
argument didn’t really hold water though; if there was a chance of a naming
conflict arising within a project, why not have the classes from different
parts of that project reside in different namespaces?

Greg, writing as PEAR President, said that he felt the ability to simply
plop a namespace declaration and a few imports‘ at the head of a file
to upgrade existing code was good. He noted that this may mean aliasing
top-level classes to another name, but couldn’t come up with a specific
example. The only use case he could think of where classes might clash would
be in an autoloading implementation, since otherwise the executor assumes
that the current namespace is intended. He wondered whether it might make
sense to have use trigger autoload where the class doesn’t
exist, and import as a non-autoloading version of the same
thing?

Short version: That’s one way of putting an end to the T_USE/T_IMPORT debate…


TLK: Exception policy [continued]

Onward with Lukas Smith’s quest for a clear policy regarding the usage of
exceptions in PECL and the PHP core. Marcus Börger suggested that
perhaps there should be written-in-stone rules about this outside the
CODING_STANDARDS file, which he interestingly referred to as
bile‘. (Maybe that was a typo?) Lukas, wondering what was so bad
about the current CS, asked how Marcus proposed to proceed. Should there be
something added to the existing file? Should there be a new CS file for PECL,
or should coding standards only apply when a PECL module became a candidate
for core inclusion? Marcus replied that all PECL modules should follow
the core rules, and if anything the CS file should be made more readily
accessible online. (Yep, it must’ve been a typo.) Lukas wrote that he’d work
on it, or else work on improving the current document; he evidently still
wasn’t sure about the ‘bile’ part.

Short version: Blame: German keyboards.


TLK: T_IMPORT vs T_USE [ad infinitum]

Stas announced that the Zend team had been unable to find a way to make
import work as both a reserved word and a class or function
name, and were now looking at use instead. If anyone could
foresee any problems with use, ‘please speak now (or forever
hold your peace :)
‘. Stas added, a little wearily, that any proposals to
replace namespace with package – or with anything
else – would be considered off-topic.

Greg asked Stas to hold off; he believed he’d found a simple solution that
would solve the problem for class names, methods and functions, but needed to
write and test the code before posting it. Marcus muttered that unless he was
missing something, this must involve there being no token for the keyword.
Stas, rather more optimistically, asked Greg to post his solution as soon as
he had it. Greg complied,
and added for Marcus’ benefit that yes, there is still a token for the keyword.

Unfortunately the patch also covered unrelated bugs and changes, which made
reviewing it far more complicated than it needed to be (grr). Greg went into
a great deal of detail about his implementation; on the internals side, much
fiddling with the lexer to force a T_STRING return wherever
possible, but only for import and namespace
following T_FUNCTION. He had also used
fully_qualified_class_name rather than
namespace_name in the parser ‘for both import syntaxes
(?); code that will currently throw a parse error (import static::oops
as ....
) would now give no warning before throwing a fatal when the
class was used – something Greg didn’t see as problematic.

Giedrius D. spoke for many when he asked if there was any reason not
to just use use? He felt that allowing keywords to be other than
keywords would bring more confusion than value. Greg pointed out that keywords
can already be used as variable names, and nobody gets too confused by
that. It wasn’t until he was swapping code with Giedrius to prove the
point that Greg realized his post had been misleading; his
import/namespace only rule applied to class names
too. Giedrius, who saw the ‘only’ part as ‘inconsistent‘, asked again
what was wrong with use. Greg explained that to him,
use would imply some kind of autoloading. Giedrius retorted that
for him, the opposite was true. The only thing they agreed over was
that code written for PHP 5.2 should continue to work under PHP 5.3.

There followed yet another exchange between various parties regarding the
implicit meaning of use vs that of import. Stefan
Walk probably said it best when he wrote that ‘the “feel” of the words is
probably influenced by your background
‘.

Short version: I thought we were done with this last week…


TLK: Interbase and PDO_FIREBIRD fixes

New guy on the block Lars Westermann had spent some time exchanging email
with Wez Furlong regarding bug fixes for both PHP’s Interbase modules. Lars
now had a bundle of patches for the PHP_5_3 branch, and noted that any or all
of these could easily go into the PHP_5_2 branch too at this stage. He would
like someone to review his patches before he committed them.

There followed a brief flooding of the internals list; initially with patched
files (Tony Dovgal put an end to that), and then with unified diffs directly
in the post, per bug (Derick Rethans and Tony, again, complained). Lars
started over for the third time with a cheerful ‘Live and learn‘ and
posted more conventional patches, along with detailed explanations of each.

There was still a lot to plough through. Lars had fixes for Interbase bugs href="http://bugs.php.net/30690">#30690 (Resource handle from
ibase_execute() becomes invalid after return), href="http://bugs.php.net/30907">#30907 (ibase_query()
causing IBserver 7 crash with NULL param as
link-id), #39056
(Interbase NUMERIC data type error), href="http://bugs.php.net/39397">#39397 (invalid statement handle in
Unknown on line 0) and #39700
(NUMERIC error when result precision are 7,8 or 12-14), with
bugs #32143 and #42284 closed as duplicates of existing Interbase reports.
For the PDO_FIREBIRD driver, there were fixes for bugs href="http://bugs.php.net/39822">#39822 (new PDO() doesn’t
work with firebird), #41522 (PDO
firebird driver returns NULL if it fails to connect), href="http://bugs.php.net/35386">#35386 (firebird: first row is
NULL) and #36128
(Interbase PDO – timestamp columns return NULL), with bug #41522
closed as a duplicate report. As part of the fix for bug #36128, there are now
three new Firebird-specific attributes to control date/timestamp formatting:
PDO::FB_ATTR_DATE_FORMAT, PDO::FB_ATTR_TIME_FORMAT
and PDO::FB_ATTR_TIMESTAMP_FORMAT. These are in line with the
existing ibase date and time formatting INI directives.

Lester Caine popped up with news of an unreported bug relating to
BLOB ids in the interbase extension, which he claimed had
been fixed in the 5.2.4 RC snapshots but not, apparently, in the PHP 5.2.4
distribution. Lars had problems tracking down any changes to the extension in
the PHP_5_2 branch, but Lester had his href="http://cvs.php.net/viewvc.cgi/php-src/ext/interbase/ibase_blobs.c?r1=1.13&r2=1.9.2.2">history intact and managed to trace the related href="http://bugs.php.net/bug.php?id=41429">bug href="http://bugs.php.net/bug.php?id=41345">reports. He added, with the
insouciance of a man who knows he will now be heard, that these reports were
not bogus.

Short version: That Lars doesn’t mess about, does he?


REQ: Extension versioning information

PHP user Gaetano Giunta had come across a bug in ext/oci8. It had been
fixed already; that wasn’t the problem. The problem was that the PECL
extension fix had been in PECL 1.0, and the bundled PHP extension fix in PHP
5.1.6. There was nothing to connect the two, and no way to code around the
bug except to test for its presence or to grep for an extension-specific
version string.

This wasn’t the first time Gaetano had come across such a situation. It
was, however, the first time he’d realized that
phpversion() can usefully be passed the name of an extension.
Sometimes, anyway. Its usefulness depended on whether the extension
maintainer had fed a meaningful version string into the
zend_module_entry struct, rather than the catch-all
NO_VERSION_YET. Gaetano wondered how much it could possibly take
to enforce a rule that all extensions must provide a version string…
starting NOW‘.

Short version: Another one for the CODING_STANDARDS bile, perhaps?


REQ: Autoloaded constants and functions

Chuck doesn’t give up that easily. He opened a new thread about autoloading
namespaced constants and functions, based loosely on Greg’s earlier
suggestion that import or use statements might
trigger __autoload(). While he’d initially seen this as a bad
idea, it had the benefit of allowing __autoload() to handle
namespaced function libraries and constants – so long as they were imported.
What would be needed for this to work would be having
__autoload() trigger whenever a fully qualified name is used,
regardless of whether that name represents a function, class or constant:


$stuff =
My::Namespace style="color: #007700">::
do_stuff();


Here, do_stuff() would be a function in the namespace
My::Namespace, rather than a method of the
Namespace class in the My namespace. At present,
wrote Chuck, __autoload() would be triggered in this situation
but fail because My::Namespace isn’t a class. The same would be
true when accessing namespace constants. Would it be possible, following a
failed __autoload() call, to check whether it has become
possible to resolve the name to something other than a class?

What Chuck hoped for was the ability to leave the decision about how his
library code should be included to the top-level application. Perhaps the
application developer might use an autoloader during development but explicit
includes in production, for example. He liked that idea, and the advent of
namespace support almost made it workable; the only thing preventing it was
that namespaced functions and constants couldn’t be fully utilized.

Stas squashed the proposal fairly comprehensively. For a start,
import is a compile-time name transformation; the class or
namespace doesn’t actually have to exist. Secondly, an
__autoload() that would trigger on any fully qualified name,
regardless of the target, wouldn’t be __autoload() as we know
it. It would have entirely different functionality, and Stas wasn’t convinced
that many people would need it. The killer was the
My::Namespace::do_stuff() example; how, wondered Stas, was the
Zend Engine supposed to know whether Chuck intended that to mean a function
in a namespace or a method in a namespaced class? As for utilizing functions
and constants, there had been no change in policy; you couldn’t autoload them
before, and you couldn’t now; on the other hand, you could utilize them
before, and you could now too.

Short version: Don’t think about it, it’ll make your head spin.


BUG: pack/unpack (again)

Brian Moon put in a last-minute plea for href="http://bugs.php.net/bug.php?id=38770">bug #38770 (pack/unpack is broken
on 64-bit) to be fixed before the PHP 5.2.5 release. He’d taken the trouble to
diagnose the problem, and believed he’d tracked down a commit from last April
that caused unpack() to break on his 64-bit Gentoo Linux box. He
thought reverting href="http://cvs.php.net/viewvc.cgi/php-src/ext/standard/pack.c?r1=1.57.2.5.2.3&r2=1.57.2.5.2.4">this
change should fix the issue; as things stood, his LONG_MAX
appeared to be shrinking. Under PHP 5.2.0 on the same machine,


href="/manual/function.var-dump.html">var_dump( href="/manual/function.unpack.html">unpack("N", href="/manual/function.pack.html">pack("N", 2147483648 style="color: #007700">)));


gave him:


array(1) {
    [1]=>
    int(2147483648)
}

but the same line under PHP 5.2.5 RC1 returned:

array(1) {
    [1]=>
    int(-2147483648)
}

Short version: Hopefully this isn’t a bug, or href="http://devzone.zend.com/article/2692#Heading8">Greg may have to shoot someone.


REQ: PDO::ATTR_PERSISTENT warning

Ben Ramsey dropped by with
a patch to raise an
informative warning on


$pdo->setAttribute style="color: #007700">(
PDO style="color: #007700">::ATTR_PERSISTENT, style="color: #0000BB">true);


Therein lay a tale. His team had been href="http://www.deshong.net/?p=61">scratching their collective head
wondering why the PDO_OCI driver wouldn’t create persistent connections. It
had taken a while to realize that $pdo->setAttribute() is of
necessity called after object instantiation, when the non-persistent
connection is already well and truly in place.
ATTR_PERSISTENT=>true needs to be passed to the PDO constructor
itself, as part of the options array.

By posting his patch, Ben hoped to save others the same confusion.

Andi Gutmans glanced at the patch, and wondered mildly why Ben had chosen to
use a switch statement for a single case. Ben cited the
likelihood of expansion, which prompted Lukas to head into his href="http://news.php.net/php.internals/32985">Greek chorus role
over ‘the entire attribute stuff in PDO‘ and hint – a little
over-dramatically – at a need for PDO2.

Short version: PDO attributes need a bit of love.


CVS: ZEND_MM_COMPACT env var

Changes in CVS that you should probably be aware of include:

  • In ext/mssql, bug #42943
    (Move *timeout initialization from RINIT to connect
    time) was fixed in PHP_5_2, PHP_5_3 and CVS HEAD [Ilia Alshanetsky]
  • Zend Engine bug #35163
    (Array elements can lose references) was fixed, along with several variations
    of the same bug [Dmitry Stogov]
  • In ext/sybase_ct, bug
    #43074
    (attempt to increment refcount outside of the macro)
    was fixed in the PHP_5_3 branch only [Ilia]
  • In ext/xmlwriter, bug
    #43099
    (XMLWriter::endElement() does not check # of params)
    was fixed in PHP_5_2, PHP_5_3 and CVS HEAD [Ilia]
  • The ability to control memory consumption between requests using
    the environmental variable ZEND_MM_COMPACT was added in 5_2, 5_3
    and HEAD [Dmitry]

In other CVS news, Dmitry added the -T <count> switch to the CGI
SAPI in 5_3 and HEAD. This new switch is intended to measure the execution
time of a script over count runs. Jani Taskinen looked through
the code, and promptly wrote to make Dmitry aware that he couldn’t rely on
gettimeofday() being available on the underlying system. Stas
briefly wondered which systems, before starting on a plan for a workaround.
Dmitry thanked Jani for catching the bad assumption, and promised a fix
tomorrow‘.

It was also Jani who noticed the compact() memory management
handler going into CVS a few weeks ago and href="http://devzone.zend.com/article/2740#Heading9">demanded an
explanation. With the aid of setenv() and the new
environmental variable, it seems his ‘something to use in scripts‘ has
now arrived.

Short version: Good thing someone was awake.


PAT: FastCGI in Russian

A Yusuf Goolamabbas (sp?) tried to interest the Russian-speaking members of
the core development team in a published
patch
to ‘greatly improve FastCGI SAPI usage in production‘. It had
originally been posted on the nginx project href="http://news.gmane.org/gmane.comp.web.nginx.russian">mailing list,
nginx apparently being a high-performance webserver/reverse proxy.

We’re nothing if not well equipped with Russians @php.net. Tony and Stas both
went to read the documentation provided, and came back with the response that
GPL’d code couldn’t be included in PHP. It seems that Tony had already
attempted to persuade the author to change his licensing, but without
success. Stas wasn’t sure why any patching was necessary in the first place;
as far as he could tell, the code amounted to a FastCGI controller for PHP.
Tony admitted that he hadn’t looked too deeply into the code; he hadn’t
imagined there could be a way to add a process manager without patching the
SAPI. Then again, he’d noticed that the code included patches for
libevent, and he didn’t think it would be a good idea to bundle
that even if the author was interested – which seemed not to be the case.

And finally, Dmitry committed a fix to make move_uploaded_file()
always set the permissions on the resulting file in line with
UMASK. The patch was contributed by one Andrew Sitnikov.

Short version: Nyet.

2 Responses to “Zend Weekly Summaries Issue #364”

  1. _____anonymous_____ Says:

    Love the summaries, makes it easy to keep plugged in to wahts going on. :-)

  2. justinwoods Says:

    Thanks Steph for your hard work on these summaries!