tags:

views:

46

answers:

1

Is there a way to dynamically and conditionally create a class definition in PHP, i.e.

if (condition matches)
  include file containing class definition
else
  class myclass extends ancestor_class { .................... }

without eval()?

My background is the accepted answer to this question. I am looking for the best way to build a untouchable core library, with user-defined empty classes extending the core library if necessary.

I want to create the final class definition "on the fly" if there is no user-defined empty class for a certain ancestor class.

Including another include file (containing the empty class definition) is out of the question, as there will be quite a number of classes.

Update: This seems to be possible in a normal condition block - didn't think of that. However, according to this article, it also seems to be regarded as bad practice and may be removed in the future. Hmm. Creative ideas welcome.

+1  A: 

See the comments under the question for more informations -- I'll try to summarize, as it might be useful to other :-)


First of all, I suppose the goal is not having users create almost empty files by themselves -- I remember another question, I think it was from you, where that popped up.

If so, why not just create those almost empty files dynamically ?
I mean, some idea like that :

if (condition matches) {
    include file containing class definition
} else {
    create another file containg the alternate class definition
    include that other file
}

As @Gordon said in a comment, a possibility, to makes things a bit easier, would be to use Zend_CodeGenerator, to help with that task of code-generation.


As pointed out : the users will not likely have write-access on the library directory, but nothing prevents you from creating those files into another "cache" directory -- afterall, it's likely that your application has write-access to at least one directory :

  • For cache ^^
  • Or, at least, for logs


A solution would be to use eval :

  • build a string containing the class' definition
  • evaluate it

But I would really not do that, for at least two reasons :

  • Debugging will probably be harder -- even for an almost empty file/string
  • Using a file means there is a possibility for opcode caching (APC, or similar tools)
  • And, as a third, thinking about it : having a file means your IDE can parse it -- might help with code-completion, type-hinting, ...


Seeing your update, I tryied conditionnal declaration :

if (false) {
    class A {
        public $a = 10;
    }
} else {
    class A {
        public $a = 20;
    }
}

$a = new A();
var_dump($a);

Changing the condition from false to true and vide-versa, I get two alternate output :

object(A)[1]
  public 'a' => int 20

object(A)[1]
  public 'a' => int 10

So... well, seems to be working !
(I'm surprised, I thought it was only possible for functions !)

But, still, I don't really like that idea... Not sure how it behaves in IDEs -- and I like having one class per file...
(Yeah, personnal opinion)

Pascal MARTIN
+1 Very good points as always, thanks for testing and making me aware of the IDE implications.
Pekka
You're welcome ; and thanks :-) ;;; I didn't think about those, when commenting -- but thought about IDE when writing, so... *(IDE and opcode cache are two reasons which make me hate `create_function` -- and eval's a bit like that ^^ )*
Pascal MARTIN