Php 将对象传递到方法中,将该对象分配给另一个对象,传入对象仍然是我传入的同一个对象
我在我的数据映射器中实现了一个小IdentityMap,它可以正确地工作,因为它知道是否已经加载了一个对象,但是它没有正确地分配内存中的对象 我已经尽可能地将代码简化为一个实体,没有数据库等。有人能解释一下为什么在lookup()方法中没有正确地将已经加载的客户对象分配给传入的客户对象吗 Customer.phpPhp 将对象传递到方法中,将该对象分配给另一个对象,传入对象仍然是我传入的同一个对象,php,oop,Php,Oop,我在我的数据映射器中实现了一个小IdentityMap,它可以正确地工作,因为它知道是否已经加载了一个对象,但是它没有正确地分配内存中的对象 我已经尽可能地将代码简化为一个实体,没有数据库等。有人能解释一下为什么在lookup()方法中没有正确地将已经加载的客户对象分配给传入的客户对象吗 Customer.php class Customer { private $id; private $name; public function getId() {
class Customer {
private $id;
private $name;
public function getId() {
return $this->id;
}
public function setId($id) {
$this->id = $id;
}
public function getName() {
return $this->name;
}
public function setName($name) {
$this->name = $name;
}
}
class IdentityMap {
private $customers;
public function lookup(Customer $customer) {
if( !array_key_exists($customer->getId(), $this->customers) ) {
return false;
}
$customer = $this->customers[$customer->getId()]; //Something wrong here?
return true;
}
public function add(Customer $customer) {
$this->customers[$customer->getId()] = $customer;
}
}
CustomerMapper
class CustomerMapper {
private $identityMap;
public function __construct(IdentityMap $identityMap) {
$this->identityMap = $identityMap;
}
public function fetch(Customer $customer) {
if( $this->identityMap->lookup($customer) ) {
return true;
}
$this->assign($customer, array('id' => 1, 'name' => 'John'));
}
private function assign(Customer $customer, Array $row) {
$customer->setId($row['id']);
$customer->setName($row['name']);
$this->identityMap->add($customer);
}
}
IdentityMap
class Customer {
private $id;
private $name;
public function getId() {
return $this->id;
}
public function setId($id) {
$this->id = $id;
}
public function getName() {
return $this->name;
}
public function setName($name) {
$this->name = $name;
}
}
class IdentityMap {
private $customers;
public function lookup(Customer $customer) {
if( !array_key_exists($customer->getId(), $this->customers) ) {
return false;
}
$customer = $this->customers[$customer->getId()]; //Something wrong here?
return true;
}
public function add(Customer $customer) {
$this->customers[$customer->getId()] = $customer;
}
}
当我运行此命令时:
$identityMap = new IdentityMap();
$customerMapper = new CustomerMapper($identityMap);
for( $i = 0; $i < 3; $i++ ){
$customer = new Customer();
$customer->setId(1);
$customerMapper->fetch($customer);
echo 'ID: ' . $customer->getId() . '<br>Name: ' . $customer->getName() . '<br><br>';
}
ID: 1
Name: John
ID: 1
Name:
ID: 1
Name:
为什么第二个和第三个客户对象没有名称?我相当肯定lookup()方法中的赋值部分存在问题。从昨晚开始,我就一直在做这件事,试着阅读所有的东西
我已将lookup()方法签名更改为在传入的对象前面有“&”符号,但运气不佳。您正在使用相同的密钥(id)向查找中添加3个客户 在第一次for循环运行之后,对于for循环的其余运行,fetch方法返回true。 所以这个名字永远不会被设定 你可以试试这个:
if( $this->identityMap->lookup($customer) ) {
return $this->identityMap->get($customer);
}
但是不要忘记在IdentityMap类中实现方法“get;” 问题是
当在第一个循环中调用fetch()并依次调用lookup()时,它将找不到任何值(因为identityMap为空),因此$customer将在assign()中被赋予新值(在本例中,$customer->name='John'和$customer->id='1')。这里注意,$customer->setId(1)不提供id代码>。无论您给出什么值,$this->assign()
都会通过将id值指定给1来修改$customer的原始id值(通过引用传递)。您可以通过将1更改为任意值来测试它(顺便说一句,如果您将1更改为3,您将看到所有结果)
因此,在第一个循环中,$customer填充了所有要正确显示的值(id->1和name->john)
但是在第二个循环中
if( $this->identityMap->lookup($customer) ) {
return true;
}
返回true。(id=1的customer对象位于$identityMap中;因此它不会修改作为参数传递的$customer对象。)
这意味着,函数在将name值分配给$customer之前返回
从第二个循环开始
for( $i = 0; $i < 3; $i++ ){
...
$customer->setId(1);
...
}
我们必须更深入。就像一个对象概念!试试这个,public function lookup(Customer&$Customer)
,这样它就可以通过引用而不是通过值来传递。@MichaelPerrenoud试过了,但没有成功。还有其他建议吗?这在理论上应该行得通,不是吗?我不知道出了什么问题。我不是因为在下次运行fetch()时添加了ID=1的客户后,它会找到ID=1的客户并返回true。为什么不显示名称?这是问题的一部分。因为您没有从查找中加载数据。您只需返回true,就可以得到一个只设置了id的customer对象。在您的第一次for循环迭代中,$this->identityMap->lookup($customer)返回false并设置名称。在第二个迭代中,$this->identityMap->lookup($customer)返回true,您不设置名称,因为如果lookup()方法返回true,则应该将传入的客户对象设置为现在指向ID=1的内存中已存在的客户对象。但这似乎不起作用。谢谢你的回复。我现在让fetch()方法返回对象,而不是只返回true或false。