Package home | Report new bug | New search | Development Roadmap Status: Open | Feedback | All | Closed Since Version 1.11.5

Bug #11775 DB_DATAOBJECT_ERROR_NODATA on update due to DB_DataObject.php:615
Submitted: 2007-08-06 18:12 UTC
From: cuppett Assigned: alan_k
Status: Closed Package: DB_DataObject (version 1.8.7)
PHP Version: 5.2.3 OS: Windows and Linux
Roadmaps: (Not assigned)    
Subscription  


 [2007-08-06 18:12 UTC] cuppett (Stephen Cuppett)
Description: ------------ For whatever reason, I can see that PHP 5.x still has problems modifying or setting indirect class variables that are arrays wherein only particular keys of the array are being updated. There are several indications that immutable behavior for arrays is desired, some indication it has been fixed, etc. However, from what I can tell, in 5.2.3 on both Windows and Linux, they are still being treated immutable. For this reason, I'm submitting a patch that will work around this behavior in the whereAdd function of DB_DataObject. This patch retains all the original with the added benefit a temporary _query variable is used/altered and they copied back to $this->_query before returning. This works around the broken behavior and has no effect on normal behavior. Test script: --------------- <?php require("DB.php"); $dsn = array ( 'phptype' => 'pgsql', 'protocol' => 'tcp', 'hostspec' => 'localhost', 'database' => 'test', 'username' => 'test', 'password' => 'test' ); define('DB_DATAOBJECT_NO_OVERLOAD',0); $options = &PEAR::getStaticProperty('DB_DataObject','options'); $options = array( 'database' => $dsn, /* 'require_prefix' => dirname(__FILE__) . '/dataobjects/', */ 'class_prefix' => 'DataObject_', /* 'class_location' => dirname(__FILE__) . '/dataobjects/DataObject_%s.php', */ 'quote_identifiers' => '1' ); require("DB/DataObject.php"); DB_DataObject::debugLevel(5); // Turns on full debugging of SQL generated and results. abstract class WMI_DataObject extends DB_DataObject { private $map; public function __construct() { $this->map = array(); } public function __get($vn) { return ($this->map[$vn]); } public function __set($vn, $value) { $this->map[$vn] = $value; } public function __isset($vn) { return array_key_exists($vn, $this->map); } } class DataObject_Host extends WMI_DataObject { public $__table='hosts'; public function __construct() { parent::__construct(); } /* Static get */ public function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('DataObject_Host',$k,$v); } public function table() { return array( 'id' => DB_DATAOBJECT_INT, 'hostname' => DB_DATAOBJECT_STR, 'display_name'=> DB_DATAOBJECT_STR, 'ip_addr' => DB_DATAOBJECT_STR, ); } public function keys() { return array('id'); } } // Running my test. $host = DB_DataObject::factory("Host"); $host->id = 2; if ($host->find(true)) { $host->ip_addr = "4.4.4.4"; echo $host->update(); } ?> Expected result: ---------------- The update should occur without any problems. The WHERE clause should get generated as WHERE "host"."id" = 2 However, because of the error on 615, this is not getting set and the query fails. Actual result: -------------- I receive the following in the trace: Notice: Undefined index: test in C:\php\PEAR\DB\DataObject.php on line 2023 DataObject_Host : 3 : got keys as a:1:{i:0;s:2:"id";} Notice: Indirect modification of overloaded property DataObject_Host::$_query ha s no effect in C:\php\PEAR\DB\DataObject.php on line 615 DataObject_Host : ERROR : update: No Data specifed for query "hostname" = 'test2.cuppett.com' , "display_name" = 'my other testing host' , "ip_addr" = ' 4.4.4.4' ,

Comments

 [2007-08-07 06:27 UTC] alan_k (Alan Knowles)
can you try 5.3.4rc1 http://qa.php.net/ The correct workaround for this is to disable overloading for that version of PHP... - And probably updating the warning on the main doc's page..
 [2007-08-07 12:00 UTC] cuppett (Stephen Cuppett)
