Laut PHP-Doku ist das Verhalten der Pseudo-Variablen $this wie folgt:
$this is a reference to the calling object (usually the object to which the method belongs, but can be another object, if the method is called statically from the context of a secondary object).
Schauen wir uns folgendes Beispiel an:
class A{
function __construct(){
$this->name = 'A';
}
function echoThisName(){
echo "My Name is {$this->name}.\n";
}
}
Jetzt rufen wir die Methode mal als Instanzmethode und mal statisch auf:
$a = new A();
$a->echoThisName();
A::echoThisName();
My Name is A.
PHP Fatal error: Using $this when not in object context in
/Users/aljoscha/test.php on line 9
Fatal error: Using $this when not in object context in
/Users/aljoscha/test.php on line 9
Das ist vernünftig. (ausser: Warum muss sich PHP eigentlich immer wiederholen? Ist eine Fehlermeldung zu subtil?)
Jetzt rufen wird diese Methoden aus einer anderen Klasse B heraus auf:
class B{
function __construct(){
$this->name = 'B';
}
function echoAsName(){
$a = new A();
$a->echoThisName();
A::echoThisName();
}
}
$b = new B();
$b->echoAsName();
Und das gibt:
My Name is A.
My Name is B.
Wir haben die Methode echoThisName der Klasse Astatisch aufgerufen, aber $this ist darin trotzdem gesetzt, und zwar als wären wir in der Instanz $b der Klasse B. $b hat sich die statische Methode gekapert.
Was sagt Ruby dazu?
class A
def initialize
@name = 'A';
end
def echoThisName
puts "My Name is #{@name}.\n";
end
end
$a = A.new;
$a.echoThisName;
A::echoThisName;
ergibt:
My Name is A.
test.rb:13: undefined method `echoThisName' for A:Class (NoMethodError)
Rufen wir A::echoThisName aus einer Instanz von B auf:
class B
def initialize
@name = 'B';
end
def echoAsName
$a = A.new;
$a.echoThisName;
A::echoThisName;
end
end
$b = B.new;
$b.echoAsName;
Ist das Ergebnis entsprechend:
My Name is A.
test.rb:23:in `echoAsName': undefined method `echoThisName'
for A:Class (NoMethodError) from test.rb:28
Besser. Dank an Stephan für den Hinweis auf die Dokumentation des Verhaltens in PHP.
Manche Dinge in PHP sind so komisch, dass man sie sich am besten einmal notiert, um sich dann in Ruhe darüber zu wundern.
Falls z.B. in PHP eine Variable $a auf den Wert null gesetzt ist, liefert isset($a) trotzdem false. (Das ist nichts Neues, aber es ist merkwürdig im Wortsinne.) Interessant auch das Verhalten von empty und is_null für ungesetzte Variablen und Variablen mit dem Wert null. Dazu initialisieren wir Variable $a mit dem Wert null und lassen Variable $b völlig uninitialisiert:
$a = null;
# $b wird nicht initialisiert
Hier nun die Tests:
Test
$a
$b
isset()
false
false
empty()
true
true
is_null()
true
true
=== null
true
true
Das Ergebnis von isset($a) ist zumindest gegen jede Intuition.
Bizarr wird es aber bei der gedoppelten (?) Notice PHP Notice: Undefined variable: b in /home/aljoscha/test.php on line 10
Notice: Undefined variable: b in /home/aljoscha/test.php on line 10, die durch is_null($b) bzw. ($b === null) ausgelöst wird, und dem überraschenden Ergebnis: true!
In what they call a “backwards compatibility change” the prototype core developers have introduced some changes to the prototype Hash class.
A little history:
From version 1.5 the Hash class started behaving a bit differently because now the Enumerable methods where copied into the Hash prototype instead of into the instances, as before. That helped minimize the memory footprint but introduced incompatibilities and removed the possibility to patch Enumerables methods because after patching Enumerable one would have to manually copy its methods into all “inheriting” classes again.
To my understanding that is in conflict with the dynamic inheritance in prototype-based languages like javascript.
See this thread for more info.
Now with 1.6. things get worse. The Hash object is not an JS object with added functionality anymore, its a wrapper around one.
The following code will work in 1.5.0.2 but not in 1.6:
test = $H({a: 1, b:2});
alert(test.a); // -> 1 in version 1.5
Instead, in prototype 1.6 you have to write test.get('a') to get to the property “a” of the underlying object. In case you need the whole object, there is always test.toObject() to the rescue. Bye bye, consise and short notation.
I feel the developers forgot what made prototype so wildly successfull: Its beautiful concept of enhancing the built in objects, not wrapping them.
I consider leaving the prototype world alltogether and will switch to mootools.
November 25, 2007 at 12:07 am · Filed under MacOSX
After installing Leopard, the previous Apache configuration file in /etc/httpd/httpd.conf is no longer used. The Apache configuration sits in /etc/apache2/httpd.conf now.
In order to enable PHP again, I uncommented the following line first: LoadModule php5_module libexec/apache2/libphp5.so
Second, to get my virtual hosts running again, I used the adapted Leopard version of Patrick Gibsons excellent utility virtualhost.sh which even automatically moves all prior (Tiger) virtual hosts.
Finally to get rid of the error Can't connect to local MySQL server through socket '/var/mysql/'
I successfully followed the steps found here: sudo mkdir /var/mysql/
sudo ln -s /tmp/mysql.sock /var/mysql/mysql.sock
They are a nice way to store flags, for example, and by providing an aggregate function to sum them up, one can easily compute complex unions of properties.
First we define an aggregate function to sum postgresql hstores, straightforward as this:
CREATE OR REPLACE FUNCTION array_to_hstore(text[]) RETURNS hstore AS $$
DECLARE
arr text[];
result hstore;
BEGIN
SELECT INTO arr $1;
SELECT INTO result sum(key=>1) FROM (
select
btrim(arr[idx.i]) as key
from
generate_series(1, array_upper(arr,1)) as idx(i)
) as dummy;
RETURN result;
END
$$ LANGUAGE plpgsql;
Now what can be done with that? For example we can turn comma separated lists into hstores:
Some days ago I tried installing svk on MacOSX using fink.
Everything worked fine except when I finally tried to use it:
aljoscha% svk
Can't locate Class/Autouse.pm in @INC
(@INC contains: /System/Library/Perl/5... [snip] ...5.8.1 .) at /Library/Perl/5.8.6/SVK.pm line 6.
BEGIN failed--compilation aborted at /Library/Perl/5.8.6/SVK.pm line 6.
Compilation failed in require at /usr/bin/svk line 6.
BEGIN failed--compilation aborted at /usr/bin/svk line 6.
The solution was not so obvious to me: Fink sets its paths in
/sw/bin/init.sh (/sw/bin/init.csh for csh users respectively)
The following article describes ticket #3592 in the RoR Trac and explains a proposed solution.
Prototypes Enumerable mixin class does not properly respect the mixees internal format. For example the reject and findAll methods, operating on Hashes, return Arrays instead of Hashes.
var a = $H({a:1, b:2, c:1, d:3});
document.writeln(a.inspect().escapeHTML());
=>#
var b = a.reject(function(val){ return (val[1]==1) });
document.writeln(b.inspect().escapeHTML());
=> [['b', 2], ['d', 3]] // !!! should be hash
var c = b.findAll(function(val){ return (val[0]=='d') });
document.writeln(c.inspect().escapeHTML());
=> [['b', 2], ['d', 3]] // !!! should be hash
In Ruby (from which the inspiration for the Enumerable Mixin stems), the reject method does return a hash, not an array, when operating on an hash:
The patch requires all classes that want to mixin Enumerable to define two more methods similar to _each: _new, which returns an empty object of that class and _add, that adds an element. Enumerable mixin thus needs to make no more assumptions about the internal structure of its mixee class.