php.de

Zurück   php.de > Webentwicklung > PHP-Fortgeschrittene

PHP-Fortgeschrittene Arbeiten mit PHP ohne Einschränkungen

Antwort
 
LinkBack Themen-Optionen Thema bewerten
Alt 21.04.2005, 14:47  
Gast
 
Beiträge: n/a
Standard array_pop und Objekte

PHP Version 4.3.5

Hallo!

Nach längerer Fehlersuche in einem komplexen Projekt habe ich die Ursache auf die folgenden Code-Schnipsel reduzieren können. Grundaufgabenstellung ist ein Objekt, das Aufrufe intern speichert und Ergebnisse von bereits getätigten Aufrufen aus dem Speicher zurückliefert (im Original steht eine Datenbank dahinter). Das zurückgeliefert Ergebnis ist in jedem Fall ein Array, das dann weiter ausgewertet wird. Im Beispiel-Objekt ist das Ganze darauf reduziert, dass die Methode cache() sich beim erstem Aufruf mit einem Argument dieses Argument, einen Text und die Aufrufzeit 'merkt'. Folgeaufrufe mit dem selben Argument liefern das Ergebnis des ersten Aufrufes. So weit so gut, hier das Objekt:
Code:
class foobar {
  var $cache = array();
  function cache($j) {
    if (!isset($this->cache[$j])) {
      $this->cache[$j] = array(
        'wert' => $j,
        'text' => 'Aufruf erfolgte mit dem Wert: '.$j.'
',
        'time' => 'Aufruf erfolgte um '.date('h:i:s').' Uhr
',
      );
    }
    return($this->cache[$j]);
  }
}
Eine 'typische' Anwendung wäre:
Code:
$foobar =& new foobar();
$v = $foobar->cache(3);
echo $v['time'];
$v = $foobar->cache(3);
echo $v['time'];
$v = $foobar->cache(3);
echo $v['time'];
$v = $foobar->cache(3);
echo $v['time'];
/* ergibt z.B.
  Aufruf erfolgte um 02:19:11 Uhr
  Aufruf erfolgte um 02:19:11 Uhr
  Aufruf erfolgte um 02:19:11 Uhr
  Aufruf erfolgte um 02:19:11 Uhr
als Ausgabe*/
und man erhält jedes Mal die selbe Zeit angezeigt - Hurra! Aber jetzt kommt's: In meiner Leichtsinnigkeit habe ich mir gedacht, warum zwei Code-Zeilen, wenn auch eine reicht. 'time' ist der letzte Index im Array, also nehme ich mir einfach array_pop() her und spare mir die Zuweisung an eine Variable:
Code:
$foobar =& new foobar();
echo array_pop($foobar->cache(3));
/* ergibt
  Aufruf erfolgte um 02:19:11 Uhr
als Ausgabe*/
Geht auch. Interessant wird es, wenn man das mehrfach macht:
Code:
$foobar =& new foobar();
echo array_pop($foobar->cache(3));
echo array_pop($foobar->cache(3));
echo array_pop($foobar->cache(3));
echo array_pop($foobar->cache(3));
/* ergibt
  Aufruf erfolgte um 02:19:11 Uhr
  Aufruf erfolgte mit dem Wert: 3
  3

als Ausgabe*/
D.h. array_pop() 'klaut' dem Objekt die Daten =8-0. Macht man übrigens folgendes
Code:
$foobar =& new foobar();
$v = $foobar->cache(3);
echo $v['time'];
echo array_pop($foobar->cache(3));
/* ergibt
  Aufruf erfolgte um 02:19:11 Uhr

  Fatal error: Only variables can be passed by reference in ...
als Ausgabe*/
gibt es den eigentlich bei diesem Konstrukt wohl immer zu erwartenden Fehler, dass das Argument von array_pop() keine Variable ist (sondern ein Funktionsergebnis, und das ist (eigentlich) unveränderlich). Das gleiche passiert übrigens auch, wenn statt einer Objektvariablen eine statische Funktionsvariable verwendet wird.

