Hi Tom
On 9 August 2014 11:35, Tom Oram <[email protected]> wrote:
> I've just been looking back at the history of this previous conversation...
>
> http://marc.info/?l=php-internals&m=132673741606531&w=2
>
> as a mockist tester I'd really REALLY like to see this be possible but I
> can see the problem with the original patch modifying the actual existing
> class.
>
> One solution I propose is rather than modify it would it be possible for
> the reflection class to be able to duplicate the class with the finals
> removed so something like this could be possible:
>
> final class A
> {
> }
>
> $r = new ReflectionClass('A');
>
> $r->defineExtendableClass('ExtendableA');
>
> class MockA extends ExtendabledA
> {
> }
>
> I'm unfamiliar with the PHP codebase so I thought I'd just ask here to find
> out if it sounds possible before diving into the code
Yes it's definitely possible, all you need to do is duplicate the
class definition and perform &= ~ZEND_ACC_FINAL on the class entry
structure flags, however...
Joe Watkins' uopz [1][2] extension already provides a mechanism to do
what you want to do. I've not tested this, but I quickly bounced a
couple of questions off Joe and I believe this should work:
final class A {}
class MockA {}
uopz_extend('MockA', 'A');
A word of warning though: if a *method* is explicitly declared final
(rather than implicitly because the class is final), and the mock
overrides this method, this will be checked at runtime and cause a
fatal error. In order to work around this, you need to use
uopz_flags() as well:
class B {
final public function c() {}
}
class MockB {
public function c() {}
}
uopz_flags('B', 'c', ZEND_ACC_PUBLIC); // remove ZEND_ACC_FINAL
uopz_flags('B', 'c', );
Note also that if you are using this approach - modifying symbol flags
at runtime - it is important that you do not declare the inheritance
relationship explicitly (i.e. class MockA extends A {}) as this will
error out before the runtime modifications are made.
If you want to look at adding similar functionality to reflection,
then looking at how uopz works would be a good place to start - but
personally I'm not sure if there's any value in this since anyone who
wants the functionality can just use uopz.
[1] https://github.com/krakjoe/uopz
[2] http://php.net/uopz
> Thoughts?
>
> Regards,
> Tom
Thanks, Chris
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php