php.de

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

PHP-Fortgeschrittene Arbeiten mit PHP ohne Einschränkungen

Antwort
 
LinkBack Themen-Optionen Thema bewerten
Alt 06.08.2010, 12:04  
Neuer Benutzer
 
Registriert seit: 02.08.2010
Beiträge: 2
PHP-Kenntnisse:
Fortgeschritten
tr8000 befindet sich auf einem aufstrebenden Ast
Standard Overloading und (mehrdimensionale) Arrays

Hallo zusammen,

ich nutze für ein Projekt das Registry Pattern in Kombination mit dem Singleton Pattern, um Variablen persistent abzulegen.
Dazu ein Ausschnitt aus der entsprechenden Klasse SessionRegistry:
PHP-Code:
class SessionRegistry
{
    protected static 
$instance null;

    protected function 
__construct()
    {
        
session_start();
        if(!isset(
$_SESSION['__registry']))
        {
            
$_SESSION['__registry'] = array();
        }
    }

    private function 
__clone()
    {
    }
    
    public static function 
getInstance()
    {
        if(
self::$instance === null)
        {
            
self::$instance = new SessionRegistry();
        }
        return 
self::$instance;
    }

    public function 
__set($name$value)
    {
        
$_SESSION['__registry'][$name] = $value;
    }
    
    public function 
__get($name)
    {
        if(isset(
$_SESSION['__registry'][$name]))
        {
            return 
$_SESSION['__registry'][$name];            
        }
        return 
null;
    }

    public function 
__isset($name)
    {
        return isset(
$_SESSION['__registry'][$name]);
    }
    