With 5.2.4RC1, it's the same: PHP Notice: Undefined index: test in C:\php\PEAR\DB\DataObject.php on line 202 3 Notice: Undefined index: test in C:\php\PEAR\DB\DataObject.php on line 2023 DataObject_Host : 3 : got keys as a:1:{i:0;s:2:"id";} PHP Notice: Indirect modification of overloaded property DataObject_Host::$_que ry has no effect in C:\php\PEAR\DB\DataObject.php on line 615 Notice: Indirect modification of overloaded property DataObject_Host::$_query ha s no effect in C:\php\PEAR\DB\DataObject.php on line 615 DataObject_Host : ERROR : update: No Data specifed for query "hostname" = 'test2.cuppett.com' , "display_name" = 'my other testing host' , "ip_addr" = ' 4.4.4.6' , C:\temp\dataobject_test>php -version PHP 5.2.4RC1 (cli) (built: Aug 2 2007 23:50:17) Copyright (c) 1997-2007 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies
 [2007-08-07 12:05 UTC] cuppett (Stephen Cuppett)
For easy recreate, here is the database schema (pgsql): CREATE TABLE hosts ( id bigserial NOT NULL, hostname character varying(50) NOT NULL, display_name character varying(100), ip_addr inet NOT NULL ); INSERT INTO hosts (id, hostname, display_name, ip_addr) VALUES (1, 'test.cuppett.com', 'my testing hosts', '24.24.24.24'); INSERT INTO hosts (id, hostname, display_name, ip_addr) VALUES (2, 'test2.cuppett.com', 'my other testing host', '4.4.4.4'); ALTER TABLE ONLY hosts ADD CONSTRAINT hosts_pkey PRIMARY KEY (id);
 [2007-08-07 12:09 UTC] cuppett (Stephen Cuppett)
It's probably pretty obvious, but since the overloading of _query is what the problem is, delete() and other functions are effected as well.
 [2007-08-07 16:09 UTC] alan_k (Alan Knowles)
have you managed to reproduce the PHP bug without DataObjects eg. with a simple bit of code? - That needs filing at bugs.php.net.. I think this bug needs leaving open - and the patch available as a workaround - but I dont think it should go into the release.
 [2007-08-07 16:19 UTC] cuppett (Stephen Cuppett)
Yes. This can be recreated in it's simplest form: <?php class MyObj { private $map; public function __construct() { $this->map = array(); } public function __set($vn, $value) { $this->map[$vn] = $value; } public function __get($vn) { return $this->map[$vn]; } } $myvar = new MyObj(); $myvar->test_var = array(); $myvar->test_var['tester'] = 3; $myvar->test_var['tester2'] = 5; var_dump($myvar->test_var); ?> With output: C:\temp\dataobject_test>php simpletest.php PHP Notice: Indirect modification of overloaded property MyObj::$test_var has no effect in C:\temp\dataobject_test\simpletest.php on line 16 Notice: Indirect modification of overloaded property MyObj::$test_var has no effect in C:\temp\dataobject_test\simpletest.php on line 16 PHP Notice: Indirect modification of overloaded property MyObj::$test_var has no effect in C:\temp\dataobject_test\simpletest.php on line 17 Notice: Indirect modification of overloaded property MyObj::$test_var has no effect in C:\temp\dataobject_test\simpletest.php on line 17 array(0) { }
 [2007-08-07 16:27 UTC] cuppett (Stephen Cuppett)
 [2007-08-07 16:31 UTC] alan_k (Alan Knowles)
Actually, that's expected behaviour. I guess what is happening is: fetch() calls unset().. on $this->_query, when it's fetched all the data. - hence leading to the error's you are seeing. I think the correct fix is probably to change the unset/isset calls to use false... - although I'm suprised this bug has not cropped up before, the whereAdd check for $_query should completely break your example code.
 [2007-08-07 16:35 UTC] alan_k (Alan Knowles)
Spoke to soon... - It's not quite as critical as I thought - build_condition actually resets $this->_query. But I think moving to a false // === false model for $_query would be more stable anyway.
 [2007-08-08 03:42 UTC] alan_k (Alan Knowles)
Can you test CVS - http://cvs.php.net/viewvc.cgi/pear/DB_DataObject/DataObject.php?revision=1.433 I've remove the unset and isset calls and replaced them with === false tests.
 [2007-08-08 16:30 UTC] cuppett (Stephen Cuppett)
Sure, I'll give it a try tonight or tomorrow morning EST
 [2007-08-09 14:49 UTC] cuppett (Stephen Cuppett)
This new file seemed to work just fine. Hope this has helped! Now I just hope the fix the root problem with PHP.
 [2007-08-10 03:37 UTC] alan_k (Alan Knowles)
This bug has been fixed in CVS. If this was a documentation problem, the fix will appear on pear.php.net by the end of next Sunday (CET). If this was a problem with the pear.php.net website, the change should be live shortly. Otherwise, the fix will appear in the package's next release. Thank you for the report and for helping us make PEAR better. Thanks for testing it. Regards Alan