r/PHP•
opulencephp

Beta of New Full-Stack PHP 7 Framework is Out

I just released the latest beta of Opulence. If you aren't familiar with Opulence, it's a new full-stack PHP 7 framework that aims to compete with established frameworks like Laravel and Symfony. A huge advantage to using Opulence is that it's hyper-focused on loose coupling between its libraries so that your domain logic isn't mixed with framework logic. Loose coupling also makes it easier to use individual libraries outside of the framework without having to also download half of the framework due to dependencies. In fact, this latest beta was all about reducing some remaining coupling. The Bootstrapper library (similar to Laravel's service providers) has been rolled into the IoC library, and all of its dependencies have been dropped. Now, you can easily use Opulence's powerful IoC container as well as its bootstrappers in any PHP application, regardless of your framework choice.

If you haven't tried Opulence out, you can install it using composer create-project opulence/project --prefer-dist --stability=dev. If you were already using it and want to upgrade, run composer update, and then follow the upgrade guide. There are some breaking changes, so please review the upgrade guide before using it.

I am nearing the first release candidate for Opulence, and once I do, these breaking changes will be reserved for major releases.

Posted Aug 30, 2016, 4:57 AM UTC

1268
creatiff•

always nice to hear about new stuff, but please stop using the word powerful :)

also, why another orm, why another template engine.

it's only a matter of time for something to come up that can compete against the major ones that are out there right now, but it really feels like a waste that people are still trying to reinvent basic things that don't need reinventing from the ground up, at this point atleast.. thousands years back wheels were round, they still are. but at the same time this is a bit of a paradox, i know it's a good thing that we contest each others ideas and conventions and at some point in time we are going to use a better twig, and a better doctrine/propel/whatever, but you really need to back it up with very strong arguments at this time, and not words like hey, its 'powerful'.. after all, you're not improving on existing technology, you're doing it different

not only that, it actually pushes me away from using your framework, cause i don't want to throw away all that twig and doctrine experience and start over again.

look at laravel, very opinionated(cough) but still, it skyrocketed because it offered an entry level to basically everything webdevelopment

7
opulencephpOP•

Thanks for the powerful reply :-) I feel like Opulence straddles a nice middle ground between Laravel and Symfony - it's simple syntax (like Laravel, but unlike Symfony's IMO entetprise-y syntax) and it is more a collection of libraries than a quasi-monolithic framework (Laravel). Opulence didn't simply reinvent stuff or do it in a different way. I urge you to browse the source code or the docs to understand what I mean. I think having an easily digestible, loosely coupled framework today is worth more than what you're giving credit for. Part of why I wrote Opulence is because of frustration I've experienced trying to incorporate other frameworks cool libraries into already-existing code bases. I'm catering to the audience that craves well-architected code without having to necessarily tie its entire code base to the flavor of the week framework. Is that a smaller audience? Sure, but I sympathize with those people, and that's why I wrote this.

Regardless, I really do appreciate your honest assessment.

5
creatiff•

good answer, tons of stuff frustrates me too, but i don't think you're targeting that audience(me) right now. this post right here, the reasoning behind it, and your answers to those frustrations is what would target me. you should write posts about it, or even on the front page of your framework maybe.. its easy for the author to see it's potential, but i'm a bit in the dark right now unless i violently go through the source ;)

2
opulencephpOP•

You're right. I need to get the ball rolling on screencast tutorials and blog posts. I haven't evangelized much because I only announced Opulence a couple months ago. Once it's in the release candidate stage, I plan on doing a lot more to market it towards my target audience.

1
phpdevster•

I like that this has its own DM ORM as an alternative to Doctrine. I find Doctrine to be clunky and cumbersome with really scatterbrained documentation. A DM ORM as simple and concisely documented as Eloquent is sorely lacking in PHP IMO.

That said, the API for doing routing in Opulence? Hoo boy. That is some next level Java right there. :(

The facade pattern exists for a reason.

5
[deleted]•

always nice to hear about new stuff, but please stop using the word powerful :)

Some alternatives:

  • Amazing
  • Magical
  • Insane
  • Unbelievable
  • Great
  • Wonderful
  • Incredible
  • Far Better
  • Truly Improved
  • Innovative
  • Phenomenal
  • Gorgeous
  • Terrific
  • Disruptive
  • A Dream To Use
  • Exciting
  • Outstanding
  • Beautiful
  • Remarkable
  • Fantastic
  • Exceptional