    public function 
__unset($name)
    {
        unset(
$_SESSION['__registry'][$name]);
    }

Um von einer anderen Klasse auf die SessionRegistry zuzugreifen verwende ich im Konstruktor der Klasse
PHP-Code:
$this->SessionRegistry SessionRegistry::getInstance(); 
und im Code dann
PHP-Code:
$this->SessionRegistry->foo $bar 
bzw. dementsprechend auch
PHP-Code:
$foo $this->SessionRegistry->bar 
Mein Problem taucht nun beim schreibenden Zugriff auf (mehrdimensionale) Arrays auf
PHP-Code:
// Aufruf
$this->SessionRegistry->foo['bar'] = $baz
// ergibt
$_SESSION['__registry'][foo['bar']] = $baz
was semantisch Humbug darstellt und in der Registry unter Schlüssel "foo['bar']" das angegebene "$baz" ablegt.

Gibt es hierfür eine elegante Lösung? Leider stehe ich gerade auf dem Schlauch...
Unelegant wäre es das komplette (mehrdimensionale) Array temporär auszulesen, zu modifizieren und wieder komplett zurückzuschreiben a la
PHP-Code:
$temp $this->SessionRegistry->foo;
$temp['bar'] = $baz;
$this->SessionRegistry->foo $temp 
Grüßung und Bedankung
tr8000
tr8000 ist offline   Mit Zitat antworten
Sponsor Mitteilung
PHP Code Flüsterer

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

Alt 06.08.2010, 13:56  
Erfahrener Benutzer
 
Registriert seit: 15.04.2010
Beiträge: 813
PHP-Kenntnisse:
Fortgeschritten
Paul.Schramenko befindet sich auf einem aufstrebenden Ast
Standard

[quote=tr8000;532986]
PHP-Code:
$_SESSION['__registry'][foo['bar']] = $baz
Also das da ist schon ma syntaktisch schlecht, würde notices werfen, weil es kein Konstante ist

Du solltest das ganze mal so probieren:
PHP-Code:
$this->SessionRegistry->foo->bar $baz
Nachtrag:
Hmm wenn ich bissl drüber nachdenke und mich nicht irre, wird das glaube ich doch nicht gehen, da du in der Klasse ein Zuweisung in der Art machst: $session[$name]
Du könntest versuchen mit der evil eval() funktion zu arbeiten, aber davon würde ich eher abraten.
Oder du bastelst dir einen Iterator, der dann für dich an die richtige Stelle das Zeug rein schreibt
__________________
"My software never has bugs, it just develops random features."
"Real programmers don't comment. If it was hard to write, it should be hard to understand!"
Positive Bewertungen sind nicht unwillkommen...

Geändert von Paul.Schramenko (06.08.2010 um 14:05 Uhr).
Paul.Schramenko ist offline   Mit Zitat antworten
Alt 17.08.2010, 13:48  
Erfahrener Benutzer
 
Registriert seit: 17.08.2010
Beiträge: 209
PHP-Kenntnisse:
Fortgeschritten
Dormilich befindet sich auf einem aufstrebenden Ast
Standard

Zitat:
Zitat von tr8000 Beitrag anzeigen
Mein Problem taucht nun beim schreibenden Zugriff auf (mehrdimensionale) Arrays auf
PHP-Code:
// Aufruf
$this->SessionRegistry->foo['bar'] = $baz
// ergibt
$_SESSION['__registry'][foo['bar']] = $baz
was semantisch Humbug darstellt und in der Registry unter Schlüssel "foo['bar']" das angegebene "$baz" ablegt.

Gibt es hierfür eine elegante Lösung? Leider stehe ich gerade auf dem Schlauch...
analog zur Definition eines Arrays:
PHP-Code:
$this->SessionRegistry->foo = array("bar" => $baz); 
Ich sehe für die Anwendung der Klasse (also das trifft eigentlich jede Sessionklasse) noch ein kleines Problem … am Anfang des Skriptes muß die Session initialisiert werden, um die "header already sent" Warnung zu vermeiden (das darf dann natürlich nicht mit dem Klassenkonstruktor kollidieren, eine bereits initialisierte Session darf nicht nocheinmal gestartet werden).

PS. IMHO, es reicht für eine Sessionklasse nach dem Singletonprinzip eine x-beliebige Triggervariable zu speichern. Dazu ist noch nicht einmal das Singleton Pattern notwendig, lediglich Mutatormethoden für diese Variable.

Geändert von Dormilich (17.08.2010 um 14:05 Uhr).
Dormilich ist offline   Mit Zitat antworten
Alt 17.08.2010, 14:06  
fab
Erfahrener Benutzer
 
Benutzerbild von fab
 
Registriert seit: 28.07.2010
Beiträge: 1.721
PHP-Kenntnisse:
Fortgeschritten
fab ist einfach richtig nettfab ist einfach richtig nettfab ist einfach richtig nettfab ist einfach richtig nett
Standard

Was hier passiert, ist dass mit __get das Array $_SESSION['__registry']['foo'] als Kopie (return by value) zurückgegeben und dann modifiziert wird. Eine direkte Modifikation des Arrays ist so nicht möglich, es sei denn man bekäme es hin, __get mit return by reference arbeiten zu lassen, was IIRC nicht möglich ist.

Ein Workaround aus dem PHP-Manual (PHP: Magic Methods - Manual 1. Kommentar):

Zitat:
Properties that are Arrays: attempting to set array values like "$a->test_array[] = 'asdf';" from outside this object will result in an "Indirect modification of overloaded property" notice and the operation completely ignored. You can't use '[]' for array value assignment in this context (with the exception only if you made __get() return by reference, in which case, it would work fine and bypass the __set() method altogether). You can work around this doing something like unioning the array instead:

PHP-Code:
<?php

$a
->test_array[] = 'asdf'// notice given and ignored unless __get() was declared to return by reference
$a->test_array += array(=> 'asdf'); // to add a key/value
$a->test_array = array("key" => 'asdf') + $a->test_array// to overwrite a  key/value.

?>
fab ist offline   Mit Zitat antworten
Alt 22.08.2010, 18:50  
Neuer Benutzer
 
Registriert seit: 22.08.2010
Beiträge: 16
PHP-Kenntnisse:
Fortgeschritten
Murdoc befindet sich auf einem aufstrebenden Ast
Standard

In deinem Fall würde sich ein ArrayAccess lohnen (und die Probleme lösen ):

PHP-Code:
<?php

use ArrayAccess;
use 
Exception;

class 
SessionRegistry implements ArrayAccess
{
    protected static 
$instance null;
    
    protected function 
__construct()
    {
        if(
header_sent())
            throw new 
Exception('zu spät ;)');
            
        if(!
defined('SID') || empty(SID))
            
session_start();
            
        if(!
is_array($_SESSION['__registry']))
            
$_SESSION['__registry'] = array();
    } 
    
    public static function 
getInstance()
    {
        if(
self::$instance === null)
            
self::$instance = new self();
            
        return 
self::$_instance;
    } 
    
    
/**
    * variable zurückgeben
    *
    * @param    scalar      $name
    * @return   mixed
    */
    
public function offsetGet($name)
    {
        return isset(
$_SESSION['__registry'][$name]) 
            ? 
$_SESSION['__registry'][$name]
            : 
null;
    }
    
    
/**
    * variable in session aufnehmen oder überschreiben
    *
    * @param    scalar      $name
    * @param    mixed       $value
    * @return   mixed
    */
    
public function offsetSet($name$value)
    {
        return (
$_SESSION['__registry'][$name] = $value);
    }
    
    
/**
    * prüfen ob variable in session existiert
    *
    * @param    scalar      $name
    * @return   boolean
    */
    
public function offsetExists($name)
    {
        return isset(
$_SESSION['__registry'][$name]);
    }
    
    
/**
    * variable aus session entfernen
    *
    * @param    scalar      $name
    * @void
    */
    
public function offsetUnset($name)
    {
        unset(
$_SESSION['__registry'][$name]);
    }
}
PHP-Code:
$session SessionRegistry::getInstance();
$session['foo'] = array();
$session['foo']['bar'] = 1;

print_r($_SESSION['__registry']) // Array ( [foo] => Array ( [bar] => 1 ) ) 
Murdoc ist offline   Mit Zitat antworten
Alt 22.08.2010, 22:07  
Erfahrener Benutzer
 
Registriert seit: 17.08.2010
Beiträge: 209
PHP-Kenntnisse:
Fortgeschritten
Dormilich befindet sich auf einem aufstrebenden Ast
Standard

Zitat:
Zitat von Murdoc Beitrag anzeigen
In deinem Fall würde sich ein ArrayAccess lohnen
falls die Klasse keine weiteren Methoden haben sollte, könnte man auch wieder zu $_SESSION zurückkehren …
Dormilich ist offline   Mit Zitat antworten
Alt 22.08.2010, 22:28  
Neuer Benutzer
 
Registriert seit: 22.08.2010
Beiträge: 16
PHP-Kenntnisse:
Fortgeschritten
Murdoc befindet sich auf einem aufstrebenden Ast
Standard

Bis auf den Unterschied, dass er mit der Klasse eigene setter und getter für $_SESSION['__registry'] hat. Aber da macht seine Registry-Klasse genauso wenig Sinn, bis auf "->" statt "[]".

Nebenbei sei noch gesagt, dass man in $_SESSION auch Indexe anlegen kann, auf die man nicht über "->" zugreifen kann.
PHP-Code:
// $foo->ein-ungültiger-index
$foo->__get('ein-ungültiger-index'); 
Rein von der Performance her wäre ein direkter Zugriff auf $_SESSION eh besser, oder eben mit einem ArrayObject aus der SPL.

Geändert von Murdoc (22.08.2010 um 22:34 Uhr).
Murdoc ist offline   Mit Zitat antworten
Alt 22.08.2010, 23:16  
moderatives Dielektrikum
 
Benutzerbild von nikosch
 
Registriert seit: 21.05.2008
Beiträge: 34.252
PHP-Kenntnisse:
Fortgeschritten
nikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz sein
Standard

Ich kann die Absicht schon verstehen, es geht quasi um ein Namespacing für bestimmte Variablenbereiche. Das praktische ist, dass man das Zugriffsobjekt via Type Hinting einfordern kann (bzw. die Schnittstelle sicherstellen).

Trotzdem halten sich die Vorteile gegenüber $_SESSION sehr in Grenzen.
__________________
--
One pixel is still too big. Please make it smaller. ASAP.

Initiative Mittelstand.
Die wichtigste Gestaltungsregel im Screendesign ist Pi mal Daumen des Arbeitgebers.
--
nikosch ist gerade online   Mit Zitat antworten
Alt 24.08.2010, 11:58  
Erfahrener Benutzer
 
Registriert seit: 17.08.2010
Beiträge: 209
PHP-Kenntnisse:
Fortgeschritten
Dormilich befindet sich auf einem aufstrebenden Ast
Standard

[obsolet]

Geändert von Dormilich (25.08.2010 um 08:20 Uhr).
Dormilich ist offline   Mit Zitat antworten
Alt 25.08.2010, 00:36  
moderatives Dielektrikum
 
Benutzerbild von nikosch
 
Registriert seit: 21.05.2008
Beiträge: 34.252
PHP-Kenntnisse:
Fortgeschritten
nikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz seinnikosch kann auf vieles stolz sein
Standard

Kleines Update. Ich benutze seit längerem ein ähnliches Konstrukt (sozusagen „namespaced“ assoziierte Session-Teilstrukturen), um definierte Persistenzobjekte an Klassen übergeben zu können.
Nach einigen negativen Erfahrungen in der Vergangenheit hatte ich mich bis dato auf 1-dimensionale Strukturen beschränkt. Zumindest objektseitig. Also:

PHP-Code:
$container = new PersObject ('namespaceMyClass');
$container->store ('foo' 42);
$myClass = new myClass ($container); 
Letztens hatte ich Iterator or IteratorAggregate? - Fabien Potencier gelesen und daraufhin das Objekt damit ausgerüstet. Unproblematisch. Beschränkt sich aber auch nur auf foreach. Eben dachte ich - bauste ArrayAccess auch noch ein. Auch das kein Problem.

PHP-Code:
echo $container['foo'];
$container['bar'] = array (2); 
Und dann lief ich wieder in die alte Geschichte mit mehrdim. Datenstrukturen:

Jeder Set-Versuch der Art
PHP-Code:
$container['bar'][2] = 3
resultiert nämlich schön in:
Code:
Notice: Indirect modification of overloaded element of ... has no effect ... on line 28
Die Bugreports dazu ergehen sich in Geschwafel und Ausreden, warum das so gewollt ist etc. Mein Fazit - solch ein Verhalten ist unlogisch und ArrayAccess praktisch nicht nutzbar. Wer will sich schon auf 1-dimensionale Arrays zwangsbeschränken. Also baue ich den Schrumms gleich wieder aus. Dann bleibts wenigstens konsistent. Den Luxus eines superglobalen Arrays wird man mit Objekten wohl nicht erreichen.
__________________
--
One pixel is still too big. Please make it smaller. ASAP.

Initiative Mittelstand.
Die wichtigste Gestaltungsregel im Screendesign ist Pi mal Daumen des Arbeitgebers.
--

Geändert von nikosch (25.08.2010 um 00:42 Uhr).
nikosch ist gerade online   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
Zwei Arrays zusammenführen chunky PHP Tipps 2010 1 10.07.2010 17:58
[Erledigt] Sortierung mehrerer Arrays philosapiens PHP Tipps 2010 16 08.06.2010 05:22
mehrere Arrays gleichermaßen sortieren maeck PHP Tipps 2010 14 30.03.2010 08:28
Schleifen Problem mit den Arrays - Logikproblem <?PHP//Ahhhja?> PHP Tipps 2010 4 28.03.2010 13:02
Best Practise: Arrays unabhängig vom index zusammenfügen lh_as PHP-Fortgeschrittene 1 16.03.2010 15:47
inhalt eines problem - arrays kürzen bzw. einer variablen zuweisen geuloth PHP Tipps 2010 6 27.02.2010 18:05
[Erledigt] Ausgabe zweier Arrays mit identischen Schlüsseln litterauspirna PHP Tipps 2009 6 13.12.2009 20:35
[Erledigt] Mehere Arrays und nur 2 Werte aus jedem auslesen litterauspirna PHP Tipps 2009 3 07.05.2009 20:30
[Erledigt] Sortieren von Arrays Roflkid PHP-Fortgeschrittene 10 06.05.2009 22:48
Mehrere Arrays summieren buggybugga PHP-Fortgeschrittene 8 22.07.2008 11:51
Arrays sortieren, Bezeichnung, Preis Ticos PHP Tipps 2006 4 07.09.2006 19:37
[Erledigt] 2 Arrays miteinander vergleichen PHP Tipps 2007 3 17.12.2005 16:54
Problem beim vergleichen von 2 Arrays PHP Tipps 2005-2 1 06.10.2005 14:25
Erkennung von Arrays in Strings PHP-Fortgeschrittene 15 07.12.2004 13:00
Werte eines Arrays in eine MySQL schreiben PHP Tipps 2004 2 28.06.2004 13:32

Besucher kamen über folgende Suchanfragen bei Google auf diese Seite
php mehrdimensionales array performance, php array overloading, \indirect modification of overloaded element of\, indirect modification of overloaded property, php zugriff auf mehrdimensionales array, magic __get mehrdimensionale arrays -ebay -test -testberichte -shop -preisvergleich, notice: indirect modification of overloaded property session, empty sessionregistry, php overloading, mehrdimensionale arrays klassen php, indirect modification of overloaded property session::$user has no effect, return zweidimensionales array, php \indirect modification of overloaded property\ \has no effect\ array, php offsetget returns array indirect modification element, php mehrdimensionales array public, overload array php, public static function array php, registry class ohne session php, php array overload, php multidimensional array mit variable zusammensetzen

Alle Zeitangaben in WEZ +1. Es ist jetzt 18:12 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