2010-08-30 9 views
10

Gibt es eine Möglichkeit, eine schreibgeschützte Eigenschaft eines Objekts in PHP zu erstellen? Ich habe ein Objekt mit ein paar Arrays drin. Ich möchte auf sie zuzugreifen, wie ich normalerweise würde ein Arrayschreibgeschützte Eigenschaften in PHP?

echo $objObject->arrArray[0]; 

Ich will aber nicht auf diese Arrays schreiben können, nachdem sie aufgebaut sind. Es fühlt sich an wie ein PITA eine lokale Variable zu konstruieren:

$arrArray = $objObject->getArray1(); 
echo $arrArray[0]; 

Und sowieso, während es das Array in dem Objekt ursprünglich hält, es hindert mich nicht aus dem lokalen Array-Variable neu zu schreiben.

Antwort

25

Nun, die Frage ist, wo möchten Sie das Schreiben verhindern?

Der erste Schritt macht das Array geschützt oder private Schreiben von außerhalb des Objekts Umfang zu verhindern:

protected $arrArray = array(); 

Wenn von „außen“ des Arrays, ein Getter Sie gut tun wird. Entweder:

public function getArray() { return $this->arrArray; } 

und den Zugriff auf sie wie

$array = $obj->getArray(); 

oder

public function __get($name) { 
    return isset($this->$name) ? $this->$name : null; 
} 

und den Zugriff auf sie mag:

$array = $obj->arrArray; 

Hinweis, dass sie keine Referenzen zurück. Sie können also das ursprüngliche Array nicht außerhalb des Bereichs des Objekts ändern. Sie können das Array selbst ändern ...

Wenn Sie wirklich ein vollständig unveränderbares Array benötigen, können Sie ein Objekt verwenden, das ArrayAccess verwendet ...

Oder könnten Sie einfach ArrayObject erweitern und all die Schreibmethoden überschreiben:

class ImmutableArrayObject extends ArrayObject { 
    public function append($value) { 
     throw new LogicException('Attempting to write to an immutable array'); 
    } 
    public function exchangeArray($input) { 
     throw new LogicException('Attempting to write to an immutable array'); 
    } 
    public function offsetSet($index, $newval) { 
     throw new LogicException('Attempting to write to an immutable array'); 
    } 
    public function offsetUnset($index) { 
     throw new LogicException('Attempting to write to an immutable array'); 
    } 
} 

Dann einfach $this->arrArray eine Instanz des Objekts machen:

public function __construct(array $input) { 
    $this->arrArray = new ImmutableArrayObject($input); 
} 

Es unterstützt nach wie vor die meisten Array wie Verwendungen:

count($this->arrArray); 
echo $this->arrArray[0]; 
foreach ($this->arrArray as $key => $value) {} 

Aber wenn Sie es versuchen um es zu schreiben, werden Sie

Oh, ein LogicException ... hat aber erkennen, dass, wenn Sie es schreiben müssen, alles, was Sie tun müssen, (innerhalb des Objekts) ist tun:

$newArray = $this->arrArray->getArrayCopy(); 
//Edit array here 
$this->arrArray = new ImmutableArrayObject($newArray); 
+0

Wenn ich mein unveränderliches Array haben möchte Laden Sie sich mit Daten zur Erstellung Ich würde die __construct-Funktion überschreiben, rufen Sie den übergeordneten Konstruktor, aber wie setze ich was das Objekt enthält? –

+0

Sehr gute Antwort! Beachten Sie jedoch, dass ein Array Objekte enthalten kann: Jedes Objekt wird als Referenz zurückgegeben und kann sogar mit Ihrer unveränderlichen Klasse geändert werden: '$ a = new ImmutableArrayObject ((object) ['foo' => 'bar')); $ b = $ a [0]; $ b-> foo = 'geändert'; ' – Philipp

3

Wenn Sie PHP 5+ verwenden, können Sie dies mit __set() und __get() Methoden tun.

Sie müssen definieren, wie sie funktionieren, sollten aber genau dies tun.

Bearbeiten Sie ein Beispiel wäre wie folgt.

class Example { 
    private $var; 
    public function __get($v) { 
     if (is_array($v)) { 
      foreach() { 
       // handle it here 
      } 
     } else { 
      return $this->$v; 
     } 
    } 
} 

Dies könnte nicht der „beste“ sein Weg, es zu tun, aber es wird je nach Arbeit, was Sie

+3

Boss: "ich dachte, Sie sagten, Sie Ihren Algorithmus beendet" Kunde: "Ich habe Chef, was ist das Problem" Boss: "Es funktioniert nicht" Client: "es funktioniert, je nachdem, was Sie brauchen" – Chris

+1

@Chris warum nimmt der Kunde Bestellungen vom Chef? Lol. –

4

brauchen die magischen Funktionen __get() und __set() werden Falls definiert, genannt werden, wenn ein nicht vorhandene oder auf Privateigentum zugegriffen wird. Dies kann verwendet werden, um "get" - und "set" -Methoden für private Eigenschaften zu erstellen und sie beispielsweise schreibgeschützt zu machen oder die Daten zu manipulieren, wenn sie darin gespeichert oder abgerufen werden.

Zum Beispiel:

class Foo 
{ 
    private $bar = 0; 
    public $baz = 4; // Public properties will not be affected by __get() or __set() 
    public function __get($name) 
    { 
    if($name == 'bar') 
     return $this->bar; 
    else 
     return null; 
    } 
    public function __set($name, $value) 
    { 
    // ignore, since Foo::bar is read-only 
    } 
} 

$myobj = new Foo(); 
echo $foo->bar; // Output is "0" 
$foo->bar = 5; 
echo $foo->bar; // Output is still "0", since the variable is read-only 

Siehe auch die manual page for overloading in PHP.

+3

Ich würde empfehlen, eine Ausnahme in 'set' zu werfen, wenn Sie nicht zulassen, dass eine bestimmte Variable gesetzt wird. Der Grund ist, dass es sonst ziemlich verwirrend sein kann, wenn jemand Neues etwas tun muss und es nicht funktioniert. "Aber ich setze dieses Array, um diese Variable aufzunehmen. Die Zuweisung ist erfolgreich, also warum funktioniert das * # @ $ nicht?" ... – ircmaxell

+0

@ircmaxell: guter Punkt ... – Frxstrem

0

dies in der Klasse tun:

private $array; 

function set_array($value) { 
    $this->array = $value; 
} 

dann nur Sie wie folgt festgelegt:

$obj->set_array($new_array);