Is it possible to modify methods of an object instance using reflection
Asked Answered
B

2

3

What I'm trying to do is create a domain model with a Plain Old PHP Object. The I'm creating a library which will do all the infrastructure stuff. So one of my models looks like this

class Project {
  public $id;
  public $name;
  public $typeId;

  private $type;

  public function getType() {
    return $this->type;
  }

  public function setType(Type $type) {
    $this->typeId = $type->id;
    $this->type = $type;
  }
}

Now if create a new Project and call setType with a valid Type object and save the project instance using the ORM both the project and type is saved. But then I load the Project and use getType method I want the ORM to have modified this method transparently to load the object from persitence. So this method here:

public function getType() {
  return $this->type;
}

to be transparently changed into:

public function getType() {
  if (is_null($this->type) {
    $this->type = $this->adapter->findById('table', $this->typeId);
  }

  return $this->type; // or return parent::getType();
}

Outlet PHP uses eval to create a Proxy class for Project called Project_Proxy but sometimes there will be subclasses of Project so I am searching for a solution by using Reflection API if there is a way.

I have search google but haven't found anyway to change a method behaviour

Edit: or would it be a good idea to use Outlet PHP's eval method to create Proxy Classes for my models and all subclasses of them?

Bria answered 18/11, 2009 at 6:38 Comment(0)
C
3

There is no builtin way of doing this. And although you can do that using the PECL extension called runkit, I would strongly recommend finding another solution. Changing the implementation of functions you can't know anything about is very dangerous and might lead to bugs where debugging a single such bug can take longer than writing the if (is_null(... statements for all your functions.

BTW: don't use is_null(), since you might fetch null values from the database over and over again. You should store the fetched values in a separate variable.

Calamitous answered 18/11, 2009 at 6:55 Comment(5)
But if i write if (is_null(... inside the model I am coupling the model with the DataAbstractionLayer by calling $this->adapter. Also is_null is not actually checking a database field but checking the property which holds the Related entityBria
Quite on the contrary: If you would be implementing logic for the class outside the class, you would defy OO programming rules. You have a database connection object (I'm assuming that $this->adapter is one) and this is called dependency injection, and is currently considered good practice.Calamitous
The issue about is_null() is that calling $user->getFirstName() twice will query the database twice if the column firstname of the users table has a NULL value.Calamitous
Thanks, then I will go with the Dependency Injection.Bria
I am actually not using getters and setters for properties but only to get related entities. So to get firstname I would use $customer->firstName but to get the street address object for the user I would user $customer->getAddress()->streetBria
P
0

Looking at the reflection doc on php.net, it appears to me it is impossible to modify on the flight a method.

You should try to do it in a different way.

Pasturage answered 18/11, 2009 at 6:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.