4
ThePsion5•
  • Awesome
  • High-Quality
  • Spacious
  • Luxurious
  • Divine
  • Decadent
  • Racist
  • Gravid
  • Engorging
  • Mysterious
  • Enigmatic
  • Disquieting
  • Spooky
  • Ghastly
  • Eldritch
  • Fetid
  • Mephitic
  • Flesh-Hungry, Eyes Glazed with Bloodlust
  • Unknowable, but Knowing, it Knows
2
BubuX•

It's fast. Opulence is written in PHP 7, for PHP 7 It can handle 500 requests/second on a cheap 512MB server and 2,000 requests/second on a modest 8GB server. Most of Opulence's settings are cached to reduce overhead on each request.

Is this considered fast? We have the power of what was considered a data-center not long ago, inside laptops weighting less than 2kg and this is the best we can do in late 2016? And this is probably a fine tuned hello world benchmark.

Well I guess if everything around you are snails, your sloth looks fast.

This is not a rant towards Opulence or even PHP. It's to the sad state of web dev.

Need to store passwords? Try our hashing library.

Why do you need to wrap bcrypt or anything if we now have this?

I'll stop here.

6
[deleted]•

This is not a rant towards Opulence or even PHP. It's to the sad state of web dev.

Love it or hate it, the architecture of PHP has a lot to do with this. You can't reload your entire environment, including some increasingly complex software on every request, even with opcache, and expect best-of-class performance.