Da es sich wohl um einen Bug handelt (habe bei php.net allerdings nix dazu gefunden), kann man wohl nix dagegen machen außer array_pop() nicht zu verwenden.

Warum ich das hier (außer zur allgemeinen Belustigung) trotzdem gepostet habe: Hat jemand eine Idee, wie ich dem Parser zeitsparend mitteile, dass zwei Variablen nicht identisch sind? Ich dachte nämlich erst, wenn ich in cache() nicht direkt $this->cache[$j] zurückliefere, sondern den Wert erst an eine andere Variable übergebe, würde es klappen, aber war nicht
Code:
$temp = $this->cache[$j];
return($temp);
macht genau das selbe. So
Code:
$temp = str_replace('','',($this->cache[$key]));
return($temp);
geht es, und noch kürzer
Code:
return(str_replace('','',($this->cache[$key]));
auch (obwohl es sich um ein Array handelt!). Aber hat irgendjemand von euch noch eine bessere Idee?
  Mit Zitat antworten
Sponsor Mitteilung
PHP Code Flüsterer

Registriert seit: 21.08.2005
Beiträge: 4682
PHP-Kenntnisse:
Fortgeschritten

Alt 21.04.2005, 16:27  
Gast
 
Beiträge: n/a
Standard

array_pop() liefert den letzten Wert von array, und verkürzt array um ein Element. Ist array leer (oder kein Array), wird NULL zurückgegeben.
  Mit Zitat antworten
Alt 21.04.2005, 16:54  
axo
Erfahrener Benutzer
 
Registriert seit: 24.12.2004
Beiträge: 1.814
axo ist zur Zeit noch ein unbeschriebenes Blatt
Standard Re: array_pop und Objekte

Zitat:
Zitat von calvini
Da es sich wohl um einen Bug handelt (habe bei php.net allerdings nix dazu gefunden), kann man wohl nix dagegen machen außer array_pop() nicht zu verwenden.
nope. no bug, php kann nur mit referenzen nicht so gut umgehen, wie es vielleicht andere sprachen können. ist ein implementierungsproblem von php und wird auf lange sicht gelöst (einiges ist in php5 bereits geschehen), aber mit php4 geht's auf jeden fall so nicht.

du brauchst das ganze auf jeden fall zweizeilig.

PHP-Code:
<?php
$foo 
= & new Foo();
$bar = & new Bar($foo);

$obj = & new someObject($bar);

// das geht in php

$myBar = & $obj -> getBar();
$myFoo = & $myBar -> getFoo();

// das geht nicht, erst mit php5, aber dort auch nur eingeschränkt.
$obj -> getBar() -> getFoo(); 

?>
d.h. du kannst rückwärts-referenzen nicht ordentlich auswerten, und das ist auch der grund, warum array_pop nicht so reagiert wie gewünscht.

in diesen fällen geht es halt einfach nicht, zeilen zu sparen.
axo ist offline   Mit Zitat antworten
Alt 21.04.2005, 17:07  
Gast
 
Beiträge: n/a
Standard

hi,

tja da ist php wirklich etwas speziell (:
es verhält sich genau in diesem fall extrem inkonsistent. ich denke das eigentlich problem das du ansprichst ist warum array_pop das array des objectes verändert obwohl es eigentlich als kopie zurückgegeben werden sollte (fehlendes &).
ehrlich meinung ? ich weiss es nicht - es macht eigentlich nicht viel sinn so aber damit müssen wir wohl oder übel leben.

das lustige ist aber das es so
PHP-Code:
$foobar =& new foobar();
$foobar->cache(3);
var_dump($foobar);
$t1 $foobar->cache(3);
print 
array_pop($t1);
var_dump($foobar); 
funktioniert. also wird wohl immer eine referenz zurückgegeben und erst mit der zuweisung eine kopie erzeugt. warum das innerhalb der klassenmethode nicht funktioniert kann ich momentan auch nicht erklären.....

gruss
Sike
  Mit Zitat antworten
Alt 21.04.2005, 17:14  
Waq
Erfahrener Benutzer
 
Registriert seit: 15.08.2004
Beiträge: 2.473
Waq
Standard Re: array_pop und Objekte

Zitat:
Zitat von calvini
Fatal error: Only variables can be passed by reference in ...
Die Fehlermeldung ist doch Wunderbar suggestiv. array_pop will eine Referenz, also liefer ihm eine!
PHP-Code:
function &cache($j
Alternativ:
PHP-Code:
$temp = &$this->cache[$j];
return(
$temp); 
__________________
mod = master of disaster
Waq ist offline   Mit Zitat antworten
Alt 21.04.2005, 17:52  
Gast
 
Beiträge: n/a
Standard

@all: Werde nicht so ganz schlau aus Euren Antworten. Lediglich Sike scheint verstanden zu haben, was ich meine .

@Meikel: Ich weiß, was array_pop() macht (bzw. machen soll), schließlich sind wir hier ja im Profi-Bereich .

@axo: Da sehe ich nicht ganz den Zusammenhang mit dem von mir geschilderten Problem ?

@Waq: Ich weiß, dass array_pop() eine Referenz erwartet (siehe auch @Meikel ).

Das Problem ist doch, dass array_pop() einerseits das Ergebnis des Aufrufs einer Methode als Referenz akzeptiert (und dabei Daten des Objektes verändert), andererseits (wenn das Ergebnis des Aufrufs der Methode vorher bereits einer Variable zugewiesen wurde) eine Fehlermeldung erzeugt. Wird array_pop() hingegen mit dem Ergebnis einer Funktion aufgerufen, tritt der Fehler immer auf, egal ob voher das Funktionsergebnis einer Variablen zugewiesen wurde oder nicht.
  Mit Zitat antworten
Alt 21.04.2005, 18:18  
Waq
Erfahrener Benutzer
 
Registriert seit: 15.08.2004
Beiträge: 2.473
Waq
Standard

Zitat:
Zitat von calvini
Wird array_pop() hingegen mit dem Ergebnis einer Funktion aufgerufen, tritt der Fehler immer auf, egal ob voher das Funktionsergebnis einer Variablen zugewiesen wurde oder nicht.
Das stimmt so nicht. Folgendes läuft wunderbar:
PHP-Code:
<?php
function foo() {
  
$v = array("hiho1\n");
  return 
$v;
}

echo 
array_pop(foo());
?>
Das hier hingegen läuft nur durch die Definition von foo() als Rerefenztyp:
PHP-Code:
<?php
class bar {
  var 
$v = array("hiho1\n","hiho2\n");

  function &
foo() {
    return 
$this->v;
  }

  function 
foo2() {
    return 
$this->v;
  }
}

$bar = new bar();
echo 
array_pop($bar->foo());
echo 
array_pop($bar->foo2());
?>
Seltsam finde ich, dass nach dem Aufruf von foo() auch foo2() funktioniert, obwohl Referenzfrei. Dürfte tatsächlich eine Eigenheit des Referenzsystems von PHP sein, kannst ja nen Bug-Report anlegen. Allerdings nicht mit deinem Beispielcode.

PS: Ist jetzt klar, wie ich die "Referenz" als Fix meinte?

PPS: Das Problem besteht so auch in PHP 5.
__________________
mod = master of disaster
Waq ist offline   Mit Zitat antworten
Alt 21.04.2005, 20:09  
Gast
 
Beiträge: n/a
Standard

Zitat:
Zitat von calvini
@Meikel: Ich weiß, was array_pop() macht (bzw. machen soll), schließlich sind wir hier ja im Profi-Bereich .
Sicher ist sicher. :wink:

Der Bug ist nachvollziehbar:
http://test.php-help.info/class-10/ (Quelltext wird angezeigt)

Ich habe die Namen etwas geändert.

Erstaunlich, daß auch das nicht will:

PHP-Code:
<?php
$i 
$this->cache[$j];
return 
$i;
?>
  Mit Zitat antworten
Alt 21.04.2005, 22:06  
Erfahrener Benutzer
 
Registriert seit: 18.07.2004
Beiträge: 2.162
PHP-Kenntnisse:
Fortgeschritten
Basti
Standard

Hi.

Ein return (array) $this->cache[$j]; bringt bei mir das erwünschte Ergebnis (5.0.2). Ist aber schon krass!

Basti
Basti ist offline   Mit Zitat antworten
Alt 21.04.2005, 22:15  
Gast
 
Beiträge: n/a
Standard

Zitat:
Ist aber schon krass!
So isses.

5.0.4:
http://test.php-help.info/class-10-1/

Da loft aber was generell schief, wenn man ein Array als Array "zwangs-casten" muß, damit array_pop() (und wert weiß, was noch) mit dem Returnwert und nicht mit der Referenz weiterwurschtelt....
  Mit Zitat antworten
Antwort


Themen-Optionen
Thema bewerten
Thema bewerten:

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an
Gehe zu

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
[Erledigt] Referenzen auf Objekte innerhalb eines Arrays PHP-Fortgeschrittene 6 31.08.2009 17:06
[Erledigt] objekte mit bilddaten serialisieren lumo PHP Tipps 2008 1 17.07.2008 12:25
[Erledigt] Objekte übergeben Felix PHP Tipps 2008 23 18.06.2008 12:21
Objekte zur Laufzeit Vererbung anhängen Zergling-new PHP-Fortgeschrittene 8 17.11.2007 17:31
2 AJAX Objekte GSJLink HTML, Usability und Barrierefreiheit 6 15.08.2007 16:05
Objekte moose PHP Tipps 2006 13 29.07.2006 16:18
Rekursives durchlaufen meiner Objekte GELight PHP Tipps 2006 2 01.07.2006 23:21
Objekte sortieren Fatal Error PHP Tipps 2006 4 13.04.2006 14:24
[Erledigt] Objekte vergleichen PHP-Fortgeschrittene 4 08.12.2005 16:20
objekte und klassen notyyy PHP Tipps 2005-2 2 24.10.2005 17:44
Objekte PHP Tipps 2005-2 12 09.10.2005 18:20
[Erledigt] Verständnisfrage OOP - Objekte in MySQL Datenbank schreiben? PHP Tipps 2005 2 19.05.2005 21:40
Ganze Objekte an Script weitergeben dreamingof8a PHP Tipps 2004-2 6 23.11.2004 12:17
[Erledigt] Referenzen auf Objekte PHP-Fortgeschrittene 2 17.08.2004 11:08
Anonyme Objekte? PHP-Fortgeschrittene 18 25.07.2004 22:19

Besucher kamen über folgende Suchanfragen bei Google auf diese Seite
array_pop object, only variables should be passed by reference array_pop, fehlermeldung array_pop, return wert von array_pop, array_pop, array_pop only variables should be passed by reference, array_pop funktioniert nicht, php objekt datensätze, php array_pop funktioniert nicht, array_pop bei objekten, php array_pop, array_pop objekt, array_pop() objekt, array_pop für classe, php objekt rückwärts durchlaufen, suche und sortieren objekte php

Alle Zeitangaben in WEZ +2. Es ist jetzt 20:30 Uhr.




Powered by vBulletin® Version 3.7.2 (Deutsch)
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
Aprilia-Forum, Aquaristik-Forum, Liebeskummer-Forum, Zierfisch-Forum, Geizkragen-Forum

Creative Commons License
Dieser Inhalt ist unter einer Creative Commons-Lizenz lizenziert.