Change the content of PHP classes and methods at runtime, with Reflection? - php

This is for fun only, don't scream please.
I would like to rewrite the content of a class's methods at runtime (I mean, without modifying the file, only replacing/editing the code in memory), is that possible?
Using reflection, or anything else?
Don't close this question please, I'm looking for another answer than runkit.

Why not simply create a new class that inherits from the one you want to modify and overwrite it's methods?
<?php
class MySimpleXML extends SimpleXMLElement {
public function themethodiwanttooverwrite() {
//...
}
}
?>
As long as the method isn't marked as final...

Related

Is there any way to bind trait to class dinamically? [duplicate]

Simple question, is it possible to dynamically add traits to a php class in runtime without using eval?
As Glavic said, you can't without using eval() or reflection hacks (and I'm not even sure about that).
But it's very unlikely you really need to.
You can achieve a lot with dynamic class composition (composing a class with some functionality you want into another class). That's simply a matter of putting a reference to the class with the desired functionality into a variable in the hosting class.
class SomeClassWithNeededFunctionality {}
class SomeClassThatNeedsTheFunctionalityOfTheOtherClass {
private $serviceClass = NULL;
public function __construct (SomeClassWithNeededFunctionality $serviceClass) {
$this -> serviceClass = $serviceClass;
}
}
No.
p.s. you can have them in standalone files, and use include() ?

Can methods be defined outside of a class?

I'm just getting into using classes in php and am coming from a C++ background. Literally every example I've seen shows methods being defined inside of the class definition, and I'm wondering if I can define my class methods outside of the class definition in order to improve readability?
Sort of. PHP 5.4 itroduced traits which is about as close as you're gonna get.
Yes you can in PHP. The function body for class methods can be put fully into external files:
class foo
{
function bar() {
include('import_method_body.php');
}
}
This works since ages.
In short, NO you can't do that;
In php every mothod should be inside the class. And that is why php isn't considered to be fully OOP language by some developers i have seen.

defining a global function in kohana

I am new to kohana and also relatively to php.
I have a simple URI encoding function, which mimics that of JS %100, unlike that of PHP's.
I want to use this function in certain classes but I don't want to define it in each and every one of them.
So, how can I define a global function to be used in all places?
(I don't want to create a class for a 3 line code function)
Thank you!
Overload the core URL helper class. Add your function as a static method.
Override your desire to avoid good OO principles. Create a new class and make a static public function. Don't create bad-old global functions.
<?php
function yourFunction( ) {
return 'your result';
}
How about that? Just write that in a file that always gets included and you're good to go. Don't go making a static class just for the sake of thinking you're doing OO, there's no point.
You can put your global function in you bootstrap (APPPATH/bootstrap.php) though I recommend extending the core URL helper class (assuming you're on Kohana 3.x) by creating a new file at APPPATH/classes/url.php:
class URL extends Kohana_URL {
public static function encode($uri)
{
// ...
}
}
It's almost always worth the 3 lines of code. Kohana was designed for you to override its core classes. Your code will be more maintainable.

How do I Use Inner Classes in PHP?

I'm from a Java background, and I want to use an inner class in php. Every time I put the inner class though, I get a syntax error. Is this possible with PHP? Also, how do I reference the outer class? Do I get access to ALL its data members?
<?php
class OuterClass {
var $x = 15;
function __construct() {
}
class InnerClass { // error when InnerClass is static
function __construct() { // error when InnerClass is static
echo $x;
}
}
}
?>
This is used for a MoveClass (as in make a move) of a specific card game. I think it'd be good design to put these classes together because they don't make sense apart. Also, the MoveClass needs to know about some data members of the Game class. Why not make it a function? It's simply too big.
Edit:
What about nested classes? From what I understand, those have to be static? O_o
PHP does not allow for inner classes. Should you wish to access all of the data members from the parent class, I would suggest you employ Inheritance.
A possible alternative:
class OuterClass {
var $x = 15;
function __construct() {
}
}
class ChildClass extends OuterClass {
function __construct() {
parent::__construct();
}
}
You can envoke a method form the parent class by referring to the class itself; In PHP you can do this with the parent keyword. So, to refer to a method in the context of a class rather than an object we use :: as opposed to ->.
in PHP 5.4 or later, you can use PHP Traits which are designed more for multiple inheritance, but may suit your needs. From the PHP Documentation:
A Trait is similar to a class, but only intended to group
functionality in a fine-grained and consistent way. It is not possible
to instantiate a Trait on its own. It is an addition to traditional
inheritance and enables horizontal composition of behavior; that is,
the application of class members without requiring inheritance.
http://php.net/manual/en/language.oop5.traits.php
As mentioned in comments to this answer from another question, the PHP version of this functionality has been added in PHP 7. It does not seem to provide exactly what you are asking for. However, it should provide you a similar design pattern.
Here's the RFC describing how it works: https://wiki.php.net/rfc/anonymous_classes
As mentioned in the other answer's comments, search the RFC page for "nested" to see an example of nesting inside an outer class.
You might want to use a stdClass instead. Here's an SO question about it: What is stdClass in PHP?
You can't nest classes like that.
Look at the "extends" section of the manual.

Dynamically Create Subclass

I am using Kohana and just found this piece of code in their autoloading method
// Class extension to be evaluated
$extension = 'class '.$class.' extends '.$class.'_Core { }';
// Start class analysis
$core = new ReflectionClass($class.'_Core');
if ($core->isAbstract())
{
// Make the extension abstract
$extension = 'abstract '.$extension;
}
// Transparent class extensions are handled using eval. This is
// a disgusting hack, but it gets the job done.
eval($extension);
basically what it does is when I am referring to a class that doesn't exist (through object instantiation, calling class_exists() etc.), Kohana will create a class (eg. Foo) that extends a library class that follows certain naming convention (eg. Foo_Core). just being curious, is there any way to do something similar but without the use of eval?
If you are looking to create a dynamic class then eval() is the goto function (pun intended.) However kind of related, I've found that you can put a class declaration within an if-then statement. So you can do the following:
if(true)
{
class foo
{
// methods
}
}
I use this to check to see if dynamically created classes (from a configuration file) are current... if so then load the class, otherwise... regenerate the class, and load the new one. So if you're looking to create dynamic classes for similar reasons this might be a solution.
I think you're stuck with eval() for that.
It's marked as a "disgusting hack" so that makes it OK :)
I'd be interested to know what you do with such an empty class...
If you were wanting to be able to cache your dynamically created classes, you could write out to a file and require it instead. This could be considered equally hack-ish, but it is an option. For classes that are created once and used often, it might be a good solution. For classes that need to be dynamic every time, sticking with eval is probably the best solution.
$proxyClassOnDisk = '/path/to/proxyCodeCache/' . $clazz .'.cachedProxyClass';
if ( ! file_exists($proxyClassOnDisk) ) {
// Generate the proxy and put it into the proxy class on disk.
file_put_contents($proxyClassOnDisk, $this->generateProxy($object));
}
require_once($proxyClassOnDisk);
In this example, the idea is that you are creating dynamic proxies for the class of $object. $this->generateProxy($object) will return the string that looks more or less like what $extension looks like in the original question.
This is by no means a complete implementation, just some pseudo code to show what I'm describing.

Categories