mirror of
https://github.com/php/web-php.git
synced 2026-03-23 23:02:13 +01:00
Remove ZEND_CHANGES and redirect all
requests for that to zend-engine-2.php which is a more up to date (and more visual) version of the changes. Also unify BC comments in error/index.php
This commit is contained in:
518
ZEND_CHANGES.txt
518
ZEND_CHANGES.txt
@@ -1,518 +0,0 @@
|
||||
Changes in the Zend Engine 2.0
|
||||
|
||||
* New Object Model.
|
||||
|
||||
The Zend Engine's handling of objects has been completely
|
||||
changed in order to allow for new features, but also to increase
|
||||
its performance.
|
||||
|
||||
Objects were handled in previous versions like primitive types
|
||||
(for instance integers and strings). The drawback of this method
|
||||
is, that semantically the whole object was copied when a
|
||||
variable was assigned or parameters were passed to a method. The
|
||||
new approach refers to objects by handle and not by value (one
|
||||
can think of a handle as an object's ID).
|
||||
|
||||
Many PHP programmers aren't even aware of the copying quirks of
|
||||
the old object model and, therefore, there is a relatively good
|
||||
chance that the amount of PHP applications that will work out of
|
||||
the box or after a very small amount of modifications would be
|
||||
high.
|
||||
|
||||
* Private Members.
|
||||
|
||||
The Zend Engine 2.0 introduces private member variables. Note
|
||||
that for performance reasons no error message is emitted in
|
||||
case of an illegal access to a private member variable.
|
||||
|
||||
Example:
|
||||
|
||||
<?php
|
||||
class MyClass {
|
||||
private $Hello = "Hello, World!\n";
|
||||
|
||||
function printHello() {
|
||||
print $this->Hello;
|
||||
}
|
||||
}
|
||||
|
||||
class MyClass2 extends MyClass {
|
||||
function printHello() {
|
||||
MyClass::printHello(); /* Should print */
|
||||
print $this->Hello; /* Shouldn't print out anything */
|
||||
}
|
||||
}
|
||||
|
||||
$obj = new MyClass();
|
||||
print $obj->Hello; /* Shouldn't print out anything */
|
||||
$obj->printHello(); /* Should print */
|
||||
|
||||
$obj = new MyClass2();
|
||||
print $obj->Hello; /* Shouldn't print out anything */
|
||||
$obj->printHello();
|
||||
?>
|
||||
|
||||
* Object Cloning.
|
||||
|
||||
The Zend Engine 1.0 offered no way a user could decide what copy
|
||||
constructor to run when an object is duplicated. During
|
||||
duplication, the Zend Engine 1.0 did a bitwise copy making an
|
||||
identical replica of all the object's properties.
|
||||
|
||||
Creating a copy of an object with fully replicated properties is
|
||||
not always the wanted behavior. A good example of the need for
|
||||
copy constructors, is if you have an object which represents a
|
||||
GTK window and the object holds the resource of this GTK window,
|
||||
when you create a duplicate you might want to create a new
|
||||
window with the same properties and have the new object hold the
|
||||
resource of the new window. Another example is if your object
|
||||
holds a reference to another object which it uses and when you
|
||||
replicate the parent object you want to create a new instance of
|
||||
this other object so that the replica has its own separate copy.
|
||||
|
||||
An object copy is created by calling the object's __clone()
|
||||
method.
|
||||
|
||||
Example:
|
||||
|
||||
<?php
|
||||
$copy_of_object = $object->__clone();
|
||||
?>
|
||||
|
||||
When the developer asks to create a new copy of an object, the
|
||||
Zend Engine will check if a __clone() method has been defined or
|
||||
not. If not, it will call a default __clone() which will copy
|
||||
all of the object's properties. If a __clone() method is
|
||||
defined, then it will be responsible to set the necessary
|
||||
properties in the created object. For convenience, the engine
|
||||
will supply a function that imports all of the properties from
|
||||
the source object, so that they can start with a by-value
|
||||
replica of the source object, and only override properties that
|
||||
need to be changed. [The function hasn't been implemented yet]
|
||||
|
||||
Example:
|
||||
|
||||
<?php
|
||||
class MyCloneable {
|
||||
static $id = 0;
|
||||
|
||||
function MyCloneable() {
|
||||
$this->id = self::$id++;
|
||||
}
|
||||
|
||||
function __clone() {
|
||||
$this->name = $clone->name;
|
||||
$this->address = 'New York';
|
||||
$this->id = self::$id++;
|
||||
}
|
||||
}
|
||||
|
||||
$obj = new MyCloneable();
|
||||
|
||||
$obj->name = 'Hello';
|
||||
$obj->address = 'Tel-Aviv';
|
||||
|
||||
print $obj->id . "\n";
|
||||
|
||||
$obj = $obj->__clone();
|
||||
|
||||
print $obj->id . "\n";
|
||||
print $obj->name . "\n";
|
||||
print $obj->address . "\n";
|
||||
?>
|
||||
|
||||
* Forced deletion of objects.
|
||||
|
||||
The Zend Engine 1.0 had no means to force deletion of an object
|
||||
if there are still references to it. The newly introduced delete
|
||||
statement calls the object's destructor and frees it even if the
|
||||
object is referenced by some other places in the engine. Other
|
||||
references to the deleted object become stale and trying to
|
||||
access them results in a fatal error.
|
||||
|
||||
Note that if you have a user-defined function delete() in an old
|
||||
script, this script will yield a parser error with the Zend
|
||||
Engine 2.0, since 'delete' is now a reserved word.
|
||||
|
||||
* Nested classes (namespaces).
|
||||
|
||||
The Zend Engine 1.0 provided only three scopes: the global
|
||||
scope, the class scope and the function scope. All scopes but
|
||||
classes could contain variables, only the class and global
|
||||
scopes could contain functions, while only the global scope
|
||||
could contain constants and classes. This means that all of the
|
||||
Zend Engine 1.0's scoping methods were inherently limited for
|
||||
solving symbol name collision problems.
|
||||
|
||||
The Zend Engine 2.0 introduces the concept of nested classes
|
||||
to solve the symbol collision problem by making it possible to
|
||||
define multiple symbol tables able to contain all types of
|
||||
symbols. The Zend Engine is aware of a current class,
|
||||
defaulting to the global scope. Each class can contain it's
|
||||
own set of constants, functions and static variables. In order
|
||||
to access a class's local symbols you can use the self:: class
|
||||
accessor, for example, you can do self::$my_static_name = "Hello".
|
||||
You can also use the class's name such as
|
||||
MyClass::$my_static_name = "Hello". WIth both constants and
|
||||
functions, if you don't specify a class context the current class
|
||||
will be searched first and if the search fails then the global
|
||||
scope will be searched. If you want to force PHP to only check the
|
||||
global scope you can use the main:: accessor. For example,
|
||||
main::strlen() to make sure you're calling the strlen() in the main
|
||||
scope. You will only need to worry about this if you are defining
|
||||
methods which have the same name as global functions. For
|
||||
constants you can use the same notation such as self::MY_CONSTANT
|
||||
or main::MY_CONSTANT.
|
||||
Sometimes you will not want to access constants, functions or classes
|
||||
via the class accessor (i.e. MyClass::) because you use them very
|
||||
often and are an extremely slow typist. In this case, you can import
|
||||
functions, classes and constants from classes with the import keyword.
|
||||
It's quite self explanatory and there are a few examples below.
|
||||
|
||||
|
||||
* Classes may contain classes.
|
||||
|
||||
Example:
|
||||
|
||||
<?php
|
||||
class DB::MySQL {
|
||||
var $host = '';
|
||||
|
||||
function db_connect($user) {
|
||||
print "Connecting to MySQL database '$this->host' as $user\n";
|
||||
}
|
||||
}
|
||||
|
||||
class DB::Oracle {
|
||||
var $host = 'localhost';
|
||||
|
||||
function db_connect($user) {
|
||||
print "Connecting to Oracle database '$this->host' as $user\n";
|
||||
}
|
||||
}
|
||||
|
||||
$MySQL_obj = new DB::MySQL();
|
||||
$MySQL_obj->db_connect('Susan');
|
||||
|
||||
$Oracle_obj = new DB::Oracle();
|
||||
$Oracle_obj->db_connect('Barbara');
|
||||
?>
|
||||
|
||||
* Classes may contain constants.
|
||||
|
||||
Example:
|
||||
|
||||
<?php
|
||||
class foo {
|
||||
const hey = 'hello';
|
||||
}
|
||||
|
||||
print foo::hey;
|
||||
?>
|
||||
|
||||
* Current namespace's symbol tables are searched first for
|
||||
constants and functions.
|
||||
|
||||
Example:
|
||||
|
||||
The following code prints "foobar", not "bar", because
|
||||
the class constant overrides the "global" constant of
|
||||
the same name.
|
||||
|
||||
<?php
|
||||
define('foo', 'bar');
|
||||
|
||||
class FooClass {
|
||||
const foo = 'foobar';
|
||||
|
||||
function printFoo() {
|
||||
print foo;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
* In the scope of a function, the current namespace is that
|
||||
of the containing class/namespace.
|
||||
|
||||
Example:
|
||||
|
||||
<?php
|
||||
class FooClass {
|
||||
function foo() {
|
||||
$this->bar();
|
||||
bar();
|
||||
}
|
||||
|
||||
function bar() {
|
||||
print "foobar\n";
|
||||
}
|
||||
}
|
||||
|
||||
$obj = new FooClass;
|
||||
$obj->foo();
|
||||
?>
|
||||
|
||||
This prints "foobar" two times, since a bar() method exists
|
||||
in the current namespace.
|
||||
|
||||
* It is possible to "import" symbols from one namespace into
|
||||
another.
|
||||
|
||||
Example:
|
||||
|
||||
<?php
|
||||
class MyClass {
|
||||
class MyClass2 {
|
||||
function hello() {
|
||||
print "Hello, World in MyClass2\n";
|
||||
}
|
||||
}
|
||||
|
||||
function hello() {
|
||||
print "Hello, World\n";
|
||||
}
|
||||
}
|
||||
|
||||
import function hello, class MyClass2 from MyClass;
|
||||
|
||||
MyClass2::hello();
|
||||
hello();
|
||||
?>
|
||||
|
||||
Example:
|
||||
|
||||
<?php
|
||||
class MyOuterClass {
|
||||
class MyInnerClass {
|
||||
function func1() {
|
||||
print "func1()\n";
|
||||
}
|
||||
|
||||
function func2() {
|
||||
print "func2()\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
import class * from MyOuterClass;
|
||||
import function func2 from MyOuterClass::MyInnerClass;
|
||||
|
||||
MyInnerClass::func1();
|
||||
func2();
|
||||
?>
|
||||
|
||||
Example:
|
||||
|
||||
<?php
|
||||
class MyOuterClass {
|
||||
const Hello = "Hello, World\n";
|
||||
}
|
||||
|
||||
import const Hello from MyOuterClass;
|
||||
print Hello;
|
||||
?>
|
||||
|
||||
Old code that does not take advantage of namespaces will run
|
||||
without modifications.
|
||||
|
||||
* Unified Constructors.
|
||||
|
||||
The Zend Engine allows developers to declare constructor methods
|
||||
for classes. Classes which have a constructor method call this
|
||||
method on each newly-created object, so it is suitable for any
|
||||
initialization that the object may need before it can be used.
|
||||
|
||||
With the Zend Engine 1.0, constructor methods were class methods
|
||||
that had the same name as the class itself. Since it is very
|
||||
common to call parent constructors from derived classes, the way
|
||||
the Zend Engine 1.0 worked made it a bit cumbersome to move
|
||||
classes around in a large class hierarchy. If a class is moved
|
||||
to reside under a different parent, the constructor name of that
|
||||
parent changes as well, and the code in the derived class that
|
||||
calls the parent constructor has to be modified.
|
||||
|
||||
The Zend Engine 2.0 introduces a standard way of declaring
|
||||
constructor methods by calling them by the name __construct().
|
||||
|
||||
Example:
|
||||
|
||||
<?php
|
||||
class BaseClass {
|
||||
function __construct() {
|
||||
print "In BaseClass constructor\n";
|
||||
}
|
||||
}
|
||||
|
||||
class SubClass extends BaseClass {
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
print "In SubClass constructor\n";
|
||||
}
|
||||
}
|
||||
|
||||
$obj = new BaseClass();
|
||||
$obj = new SubClass();
|
||||
?>
|
||||
|
||||
For backwards compatibility, if the Zend Engine 2.0 cannot find
|
||||
a __construct() function for a given class, it will search for
|
||||
the old-style constructor function, by the name of the class.
|
||||
Effectively, it means that the only case that would have
|
||||
compatibility issues is if the class had a method named
|
||||
__construct() which was used for different semantics.
|
||||
|
||||
* Destructors.
|
||||
|
||||
Having the ability to define destructors for objects can be very
|
||||
useful. Destructors can log messages for debugging, close
|
||||
database connections and do other clean-up work.
|
||||
|
||||
No mechanism for object destructors existed in the Zend Engine
|
||||
1.0, although PHP had already support for registering functions
|
||||
which should be run on request shutdown.
|
||||
|
||||
The Zend Engine 2.0 introduces a destructor concept similar to
|
||||
that of other object-oriented languages, such as Java: When the
|
||||
last reference to an object is destroyed the object's
|
||||
destructor, which is a class method name __destruct() that
|
||||
recieves no parameters, is called before the object is freed
|
||||
from memory.
|
||||
|
||||
Example:
|
||||
|
||||
<?php
|
||||
class MyDestructableClass {
|
||||
function __construct() {
|
||||
print "In constructor\n";
|
||||
$this->name = 'MyDestructableClass';
|
||||
}
|
||||
|
||||
function __destruct() {
|
||||
print 'Destroying ' . $this->name . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
$obj = new MyDestructableClass();
|
||||
?>
|
||||
|
||||
Like constructors, parent destructors will not be called
|
||||
implicitly by the engine. In order to run a parent destructor,
|
||||
one would have to explicitly call parent::__destruct() in the
|
||||
destructor body.
|
||||
|
||||
* Exceptions.
|
||||
|
||||
The Zend Engine 1.0 had no exception handling. The Zend Engine 2.0
|
||||
introduces a exception model similar to that of other programming
|
||||
languages.
|
||||
|
||||
Example:
|
||||
|
||||
<?php
|
||||
class MyException {
|
||||
function __construct($exception) {
|
||||
$this->exception = $exception;
|
||||
}
|
||||
|
||||
function Display() {
|
||||
print "MyException: $this->exception\n";
|
||||
}
|
||||
}
|
||||
|
||||
class MyExceptionFoo extends MyException {
|
||||
function __construct($exception) {
|
||||
$this->exception = $exception;
|
||||
}
|
||||
|
||||
function Display() {
|
||||
print "MyException: $this->exception\n";
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
throw new MyExceptionFoo('Hello');
|
||||
}
|
||||
|
||||
catch (MyException $exception) {
|
||||
$exception->Display();
|
||||
}
|
||||
?>
|
||||
|
||||
Old code that has no user-defined functions 'catch', 'throw' and
|
||||
'try' will run without modifications.
|
||||
|
||||
* Dereferencing objects returned from functions.
|
||||
|
||||
Example:
|
||||
|
||||
<?php
|
||||
class Circle {
|
||||
function draw() {
|
||||
print "Circle\n";
|
||||
}
|
||||
}
|
||||
|
||||
class Square {
|
||||
function draw() {
|
||||
print "Square\n";
|
||||
}
|
||||
}
|
||||
|
||||
function ShapeFactoryMethod($shape) {
|
||||
switch ($shape) {
|
||||
case 'Circle': return new Circle();
|
||||
case 'Square': return new Square();
|
||||
}
|
||||
}
|
||||
|
||||
ShapeFactoryMethod('Circle')->draw();
|
||||
ShapeFactoryMethod('Square')->draw();
|
||||
?>
|
||||
|
||||
* Static member variables of static classes can now be
|
||||
initialized.
|
||||
|
||||
Example:
|
||||
|
||||
<?php
|
||||
class foo {
|
||||
static $my_static = 5;
|
||||
}
|
||||
|
||||
print foo::$my_static;
|
||||
?>
|
||||
|
||||
* Parameters that are passed by reference to a function
|
||||
may now have default values.
|
||||
|
||||
Example:
|
||||
|
||||
<?php
|
||||
function my_function(&$var = null) {
|
||||
if ($var === null) {
|
||||
die('$var needs to have a value');
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
* Built-In Backtracing.
|
||||
|
||||
Example:
|
||||
|
||||
<?php
|
||||
$backtrace = debug_backtrace();
|
||||
|
||||
foreach ($backtrace as $step) {
|
||||
$class = isset($step['class']) ? $step['class'] . '::' : '';
|
||||
|
||||
printf(
|
||||
"%s%s [%s:%s]\n",
|
||||
$class,
|
||||
$step['function'],
|
||||
$step['file'],
|
||||
$step['line']
|
||||
);
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
@@ -138,8 +138,6 @@ $uri_aliases = array (
|
||||
"subscribe" => "mailing-lists",
|
||||
"logos" => "download-logos",
|
||||
|
||||
"README.mirror" => "mirroring", // backward compatibility
|
||||
|
||||
# manual shortcuts
|
||||
"ini" => "configuration",
|
||||
|
||||
@@ -159,19 +157,20 @@ $uri_aliases = array (
|
||||
"gd" => "image",
|
||||
|
||||
"tut" => "tutorial",
|
||||
"tut.php" => "tutorial", // for backward compatibility with PHP page!
|
||||
"tut.php" => "tutorial", // BC
|
||||
|
||||
"faq.php" => "faq", // for backward compatibility with PHP page!
|
||||
"bugs.php" => "bugs", // for backward compatibility with PHP page!
|
||||
"bugstats.php" => "bugstats", // for backward compatibility with PHP page!
|
||||
"faq.php" => "faq", // BC
|
||||
"bugs.php" => "bugs", // BC
|
||||
"bugstats.php" => "bugstats", // BC
|
||||
|
||||
"icap" => "mcal", // mcal is the successor of icap
|
||||
|
||||
"README.mirror" => "mirroring", // BC with mirroring readme!
|
||||
"README.mirror" => "mirroring", // BC
|
||||
"ZEND_CHANGES.txt" => "zend-engine-2.php", // BC
|
||||
|
||||
# external shortcut aliases ;)
|
||||
"dochowto" => "phpdochowto",
|
||||
"projects.php" => "projects", // for backward compatibility with PHP page!
|
||||
"projects.php" => "projects", // BC
|
||||
);
|
||||
|
||||
$external_redirects = array(
|
||||
|
||||
Reference in New Issue
Block a user