Closed diegocpires closed 10 years ago
I don't believe protected nor private visibility is supported, what do you think of that and how you solved your problem?
Pascutti,
Now i don't have much time to change the "core" of Relational, anyway i changed the properties to public and, go horse. =P
When i deploy the first version of the system, i look a solution for this.
@diegocpires private properties are accessible only using methods from convention styles. It cannot read from set and get.
This should work:
<?php
namespace MyApplication;
class Post
{
public $id;
private $name;
public function setName($name)
{
$this->name = $name;
}
public function getName()
{
return $name;
}
}
$mapper = new \Respect\Relational\Mapper($myPDOInstance);
$mapper->entityNamespace = '\\MyApplication\\';
$newPost = new Post;
$newPost->setName("Example Post");
$mapper->persist($newPost);
$mapper->flush();
The id
property has a problem, though. The current implementation requires it to be public in order to work. It shouldn't be hard to change it here and here to use the inferSet
method that figures out which setter to use.
I'm reopening this, it may be a quick fix.
@alganet Weird... I'm using magic method __call, to not declare every getter and setter.
But, declaring the getters and setters still not working! The registry in database is created, but values are null.
My "GenericMapper"
<?php
namespace ProCorpo\CRM\Mapper;
use Respect\Relational\Sql;
use Respect\Config\Container;
use Respect\Relational\Db;
abstract class GenericMapper {
public $conexao;
protected $c;
protected $db;
protected static $instances;
public function __construct() {
$this->c = new Container(CONFIG_DIR . '/config.ini');
$this->conexao = $this->c->mapper;
$this->conexao->entityNamespace = '\\ProCorpo\\CRM\\Model\\';
$this->db = new DB($this->c->pdo);
}
My "GenericModel"
<?php
namespace ProCorpo\CRM\Model;
use ProCorpo\CRM\Helper\Formatters as f;
abstract class GenericModel {
protected $mapper;
public function __construct()
{
$this->mapper = \ProCorpo\CRM\Mapper\Factory::getInstance($this->nomeEntidade);
}
public function __call($nome, $argumentos)
{
if(substr($nome, 0, 3) == "get")
{
$nomePropriedade = substr($nome, 3);
return $this->getMagico($nomePropriedade, $argumentos);
}
if(substr($nome, 0, 3) == "set")
{
$nomePropriedade = substr($nome, 3);
return $this->setMagico($nomePropriedade, $argumentos);
}
throw new Exception("Método não existe", 1);
}
protected function getMagico($nome, $argumentos)
{
$nomePropriedade = \ProCorpo\CRM\Helper\Formatters::fromCamelCase($nome);
if(property_exists(self::nomeClasse(), $nomePropriedade)) {
return $this->{$nomePropriedade};
}
}
My "BancoModel"
<?php
namespace ProCorpo\CRM\Model;
use ProCorpo\CRM\Helper\Formatters as f;
class Banco extends GenericModel {
protected $unidade_id, $nome, $valor;
public $id;
public function setNome($nome) {
$this->nome = $nome;
}
public function getNome() {
return $this->nome;
}
I'll look at these two points you mentioned to try to fix it.
@alganet @augustohp
I made changes in method extractColums
for tests. Aparently change only this method works, at least in my case works.
I'm not sure this is correct or this is the best approach , but, again, in my case works.
I'm catching only protected and public properties.
protected function extractColumns($entity, Collection $collection)
{
$primaryName = $this->getStyle()->identifier($collection->getName());
$nameClass = get_class($entity);
$reflect = new \ReflectionClass($nameClass);
$props = $reflect->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED);
$cols = array();
foreach($props as $prop) {
$nameCamelCase = "get".f::toCamelCase($prop->name);
if(is_callable(array($entity, $nameCamelCase))) {
$valueField = $entity->$nameCamelCase();
} else {
$valueField = $entity->{$prop->name};
}
$cols[$prop->name] = $valueField;
}
foreach ($cols as &$c) {
if (is_object($c)) {
$c = $c->{$primaryName};
}
}
return $cols;
}
@diegocpires @alganet what do you think in use \ReflectionProperty::setAccessible()?
protected function extractColumns($entity, Collection $collection)
{
$primaryName = $this->getStyle()->identifier($collection->getName());
$reflect = new \ReflectionClass($entity);
$props = $reflect->getProperties(
\ReflectionProperty::IS_PUBLIC
| \ReflectionProperty::IS_PROTECTED
| \ReflectionProperty::IS_PRIVATE
);
$cols = array();
foreach($props as $prop) {
if (!$prop->isPublic()) $prop->setAccessible(true);
$value = $prop->getValue($entity);
$cols[$prop->name] = is_object($value) ? $value->{$primaryName} : $value;
}
return $cols;
}
now in Mapper::tryHydration(); you can use the ReflectionProperty::setValue($instance, $value); To you use private property like PDOStatment::fetch(); do in fetch class mode.
Sorry for a lot of commits! I was working on two projects and I wrong terminal. So, I rebase and pull the relational instead of other.
But the last commit is right. https://github.com/felipecwb/Relational/commit/618637be27aad4c069bb9c745cfd9e94ea2df4c2
@diegocpires any more about that? This issue can be closed?
For me is perfect.
Thanks to all for the support. And for @felipecwb for the wonderful job. =D
Hi!
Im working with Entity Class using for reference this manual section https://github.com/Respect/Relational#entity-classes.
My code is working ok, except one item.
When i use protected properties in classes, this properties not persist in the database. I'm looking in the source code of Relational and i really not understand why this "columns" are not persist. (In time, i'm using magic methods for call, get, isset and set).
Anyone works with protected properties and Entity Classes to help me in a solution?