Good way of modifying a class and dumping it ? - Reflection?
I am trying to create a method that can modify a class in a file and dump the class to the same file.
What is the best practice to do this ?
What I am trying to do is:
Say i have the class:
Test.php:
namespace test;
class Test{
}
... and i want to process this class so the final output will be
Test.php:
namespace test;
class Test implements /interfaces/Entity{
}
With *str_replace* it would be something like:
function parseImplementation($src, $class, $interface){
return str_replace("$class", " $class implements $interface", $src);
}
I have tried the Reflection API, but I cant really find a way to edit the class itself and dump it to source code.
Is there any smooth way of doing this ? str_replace is not an option, because Test class can be implementing other stuff and 开发者_如何学Gotyped with tabs / spaces as separators.
What you want is a source-to-source program transformation system. This is a tool that parses code to compiler data structures (abstract syntax trees) that are independent of layout, etc. and then lets you write "if you see then then replace it by that" operations, that operate on the compiler data structures. (Yes, you can try do this with string hacking, and it may work for the example you have in hand, but string hacking won't be reliable in general for the same reason that you can't using just string hacking to parse real source code).
To do this, you need something that can reliably parse PHP and apply source to source transformations. Not many tools exist to do so.
Our DMS Software Reengineering Toolkit with its PHP Front End is one that can.
Your specific transformation can be done like this with DMS:
domain PHP~PHP5; -- declare the programming language DMS will process
rule add_interface_to_class(class_name:identifier,
m: class_members):
class_declaration -> class_declaration =
"class \i { \m } "
-> "class \i implements /interfaces/\entity\(\){ \m } ";
rule add_another_interface_to_class(class_name:identifier,
ifaces:interfaces,
m: class_members):
class_declaration -> class_declaration =
"class \i implements \ifaces { \m } "
-> "class \i implements \ifaces,/interfaces/\entity\(\){ \m } ";
I have two rules here, one to handle the case where your class has implements clause, and one to handle the case where an implements clause already exists.
It wasn't clear how "namespace test" played into your example, but if that was important you'd have to add a conditional test to each rule, to verify the identifier i was in the "right" namespace.
精彩评论