Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically generate classes at runtime in php?

Here's what I want to do:

$clsName = substr(md5(rand()),0,10); //generate a random name $cls = new $clsName(); //create a new instance  function __autoload($class_name) {   //define that instance dynamically } 

Obviously this isn't what I'm actually doing, but basically I have unknown names for a class and based on the name, I want to generate the class with certain properties etc.

I've tried using eval() but it is giving me fits over private and $this-> references...

//edit

Ok, obviously my short and sweet "here's what I want to do" caused massive strife and consternation amongst those who may be able to provide answers. In the hope of getting an actual answer I'll be more detailed.

I have a validation framework using code hints on the site I maintain. Each function has two definitions

function DoSomething($param, $param2){    //code } function DoSomething_Validate(vInteger $param, vFloat $param2){    //return what to do if validation fails } 

I'm looking to add a validator for primary keys in my database. I don't want to create a separate class for EVERY table (203). So my plan was to do something like

function DoSomething_Validate(vPrimaryKey_Products $id){ } 

Where the __autoload would generate a subclass of vPrimaryKey and set the table parameter to Products.

Happy now?

like image 991
Will Shaver Avatar asked Jul 29 '09 23:07

Will Shaver


2 Answers

As of PHP 7.0, with a little creativity and knowledge of some lesser known PHP features, you can absolutely do this without resorting to eval or creating script files dynamically. You just need to use anonymous classes and class_alias(), like such:

spl_autoload_register(function ($unfoundClassName) { {     $newClass = new class{}; //create an anonymous class     $newClassName = get_class($newClass); //get the name PHP assigns the anonymous class     class_alias($newClassName, $unfoundClassName); //alias the anonymous class with your class name } 

This works because anonymous classes are still assigned a name behind the scenes and put in the global scope, so you're free to grab that class name and alias it. Check out the second comment under the anonymous classes link above for more information.

Having said that, I feel like all the people in this question who are saying "Eval is always a very bad idea. Just don't use it ever!" are just repeating what they've heard from the hive mind and not thinking for themselves. Eval is in the language for a reason, and there are situations where it can be used effectively. If you're on an older version of PHP, eval might be a good solution here.

However, they are correct in that it can open up very large security holes and you have to be careful how you use it and understand how to eliminate the risks. The important thing is, much like SQL injection, you have to sanitize any input you put in the eval statement.

For example, if your autoloader looked like this:

spl_autoload_register(function ($unfoundClassName) { {     eval("class $unfoundClassName {}"); } 

A hacker could do something like this:

$injectionCode = "bogusClass1{} /*insert malicious code to run on the server here */ bogusClass2";  new $injectionCode(); 

See how this has the potential to be a security hole? Anything the hacker puts between the two bogusClass names will be run on your server by the eval statement.

If you adjust your autoloader to check the class name passed in (i.e. doing a preg_match to make sure there's no spaces or special characters, checking it against a list of acceptable names, etc.), you can eliminate these risks and then eval might be totally fine to use in this situation. If you're on PHP 7 or higher though, I recommend the anonymous class alias method above.

like image 114
dallin Avatar answered Nov 01 '22 21:11

dallin


its funny, actually this is one of the few things where eval doesnt seem such a bad idea.

as long as you can ensure that no user input will ever enter the eval.

you still have downsides like when your using a bytecode cache that code wont be cached etc etc. but the security issues of eval are pretty much related to having user inputy in the eval, or to ending up in the wrong scope.

if you know what you are doing, eval will help you with this.

That said, in my opinion you are much better off when you no rely on type-hinting for your validation, but you have one function

DoSomething_Validate($id) {     // get_class($id) and other validation foo here } 
like image 33
foobaer Avatar answered Nov 01 '22 19:11

foobaer