And software can't be simplified forever, because as you gain that next 1% of server performance, by dropping features and flexibility, you lose 50% of developer performance. I was here in the PHP 4.0 days when PHP development was about running SQL queries in the middle of your HTML, and I think we all agree we don't want that anymore. Well, step by step... we don't want this, we don't want that, and we have the modern status quo of loading at least a few dozen classes per request (and that's minimal, some frameworks load hundreds).

Compare PHP results to something like Play (based on Nette, which is written in Java), PHP will always be about 10x to 100x slower... Unless the architecture changes.

Maybe one day.

7
BubuX•

You can't reload your entire environment, including some increasingly complex software on every request, even with opcache, and expect best-of-class performance.

Agreed. Although that model brings some conveniences. You are guaranteed to have a clean session, without having to worry about race conditions and memory leaks on every request. The trade-of is we have to boot the stack from zero for each of those 2000 requests/s.

Like you said opcode caching helps but can only go so far. Autoloading helps with performance in the big picture most of the times but, again like you said, it doesn't matter when the framework loads hundredths of classes per request.

I love PHP. I just don't like the way some use PHP.

2
[deleted]•

You are guaranteed to have a clean session, without having to worry about race conditions and memory leaks on every request.

Architectures like Play and Node don't suffer from race conditions. As for leaks... with PHP the only reason we have so many components with leaks is because leaks don't matter, because of the architecture. In other words, PHP encourages leaky code. Change the architecture, and all those leaks will be fixed very fast.

There's also a way of fixing the remaining subtle leaks: reboot the environment for a given thread, but not after every request, but after every, say, million requests.

1
phpdevster•

Anthony Ferrera gave a good talk about other issues that affect performance in PHP. http://m.youtube.com/watch?v=qjYyC47rdVs.

I know Laravel is very guilty of "string magic" and dynamic method calls, which affects its performance. Would love to see a Blackfire profile against modern frameworks though, just to see where each spends most of its time.

2
sypherlev•

This is an excellent talk to watch.

1
furrycardboard•

There are pure PHP web servers that address this specific deficiency by using a persistent process to host your app (including one extremely impressive project created by one of the internals devs, IIRC). From what I remember of their benchmarks, they blow the standard stacks out of the water on performance.

1
[deleted]•

There are such servers, one was even written as a C extension for PHP, to eliminate the overhead of parsing HTTP requests and producing HTTP responses in userland (because the built-in functionality can't handle a persistent process).

The problem is the ecosystem won't follow a third party solution. So this option will remain a fringe option that many libraries and extensions will choke on, as they've not been tested in a persistent process based primarily around asynchronous execution.

Things will change when this becomes one of the PHP binaries that come out of the box. Like CLI, CGI, FastCGI and the Apache modules.

1
opulencephpOP•

I agree with your sentiments about wanting web apps to be faster than they are, but all I can do is compare Opulence to what else is out there, and it does quite well in that regard.

Good catch about the hash link. The hasher class is a holdover from a time when Opulence supported older versions of PHP. You're right about PHP 7 though - it is a somewhat irrelevant class now. I've updated that portion of the site to talk about Opulence's encryption library, which is very relevant.

3
BubuX•

Good attitude :)

Thanks for your reply. Keep it up.

1
[deleted]•

[removed]

1
PoliteUsersBotBot•

Thank you for fully automatically and mindlessly assuming every post with a certain keyword is meant politely! But hey, it's the sentiment that counts.

This bot was created by Spritetm For more information check out r/Polite_Users_Bot_Bot!

7
BubuX•

My ex wife wouldn`t agree you you mr bot.

3
sypherlev•

It's fast compared to stuff like Laravel. People who actually care about this particular metric are not going to be impressed, and people who don't care... don't care, obviously.

I mean, I used to work on a big data driven CI2 system that handled 2k+ requests per second, and that was 4 years ago. Get back to me when you can do something completely bonkers, like 10k per second without caching.

3
nazar-pc•

If this is considered for very simple applications, I'm already scared by amount of boilerplate for medium complexity app:

use Opulence\Ioc\Container;
use Opulence\Routing\Dispatchers\ContainerDependencyResolver;
use Opulence\Routing\Dispatchers\MiddlewarePipeline;
use Opulence\Routing\Dispatchers\RouteDispatcher;
use Opulence\Routing\Router;
use Opulence\Routing\Routes\Compilers\Compiler;
use Opulence\Routing\Routes\Compilers\Matchers\HostMatcher;
use Opulence\Routing\Routes\Compilers\Matchers\PathMatcher;
use Opulence\Routing\Routes\Compilers\Matchers\SchemeMatcher;
use Opulence\Routing\Routes\Compilers\Parsers\Parser;

$dispatcher = new RouteDispatcher(
	new ContainerDependencyResolver(new Container()),
	new MiddlewarePipeline()
);
$compiler = new Compiler([new PathMatcher(), new HostMatcher(), new SchemeMatcher()]);
$parser = new Parser();
$router = new Router($dispatcher, $compiler, $parser);
$router->get("/foo", function () {
	return "Hello, world!";
});

Does anyone will ever use these components outside of framework? Isn't it possible to replace them in any other way? Looks like decoupling for the sake of decoupling, while the truth is that it will almost never used. I'm pretty sure no one will remember this amount of boilerplate easily, so that it will be just copy-pasted most of the times. Would be nicer to have extremely simple interface right from the beginning.

3
[deleted]•

Wait, I have an idea. We'll put all this boring wiring code in a static class to make it simple, and call it a façade...

16
Winter_already_came•

Lmao, nice idea Tay

3
mofrodo•

I don't think I've ever read a single positive post from you. The community could use a little less of your poison.

1
[deleted]•

That wasn't negative. My heart is full of nothing but love and compassion for the fellow PHP developer.

1
Winter_already_came•

That happens only if you want to use it outside the framework. Usually all that boilerplate is taken care of in the bootstrappers.

2
opulencephpOP•

That's the beauty of bootstrappers. If you use them, you could simplify the above code to:

$container = new \Opulence\Ioc\Container();
(new \Opulence\Framework\Routing\Bootstrappers\RouterBootstrapper)->registerBindings($container);
$router = $container->resolve(\Opulence\Routing\Router::class);
$router->get("/foo", function () {
    return "Hello, world";
});

If you took away all the use statements, the boilerplate code you posted really isn't much. Regardless, if you're willing to use the IoC library, you could get away with my example above. If you don't want to, then you're free to implement your own IDependencyResolver, which could use the IoC container library of your choice. That's the point of some of this code - it makes everything so much more flexible because now you're not stuck using Opulence's libraries if you already have others you'd rather use. It's a tradeoff - write literally 2-3 more lines of code to not inherit 5 extra inter-framework dependencies (Laravel) or have a couple lines fewer and be stuck with several other libraries. It's not a matter of being slower due to those extra dependencies - it's a matter of now being forced to use several libraries when I may not want to in my application.

1
pgl•

What does IoC stand for?

2
modestlife•

Inversion of control

2
pgl•

OK, thanks.

1
magicpretzel•

You probably didn't read the memo. This is supposed to be how modern, testable, well-abstracted PHP applications are done.

This is the effect of absolute obedience to the rule "inject all the things".

-2
nazar-pc•

I've read it, but modern, testable and well-abstracted PHP applications aren't necessary composed of megabytes of boilerplate like snippet from docs above. There is literally 2 lines of code that do something:

$router->get("/foo", function () {
	return "Hello, world!";
});

Everything else uses defaults and should be reduced to very minimum (preferably to single line of code) with possibility to optionally write original boilerplate if there is (ever) need to do so (for whatever purposes).

2
[deleted]•

I've read it, but modern, testable and well-abstracted PHP applications aren't necessary composed of megabytes of boilerplate like snippet from docs above. There is literally 2 lines of code that do something

Sigh. When programmers start to complain about unnecessary boilerplate, I sometimes wonder if they know the first thing about structured programming. Like code reuse through the magic of functions and classes:

function getDefaultRouter() {
	$dispatcher = new RouteDispatcher(
		new ContainerDependencyResolver(new Container()),
		new MiddlewarePipeline()
	);
	$compiler = new Compiler([new PathMatcher(), new HostMatcher(), new SchemeMatcher()]);
	$parser = new Parser();
	return new Router($dispatcher, $compiler, $parser);
}

Now using the very same framework is reduced to this:

$router = getDefaultRouter();

$router->get("/foo", function () {
	return "Hello, world!";
});
  • If it's repetitive boilerplate (i.e. same across all projects), put it in a function/method and forget it ever existed.

  • If it is not repetitive boilerplate (project-specific), don't complain you need to write it, because it's there to help you configure your application, and you need it (if you wouldn't need it, refer to the previous bullet point).

Either way, it's kind of embarrassing to complain about it.

5
nazar-pc•

This was exactly my point! Something like that should be available out of the box and used in docs. Why would everyone write or copy-paste the same shit in every project? We are all about re-using code, but wasting time on glue for components built in the same kitchen. Seems ridiculous to me, could be much better experience.

1
[deleted]•

This is the effect of absolute obedience to the rule "inject all the things".

You're saying this sarcastically, but this type of code is written once for a project, and then not touched for months. It gives you the flexibility to define and change your architecture where other frameworks don't allow it.

And if you're absolutely certain you'd never ever change the wiring... good news, you can put it in a class and call it Application, or something, like all other frameworks do, and reuse it across projects.

In any case, don't mock people who give you configurable components. The easiest thing in the world is to wrap this configurability in something static and monolithic. But the reverse scenario is almost impossible: to start with something static and monolithic, and make it highly modular and configurable.

1
magicpretzel•

You're saying this sarcastically, but this type of code is written once for a project, and then not touched for months. It gives you the flexibility to define and change your architecture where other frameworks don't allow it.

"not touched for months" -> change that to years. what did you earn out of that configurability?

1
[deleted]•

what did you earn out of that configurability?

I earn the ability to choose the best components for an app, components from different authors, and quickly wire them to make them work as one. I've also had to replace components for a project during maintenance, and it's nice when it goes without a hitch.

In the long run, you'll have to replace components even just because some of what you use gets abandoned. That's a fact of life, and frameworks are not immune, the PHP graveyard is full of once-popular frameworks.

The fact you can update your app piece by piece through adapters and wiring means it's possible to do at all. Because when your framework (or compatible framework version) gets abandoned, and you need to replace all or none of it... you're in deep trouble. It's time for a complete project rewrite then. And that is incredibly hard to pull off without disrupting your business for a significant period of time.

Also, the trick is to keep interfaces that compose in your bootstrap wiring simple so they are simple to reimplement, decorate. This allows me to add concerns like: logging, caching, admin notifications, security checks, fallbacks, without writing a single line of logic: just through compositing and decoration in the bootstrap.

I know it's hard to realize you can solve actual problems in the wiring configuration, but this is the result of relying on a monolithic framework. Because I have control over the wiring, I don't need YAML/XML configuration with hundreds of settings you need to find in the framework manual, with the hope it does what you want, nor I need to copy-paste logic in my controllers when I need to solve a system-wide or module-wide concern. I change a couple of lines in the wiring, and it's done.

2
geggleto•

shouldn't a framework be something simple...

$framework = new Framework();
$framework->get('/', function () { return "Hello World"; });
$framework->run();
-1
Winter_already_came•

Should it be simple or something modular and customizable that CAN be made that simple?

2
ahundiak•

Running the composer command from the documents resulted in an error:

php -r "shell_exec((file_exists(getcwd() . '/composer.phar') ? PHP_BINARY . ' composer.phar' : 'composer') . ' dump-autoload -o');"
'composer' is not recognized as an internal or external command, operable program or batch file.

I ran the dump-autoload manually so no problems but at least on my windows development machine, the composer executable lives in a bin directory accessible via $PATH.

I kind of wish you used some of the PSR interfaces for things like Request/Response. I understand why you didn't but it does mean that Opulence will have to spawn it's own eco-system.

Looking forward to messing around with it.

1
opulencephpOP•

Hmm, I'll have to investigate that error. Thanks for reporting it! I understand your concerns about not using the PSRs for requests and responses. PHP badly needs abstractions for them, but I just felt like the PSR was lacking lots of important functionality and was prone to accidentally writing bugs due to immutability. If there ever was a better implementation out there, I'd adopt it in a second.

1
nyamsprod•

so I have a little app in PSR-7 how do I convert it or bridge it to Opulence without having to re-invent the wheels since Opulence does not:

  • follow PSR-7 (which is fine by me)
  • does not provide a bridge (like Symfony does ... reused by Laravel)

The same question could be ask for a convertion from HTTPFoundation to Opulence

0
opulencephpOP•

Unfortunately, I do not have any kind of bridge for PSR-7. I looked into implementing such a thing, but it wasn't trivial. I'm not opposed to it, but writing a bridge for a poorly-implemented PSR that never gained a huge following just isn't high enough on my priority list. That's not meant as a snobby comment - I just have other things to tackle before I'd allocate the time to write such a thing. If you're feeling up to the task, you can always submit a pull request ;-)

2
nyamsprod•

The same question could be ask for a convertion from HTTPFoundation to Opulence

this has nothing to do with PSR-7, PSR-7 was used as an example. How to one migrate an app from Symfony or Laravel to your Framework such documentation or bridge would help for testing or adoption?

but writing a bridge for a poorly-implemented PSR that never gained a huge following just isn't high enough on my priority list.

Do you have statistics to back your opinion ? I would be interested in viewing them. Last time I check Slim 3 or Guzzle 6, for instance, are very popular.

1
opulencephpOP•

Laravel and Symfony did not embrace PSR-7. Symfony wrote a bridge for it, but doesn't dogfood PSR-7 because it's simply not as powerful as HTTPFoundation. By extension, neither does Laravel.

1
nyamsprod•
1
dracony•

What makes a framework a "PHP 7 framework" ? Are "PHP 7" libraries somehow superior to the "PHP 5" ones?

-7
[deleted]•

What makes a framework a "PHP 7 framework" ?

Are you serious. It means it requires PHP 7 and takes advantage of the new PHP 7 features.

7
dracony•

Well yes, but which features are those realisticly? Type hinting? Do you even care if the library that you use uses those internally, if it is the code you won't touch anyway?

Are there any real PHP-7 features that you would want your library to use?

-1
[deleted]•

Any time there is an interface, the inability to specify a return type mean you're basically writing an interface that returns whatever. So type hinting, both scalars and return types, significantly reduce bugs caused by library users implementing SPI-s improperly.

Anonymous classes are huge for libraries, it allows you to encapsulate how and when a class is created, focuses the architecture on addressing instances implementing interfaces (versus configs and method calls littered with Something::class, you've seen it). It also allows you to create single-file factories that provide many different implementations of the same interface (for decoration for ex.), which is more efficient than creating separate classes.

Like closures in PHP 5.3, the feature seems subtle and a nice-to-have, but it changes the entire way you do architecture in PHP (if you realize its use cases).

Expectations is also huge for libraries. Finally a library can have rich (and somewhat slow) assertions aid during development, and turn them off at no cost in production. I used to previously rely on good old DEBUG flags, but all that extra code would still load in production. Assertions that disappear are a much better and universal tool for this.

There are also other features, but I hope you notice: it's not just about what PHP 7 features the library uses in its code, it's also about what PHP 7 features the library knows its users can use. This changes the way library APIs are designed, and all for the better.

Also a library designed for PHP 7 would take advantage of the PHP 7 engine performance characteristics. PHP 7 is not just "faster", in a uniform way. It's a bit faster in some areas, much faster in other areas. RAM usage is similar. Many optimizations and workarounds that were tested and designed for PHP 5 no longer apply for 7, so when your focus is PHP 7, it allows you to get more out of it.

4
dracony•

You can still use anonymous classes in your own code if you like? What do you care if the library you are using used anonymous classes or not?

it's also about what PHP 7 features the library knows its users can use

Does opulance have some amazing feature you can use with anonymous classes? Because I didnt notice any

1
opulencephpOP•

The nice thing about it being a PHP 7 framework is that any Opulence interfaces or base classes you'd like to extend are using return types and scalar type hints. Otherwise, it's frustrating to write your app in 7, but have to write anything that extends Opulence in 5.*.

1
dracony•

Why? The PHP 5 libraries and frameworks use phpdoc annotations that achieves the same result for you in the IDE

0