Closed tontof closed 7 years ago
Try defining the id property in the Blog class
The PHP Notice is removed, but the problem persists as it does not associate the id to the defined blog object.
These tests pass
public function testResultClassPrivateProperties() {
$this->populateBlogs();
$blogs = new \Maphper\Maphper($this->getDataSource('blog', 'id'), ['resultClass' => 'BlogPrivate']);
$blog = $blogs[2];
$this->assertInstanceOf('BlogPrivate', $blog);
$this->assertEquals('blog number 2', $blog->getTitle());
}
public function testResultClassPrivatePropertiesWrite() {
$this->populateBlogs();
$blogs = new \Maphper\Maphper($this->getDataSource('blog', 'id'), ['resultClass' => 'BlogPrivate']);
$blog = $blogs[2];
$blog->setTitle('Title Updated');
$blogs[] = $blog;
//Reload the mapper to ensure no cacheing is used
unset($blogs);
unset($blog);
$blogs = new \Maphper\Maphper($this->getDataSource('blog', 'id'), ['resultClass' => 'BlogPrivate']);
$blog = $blogs[2];
$this->assertEquals('Title Updated', $blog->getTitle());
}
I don't think your pasted tests are linked with the problem. The correct one is:
public function testResultClassPrivatePropertiesWriteWhenUpdating() {
$this->dropTable('blog');
$blogs = new \Maphper\Maphper($this->getDataSource('blog', 'id', ['editmode' => true]), ['resultClass' => 'Blog']);
$blog = new Blog();
$blog->title = 'My Blog Title';
$blog->content = 'This is my first blog entry';
//Store the blog using the next available ID
$blogs[] = $blog;
$this->assertEquals(1, $blog->id);
}
Anyway, it works great now ! Thanks
Oups, it works better, but it does not work correctly with sqlite
$pdo = new PDO('sqlite:memory');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$blogSource = new \Maphper\DataSource\Database($pdo, 'blog', 'id', ['editmode' => true]);
$blogs = new \Maphper\Maphper($blogSource, ['resultClass' => 'Blog']);
$blog = new Blog;
$blog->title = 'My Blog Title';
$blog->content = 'This is my first blog entry';
//Store the blog using the next available ID
$blogs[] = $blog;
var_dump($blog);
gives
class Blog#19 (3) {
public $id =>
NULL
public $title =>
string(13) "My Blog Title"
public $content =>
string(27) "This is my first blog entry"
}
So the id property is now created correcly, but its value is NULL
(same behaviour using $pdo = new PDO('sqlite:./test.db');
My bads, it works if the $id property is not defined in class
class Blog {
// public $id;
}
$pdo = new PDO('sqlite::memory:');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$blogSource = new \Maphper\DataSource\Database($pdo, 'blog', 'id', ['editmode' => true]);
$blogs = new \Maphper\Maphper($blogSource, ['resultClass' => 'Blog']);
$blog = new Blog;
$blog->title = 'My Blog Title';
$blog->content = 'This is my first blog entry';
//Store the blog using the next available ID
$blogs[] = $blog;
var_dump($blog);
Works correcty
class Blog#9 (3) {
public $title =>
string(13) "My Blog Title"
public $content =>
string(27) "This is my first blog entry"
public $id =>
string(1) "1"
}
But
class Blog {
public $id;
}
$pdo = new PDO('sqlite::memory:');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$blogSource = new \Maphper\DataSource\Database($pdo, 'blog', 'id', ['editmode' => true]);
$blogs = new \Maphper\Maphper($blogSource, ['resultClass' => 'Blog']);
$blog = new Blog;
$blog->title = 'My Blog Title';
$blog->content = 'This is my first blog entry';
//Store the blog using the next available ID
$blogs[] = $blog;
var_dump($blog);
gives
class Blog#9 (3) {
public $id =>
NULL
public $title =>
string(13) "My Blog Title"
public $content =>
string(27) "This is my first blog entry"
}
which is quite unexpected, even if for me that's not really a problem as I do not defined the $id property !
Just in case. Adding $valueCopy->{$pk[0]} = $value->{$pk[0]};
to the offsetSet method seems to correct this problem.
public function offsetSet($offset, $valueObj) {
if ($valueObj instanceof \Maphper\Relation) throw new \Exception();
//Extract private properties from the object
$propertyReader = new \Maphper\Lib\VisibilityOverride();
$value = $propertyReader->getProperties($valueObj);
$value = $this->processFilters($value);
$pk = $this->dataSource->getPrimaryKey();
if ($offset !== null) $value->{$pk[0]} = $offset;
$valueCopy = clone $value;
$value = $this->wrap($value);
$this->dataSource->save($value);
$valueCopy->{$pk[0]} = $value->{$pk[0]}; // Added line !
$value = $this->wrap((object) array_merge((array)$value, (array)$valueCopy));
$this->createNew($value, $valueObj);
}
edit: maybe with adding a test if (is_null($offset))
As in README
it works
But if I use
resultClass
I've got
PHP Notice: Undefined property: Blog::$id
I guess it's because of the createNew method from maphper that does not handle stdClass the same way. If this is the expected behaviour, then i guess it should be warn in the README or maybe I'm wrong ?