views:

37

answers:

2

Hi,

I read this post after doing a search for related posts.

I have a slightly different, but related problem.

Is there a way WITHOUT EVAL() (because this is a bad idea - open for abuse if someone allows a user to supply the value that is used in eval, etc) such that you can define the structure of the class, for example:

if(!class_exists($className) && dao::tableExists($className)) {
   class $className extends daoObject {
     public function __construct($uid) {
      parent::__construct($uid);
     }
   }
   dao::generateClass($className);
}

The reason for this is because when new core tables are added to a framework, they could be used with a generic data access object for accessing the corresponding fields (getters/setters via __call in the parent, add/insert and update/delete) without writing a class for each, without requiring the coder to write a class and then having to inspect it or writing custom code generators for the various types of tables. the daoObject does that all for me.

The intention is to use this kind of method to define a class if it doesn't exist, then write the class definition to a file.

If the corresponding table name doesn't exist, it will fail. If the class exists (e.g. the next time it is run) then it won't define it. If it doesn't exist but is a tablename, you could create it, use it and save it the first time you call it, which would occur when new tables are inserted and a script is run to insert data. The authors will define only the table fields and sample data via csv. This script will generate classes and import the data in one hit. I COULD write the definition to a file, then include it, which seems like it could work, but I want to do that AFTER I've modified the properties of the object so I don't have to write to files twice to make it work.

This is simplified, but is it possible?

If I find a way, I'll post back.

Thank you

A: 

I don't think it's possible; as you said, the best option is probably to write the class to a file, then autoload that/those classes.

0x90
A: 

You can't use a variable for a class name (unless as you say, with eval()).

So if you really need to create DAO objects at runtime for tables for which no class is defined, perhaps you should make a DAO class for "other table" and pass the name of the table in the constructor.

class OtherTable extends daoObject {
  public function __construct($uid, $tableName) {
   $this->table = $tableName;
   parent::__construct($uid);
  }
}

$FootballTable = new OtherTable($uid, 'football'); 
trigger_error("You need a new table class!", E_USER_WARNING);

If your logs show that you have any of these user-warnings, you should use that as a reminder to go create a proper class for the new table(s).


Re your comment:

Generating code for a new class at runtime, even as a fallback condition, is not a good habit. The risk is that some untrusted content sneaks into your class definition (such as user input, but it can be something else). Then you have a Code Injection security problem.

Either you need a generic any-table DAO class like I showed, or else the best solution is that you create new DAO classes during development, at the time you create new tables in your database. Why is that not your solution?

Bill Karwin
This is the best answer because trying to solve the problem with a dynamic class construction approach misses the point that what we aimed to achieve was instantiating a valid DAO class for the table. However, we're still stuck with the problem of how to deal with this at runtime if no class has yet been created. I think a combination of fallback to file-writing and a factory class could be used. For example, create a factory class to return objects that may be referenced/created in new plugins with new table structures. In those, try to include, fallback to a new file. This should work.
ArcaneErudite