2011-01-04 1 views
0

Внутри класса у меня есть три массива (в качестве переменных экземпляра), которые должны указывать на одни и те же объекты. Первый - это числовой индексный массив, который я возвращаю из некоторой внешней функции. Второй массив должен индексировать одни и те же объекты по их имени. Третье по другому свойству. Это для быстрого доступа через эти свойства. Итак, дело в том, что не имеет значения, какой массив я использую для доступа к объекту и его изменения.Как сделать по-разному индексированные массивы PHP указывать на одни и те же объекты

Однако это не может произойти. Я знаю о ссылках на PHP. Я знаю о ссылках на Java. Я знаю о указателях C, но я не могу этого сделать - везде, где я пытаюсь разместить амперсанд (= &).

class xxx { 

    private $objs; 
    private $objsByName; 

    public function __construct() { 

    $this->objs = getObjs(); 
    $this->objsByName = array(); 
    foreach($this->objs as $obj) { 
     $this->objsByName[$obj->getName()] = $obj; 
    } 
    } 

} 

Там нет места здесь, где я не пробовал заменить = с = &

Я что-то не хватает?

+0

Добро пожаловать в StackOverflow. Вы можете форматировать исходный код с помощью кнопки '{}' панели инструментов (я сделал это для вас на этот раз). Не забудьте отметить как * Accepted * лучший ответ, который решает вашу проблему. –

ответ

0

Замените петлю foreach на эту.

for($i = 0 , $n = count($this->objs); $i < $n ; $i ++){ 

$this->objsByName[$this->objs[$i]->getName()] = &$this->objs[$i]; 

} 

Это позволит решить вашу проблему :)

Спасибо!

Hussain.

0

В PHP объекты всегда передаются по ссылке (you cannot copy an object unless you use clone keyword). Этот код иллюстрирует это:

<?php 

class AnObject{ 
    private $name; 
    public $count=0; 

    public function __construct($name){ 
     $this->name = $name; 
    } 

    public function getName(){ 
     return $this->name; 
    } 
} 

function getObjs(){ 
    return array(
     new AnObject('One'), 
     new AnObject('Two'), 
     new AnObject('Three'), 
    ); 
} 


class xxx { 

    private $objs; 
    private $objsByName; 

    public function __construct() { 

    $this->objs = getObjs(); 
    $this->objsByName = array(); 
    foreach($this->objs as $obj) { 
     $this->objsByName[$obj->getName()] = $obj; 
    } 
    } 

    public function alterAnObjectByName($name){ 
     $this->objsByName[$name]->count++; 
    } 

} 

$x = new xxx; 
var_dump($x); 
$x->alterAnObjectByName('Two'); 
var_dump($x); 

Проблема, вероятно, в другом месте.

0

Отметить эту часть из руководства PHP: http://php.net/manual/en/control-structures.foreach.php

Если не ссылается массив, Еогеасп работает на копии указанного массива, а не сам массив. foreach имеет некоторые побочные эффекты для указателя массива. Не полагайтесь на указатель массива во время или после foreach, не перезагружая его.

Таким образом, ваш $ obj является копией.

Я не тестировал код Хусейна, но это выглядит как хороший вариант :)

0

PHP всегда использовать копию на функции записи, есть вероятность, что ваши объекты будут такими же, пока не будет изменен.

Чтобы избежать ошибок, вы должны сказать, что один из ваших массивов содержит данные, а другие - только индексы.

Используйте индекс, чтобы найти идентификатор, и используйте массив данных, индексированный по id, для чтения и изменения данных.

0

В PHP5 вы можете добавить & переменной as, чтобы сделать цикл Еогеасп не клонировать объект:

foreach($this->objs as &$obj) { 
    $this->objsByName[$obj->getName()] = &$obj; 
} 

Ссылка: http://php.net/manual/en/control-structures.foreach.php

р/с: Я не уверен, если & внутри тела foreach необходимо или нет, а просто добавьте его в безопасное место. Или вы можете попробовать удалить его, чтобы убедиться, что это необходимо или нет.

Смежные вопросы