As of January 22nd, 2017 PSR-15: HTTP Server Request Handlers has been accepted. The final vote was 12 members in favor, none opposed, and none abstaining. I am very grateful to everyone that contributed during the last (almost) two years. And especially thankful for Matthew Weier O'Phinney, who ultimately sponsored the PSR and got it through the review phase!

The PSR itself is split into two parts: a middleware interface and a request handler interface. Typically the middleware will perform checks or modifications on the request, pass it to the request handler to generate a response, and then perform checks or modifications on the response before returning it.

Writing a middleware is done by importing the MiddlewareInterface and defining a process() method. This method must generate a response, either by delegating to the request handler or generating it internally. For example, if a middleware was checking CORS headers it would generate a response internally if the request did not have correct headers. If the correct headers are present, it would delegate to the request handler to generate a response. Matthew Weier O'Phinney has a much more in-depth example of middleware on his blog, along with a lot of historical information.

Writing a request handler is less common. Typically the request handler will be implemented in a middleware dispatching system to continue processing a middleware stack. The request handler may also be used as the last item in a middleware stack to execute application code. It is not expected that controllers or domain actions will implement the request handler, though it is possible to do so.

A final note: as of the time of writing this post, just 10 days after the acceptance vote, there are already 107 packages depending on psr/http-server-middleware and over 2000 installs. This is a great vote of confidence from the community!

]]>

CQRS has been getting a fair bit of attention in the last few months. One of the major benefits of using CQRS is that you can completely isolate reading data from writing data. This allows architecting around slices instead of layers. The less cross-cutting concerns exist in your application the

CQRS has been getting a fair bit of attention in the last few months. One of the major benefits of using CQRS is that you can completely isolate reading data from writing data. This allows architecting around slices instead of layers. The less cross-cutting concerns exist in your application the more rapidly change can be realized.

Creating a Query Object

Having an object that represents a query is a great starting point for experimenting with CQRS. Let's we have a database of users in our system and an administrator can search for users based on a set of criteria:

The first name of the user

The last name of the user

The role of the user

In addition, we allow the results to be sorted by first or last name.

Note: These examples are not going to address limits or offsets. There are multiple ways to handle paging and addressing them would outside the scope of this post.

From this information, we can construct UserSearchQuery that represents the criteria:

There are a couple of things to note right away. The first is that we are using a named constructor and making the __construct function private. This allows us to expose different variations of the search criteria in different contexts without having to refactor code using the class. For instance, we might want to have a forEmployee method that eliminates the ability to search by $role:

$query = SearchUserQuery::forEmployee($first_name, $last_name);

The second thing to note is that this class is completely immutable. There are no methods that allow it to be modified, the __construct method is private, and the class is marked as final. This makes it a safe DTO, which is exactly what we want, since a query will be carrying data into your domain layer.

By itself this is a good start but we can improve it even more by adding state validation. One way to accomplish this is with the beberlei/assert package. Let's update our constructor with validation:

If anything goes wrong in this check, a Assert\LazyAssertionException will be thrown that contains all the validation errors. We can now call this function from the constructor to ensure that our object cannot be created with invalid state:

Creating a Repository Object

By itself, a query object does nothing but capture and validate some user request parameters. In order to respond to the request we will need to query the database. A fantastic PDO wrapper called EasyDB will make this very straight forward.

Perfect, now we have a repository that takes the query object and returns an array of database results. All of the query parameters are escaped safely thanks to EasyDB and creating the dynamic conditions for first/last name was simple with EasyStatement. Even the direct usage of the $query->orderBy() is safe, because we know the query object validation limits the possibilities to first_name or last_name, which are valid column names.

The query generated would be something like the following, depending on the parameters set in the query object:

SELECT *
FROM users
WHERE (
first_name LIKE '%luke%'
OR last_name LIKE '%sky%'
)
AND role = 'employee'
ORDER BY last_name

Note: we will assume that this class will be dependency injected with a working EasyDB connection.

Escaping LIKE Conditions

Update: There is one additional consideration that we need to address here, which is that LIKE conditions have additional characters that must be escaped. This can be done with the escapeLikeValue() method in EasyDB. The first and last name query conditions become:

And once we have the query we can pass it into a repository to get the results. For the sake of simplicity, assume that $this->users is an instance of SearchUserRepository that was dependency injected into the controller:

Conclusion

With this example we have seen that creating query objects can be simple, without the need for complex modeling systems. Using a self-validating object creates a safe contract between our application and our domain. Using a simple (but powerful!) PDO wrapper makes writing dynamic queries simple, without the need for an ORM package.

If you have thoughts about this article, be sure to tweet me @shadowhand!

]]>

Last summer the development team at When I Work started to develop an open source framework that would be the basis for future projects and provide a migration path from our aging Kohana codebase to something more modern.

Last summer the development team at When I Work started to develop an open source framework that would be the basis for future projects and provide a migration path from our aging Kohana codebase to something more modern.

Originally we called it Spark. While we liked the idea of "starting something" it quickly became apparent that due to the plethora of projects already using the name Spark, not to mention a long standing Apache project, it was a poor choice.

The name Equip was chosen instead because it also represented something we value: being able to pick and choose useful tools without getting stuff we don't need.

If frameworks were knives, Equip would be a Santoku and most other frameworks would be a Swiss Army Knife. Without doubt, both will cut things, but the Santoku will be really effective at what it does. While multi-purpose tools are perfectly acceptable when you are prototyping and aren't sure what your business requirements will be in a week or a month or a year, it makes sense to choose something that offers a lot of flexibility and defines your architecture for you.

Standing on the Shoulders of Giants

Equip may be new but it is inventing very little. Like any good modern PHP framework it borrows from the best of the ecosystem in creative ways. The basic design of Equip is based around the ADR pattern with Auryn making dependency injection much easier. We use FastRoute for routing, Relay for middleware dispatching, and Whoops for exception handling.

Since Equip is based around PSR-7 we require an implementation that includes server requests. You can choose which vendor you want to use. Our current preference is Diactoros but Equip should work equally well with Slim if you wanted to mix frameworks.

The Bootstrap

I am really proud of our bootstrap. While some frameworks have big bootstraps and multitudes of configuration files, Equip has just public/index.php. It looks like this:

As a developer, you have complete control over this file. You can add new configuration, change middleware, and modify routing all in one. Configuration is just a list of classes, as is middleware. Both are executed in the order defined. Routing is done with a closure or any callable. Each of these steps are collected and then executed when run() is called.

Configuration

The first step of Equip bootstrapping is configuration of Auryn for dependency injection. Each of these classes receive the injector instance and apply specific configuration. If there are variable settings that are based on deployment, such as database credentials or service tokens, support for .env files is provided by the Equip\Env class. Injecting the Env class is super simple with the Equip\Configuration\EnvTrait.

Middleware

The next step of bootstrapping is to collect middleware. The middleware list is executed in the order added. Typically the last middleware is ActionHandler, which executes the domain code that was selected by routing and passes the payload generated by the domain to one or more formatters that prepare a PSR-7 response from the payload. Finally, the ResponseSender translates the response object into an HTTP response by sending the headers and body content.

Routing

The final step of bootstrapping is routing. The Directory is passed to a closure, which defines the actions that are responsible for specific HTTP method and URI combinations. Typically the action is defined just as the domain class that should be executed. It it also possible to pass a fully constructed Action class for control over the input that the domain receives and the responder for domain output.

Domains

In Equip, all application logic is executed with Domain classes. The domain receives all of the request input as a single $input array and returns a Payload object. The payload can contain a status, messages, and output that will ultimately be translated into a HTTP response. Within domain code there are no HTTP references. Authentication is handled in middleware, as is parsing request bodies. This allows domain code to be reused in other contexts and greatly simplifies testing.

Execution

When the run() method is called, configuration is applied to the injector and the middleware is executed by Relay. All of the heavy lifting is handled by dependency injection and middleware. Very simple and, in our experience, extremely effective.

Read the Docs

For more in depth explanation of how bootstrapping and the rest of Equip works, be sure to read the docs!

Present and Future

Late last week, we released Equip version 2.0.0. This is a significant milestone for us, as it represents nearly a year of refinement, enhancement, and tuning. Fundamentally, very little has changed since version 1.0.0. Our core dependencies haven't changed and domain level interfaces remain exactly the same.

I am quite proud of what we have accomplished since the last major release and feel that Equip is now a mature and stable micro-framework.

Looking forward, there are no set plans to make additional changes. At this point, it is unlikely that the framework will radically change until the PHP FIG standardizes a HTTP middleware interface. Even then, this will be mostly changes in configuration. Domain classes written today will likely work for years to come.

Equip More Tools

Equip provides a number of additional packages that can be useful in high performance applications, such as:

As When I Work continues to build production applications with Equip more tools may appear. We're currently working on some interesting REST authentication solutions that may be partially open sourced.

Conclusion

As your application grows so will your team. The struggle to provide high performance applications always comes up against architecture problems. Equip provides a minimal, effective, and clean structure without trying to dictate how your business logic should work. We hope it can be as powerful for you as it has for us.

]]>

The last 72 hours have been interesting to say the least. My rebuttal to Anthony's post have lead to some very interesting conversations. Among these is Andrew Carter's post entitled PSR-7 Objects Are Not Immutable in which he details how an exception handler middleware can generate a bad response body,

The last 72 hours have been interesting to say the least. My rebuttal to Anthony's post have lead to some very interesting conversations. Among these is Andrew Carter's post entitled PSR-7 Objects Are Not Immutable in which he details how an exception handler middleware can generate a bad response body, if the body was already written to.

Unlike the request and response interfaces, StreamInterface does not model immutability. In situations where an actual PHP stream is wrapped, immutability is impossible to enforce, as any code that interacts with the resource can potentially change its state (including cursor position, contents, and more).

The Dependency Problem

If we look at the code in question we see that Expressive writes directly to the body, rather than replacing it, effectively:

$response->getBody()->write($content);

Herein lies our dependency problem: there is no way to create a new stream instance unless we rely on a concrete implementation. The StreamInterface is mutable and has no method to create a new instance from some content. The MessageInterface::withBody() method requires that we pass it a stream. If we rely only on psr/http-message and allow the user to choose the implementation, we have no option other than to write directly to the existing stream.

Andrew states that this is a problem with PSR-7 and I don't necessarily disagree. The technical problem with streams is impossible to solve, which is why the FIG ended up with one mutable interface when all others are immutable. We cannot solve this problem directly, because that's simply the way PHP works. We can't rely on StreamInterface::rewind() because the stream might not be seekable.

The Factory Solution

Anthony was entirely right when he suggested that a factory would solve the "need a clean response" problem. Andrew is highlighting something that I have wrestled with and was unable to solve. I think the correct solution is to define a factory interface for PSR-7 objects. Packages that implement PSR-7 could also implement the factory and then we could do the correct thing in our code:

Problems with Factories

I still stand by my earlier statement:

The best dependency inversion we can have is not needing a container or factories.

In relation to factories, which are usually injected into the constructor, the problem is that we cannot enforce constructor arguments via an interface. Constructor signatures can be modified by extension without runtime errors. And to a lesser extent, return type enforcement is not possible before PHP 7.

While we have to acknowledge these problems, I still believe that factory is extremely useful and would be beneficial.

Conclusion

Not only would a factory solve the partial body problem, it would provide a better focal point for continued debate on PSR-7 middleware. Having a factory would make writing middleware more robust regardless of the interface that becomes standard.

If you have worked with a PSR-7 compatible microframework, you have almost certainly seen this signature already:

fn(request, response, next): response

What's to fight about?

Without question, the most divisive part of the proposed interface has the inclusion of the $response parameter. The perceived problem, as Anthony puts it, is this:

What does $response mean inside of the middleware?

From my perspective, the answer to this question is quite simple: The response is a instance of a response that may be clean or may have been modified.

Anthony does not disagree on this point and goes on to say:

The problem is that the actual meaning of the instance passed in depends on what outer middleware (middleware that was called before it) decided the meaning should be. This means that no middleware can actually trust what $response means.

And there is the source of the disagreement. I believe that we can, and should trust that the middleware we choose to use is doing the right thing. If we are unsure, we can easily validate it ourselves.

The Middleware Lifecycle

At this point, I think it would be useful to explain how the middleware lifecycle works, as I and others choose to implement it. Here is a very succinct diagram that comes from Slim Framework:

In terms of code, the basic premise is that you create a request instance, a response instance, and pass them into some kind of dispatcher that holds you middleware. In Equip the middleware is added via an application builder, in the index.php front controller:

The middleware is executed in the order added, so the ResponseSender is both the first entry and final exit point. The ActionHandler is executed last and returns first. All of these middleware components only depend on PSR-7 interfaces, not a specific implementation of those interfaces.

The World of HttpFoundation

Those that are opposed to the current proposal are almost universally users of Symfony HttpFoundation or their exposure to middleware comes from StackPHP which is based on Symfony HttpKernel. These users have, in my estimation, become used to the idea that they can create custom extensions of a concrete class and use them everywhere. If your entire object-oriented HTTP world is based around knowing that you can create an extension of Symfony\Component\HttpFoundation\Response and everything just works, then losing control of that ability seems scary.

The world we have with PSR-7 is better, precisely because we no longer need to rely on extension and concrete implementations. Instead, by inverting the choice of implementation to the developer using these components, we allow for greater freedom of choice and better interoperability. If the proposed PSR becomes a standard, anyone will be able to write middleware that type hints against a standard interface. Anyone who wants to use that middleware will be able to do so, with an entirely different implementation of PSR-7 than the author. Imagine a world where there is no "Slim middleware" or "Guzzle middleware", only "HTTP middleware". Anyone who uses PSR-7 will be able to choose from a huge ecosystem, similar to our huge ecosystem of Composer packages. We won't need to have 50 different implementations of HTTP caching that do the same thing, we can have a handful that serve specific needs.

But what about these pesky partial responses that are going to trip us up?

Exceptions in the Lifecycle

Time and time again, the concern brought up about not being able to trust the state of the response is raised. Some have described a situation where an error occurs somewhere during the middleware lifecycle and a partially complete or error response is generated with incorrect headers attached. Anthony uses the cache middleware as an example of this, because it applies cached headers to the response before executing the rest of the middleware stack. What Anthony and others do not consider is that there would almost certainly be an ExceptionHandler middleware that wraps later middleware.

Having an ExceptionHandler as part of your middleware stack is quite common. A typical exception handler middleware will look something like this:

The critical thing to note here is that the partial response is never used. If an exception occurs, the response that was passed to this middleware is decorated and returned. So long as your middleware stack has this middleware as close to the top as possible, a badly formatted response will never get decorated as an error. We don't need a factory to achieve this, because the functionality is already there. We don't need a concrete implementation, because it would hurt interoperability. The best dependency inversion we can have is not needing a container or factories.

Conclusion

And there you have it. These concerns about trust really boil down to not trusting that a developer knows what they are doing. By taking that stance we are throwing out the baby with the bath water. By inverting more control to developers, while providing an interface that reinforces this inversion, we are increasing the ability to share. This is good for interoperability and good for the PHP ecosystem. The front page of PHP FIG states the mission as:

Moving PHP forward through collaboration and standards.

This middleware standard would do both by building on the foundation of PSR-7 to enable further collaboration in the realm of middleware.

]]>

A while back I write Dependency Injection with Auryn which covered high level configuration of classes. It did not properly discuss how to handle situations where service location is necessary.

But Service Locators Are Evil!

You'll often hear this statement when talking with someone about dependency injection. In fact, Auryn

You should never, ever write this kind of code. If you discover it in a project, refactor it out as soon as possible.

A Necessary Evil

Sometimes service location is necessary to ensure that only the code needed is being loaded and executed. Routing to a controller based on the URL path is an obvious real world situation. We might have some routing code that looks like this:

Using it with Vim

Once the plugin is installed, it should Just Work. Open a file, add some trailing whitespace, save it and see the magic in action!

]]>

One of the best changes that I have recently ever made to my workflow has been reading Chris Beams' excellent How to Write a Git Commit Message. If you haven't read it, you should go do it right now and come back once you are done.

The Problem

One of the best changes that I have recently ever made to my workflow has been reading Chris Beams' excellent How to Write a Git Commit Message. If you haven't read it, you should go do it right now and come back once you are done.

The Problem

You're programming something and it seems to be working fine. You commit it and push it for QA to review. They come back with a problem that you didn't consider. You write a fix and push it again. Repeat this a few more times and you're starting to get frustrated and your commit messages start to look like this:

Fixed for real

And then a four hours later, when all you want is a beer:

I hate my life

Finally you get it working and the next day your code reviewer looks at your pull request and has a comment:

The Real Problem

You are not a bad programmer. You are just moving too fast and you had developed some bad habits because of it. As my favorite Zen quote goes:

You are perfect just as you are, and you could use a little improvement. – Shunryu Suzuki

What can you do to improve your commit habits?

The Solution

One of the most powerful features of Git is hooks. These little scripts can let us validate our changes using external tools, block us from committing, and check our commit messages for us. This can force us to slow down and be sure that what we are committing is what we really want.

Installing Static Review

Next you will want to allow globally installed Composer binaries to be used as normal commands. Edit your .bashrc or .zshrc or other shell configuration to contain the global bin path. It should look something like:

export PATH="$PATH:$HOME/.composer/vendor/bin"

Now you should have static-review.php available in your shell at all times. The next step will be to add the hooks to any Git repository that you want to do reviews on. To install the default file checks:

Conclusion

The excellent Static Review Git hooks help us have better habits by ensuring that we write good commit messages and follow best practices in our code. While it might seem annoying and slow at first, with time you will become aware of your mistakes as they happen, instead of being reminded by someone else later. By writing better code we help everyone that we collaborate with and maintain a high standard of quality throughout our projects.

In this situation, how valuable is it that we test every permutation of the constructor arguments? How would we test the difference between a ttl=60 and ttl=120? In the case of JWT we can decode the output and verify exact matches, but how valuable would that be? In my opinion, it is far more valuable to:

Defines what configuration is necessary to generate and validate tokens.

Ensure that token generation uses configuration correctly.

Starting from this position it is clear that the configuration would be better defined as a value object than as raw values. This changes our signature to:

Now we have a clearly defined value object that can be reused for both generation and validation without having to duplicate the values. If we need to add more options to the configuration we can do so without worrying that extended classes will no longer match signatures. And testing the generator becomes much easier because we can provide a mock object of the configuration to assert that the correct values are used at the correct time.

Binary Class Pattern

What I conclude from working through this particular code review and my own projects is that we can write better code by choosing to use only two types of objects:

Value Objects, constructed only with scalar values.

Collaborator Objects, constructed only with other objects.

Conclusion

By following a binary class pattern our code becomes easier to understand and more adaptable to change while also being more robust. We gain the ability to do independent testing of operation and structure while maintaining a clearer separation of concerns.

]]>

As someone who most often works with PHP I often find myself envious of the more advanced data structures that are present in a language like Python. As an experiment, I decided to see if it would be possible to bring some of those basic structures to PHP while also

As someone who most often works with PHP I often find myself envious of the more advanced data structures that are present in a language like Python. As an experiment, I decided to see if it would be possible to bring some of those basic structures to PHP while also preserving immutability. The result of this experiment is Destrukt.

Why immutable?

Before we talk about the structures themselves, let's talk about immutability for a second. Since PSR-7 decided to implement immutability there has a been a lot of buzz about it in the PHP community. The basic reasoning is this:

An immutable object cannot be modified by accident.

That might seem like a completely obvious statement or too trivial but this comes with a number of interesting "constraints" that help us write better code:

Passing objects to collaborators is completely safe. We no longer need to even consider the possibility that the object would be modified or put into an different state than before the call.

Changes are explicit. If we do want to allow a collaborator to modify an object, we can explicitly do so by reassignment:

$thing = $tustedObject->modify($thing);

This also has an extra benefit of making testing easier because complex objects do not need to be rebuilt as often.

Reasoning is simple. Because all objects are safe from modification by default, and all changes are explicit, a significant amount of cognitive load can be reduced by not having to follow complex method chains to see where changes occur.

Together these constraints actually give us greater freedom to do complex operations while worrying less about object state.

What is an array?

PHP is fairly unique among popular programming languages in that the array type can be used in so many ways. All of the following are arrays in PHP:

While this approach provides a great amount of flexibility it also makes it more difficult to validate data that is being passed through an application. What if someone forgets that this array is meant to be associative and uses $product[] = $description and suddenly the array is missing the product ID as a key and gets assigned a random number that refers to some other product? Not only is this a real possibility but it is nearly impossible to discover until a customer complains that the product they are adding to their cart is changing into something else.

By using more strict data structures, we can avoid these problems and have more testable code.

Each of these are standard data types that are commonly found in many programming languages. In destrukt, all of them can be created from a generic array and are validated. They can also be counted, serialized, encoded as JSON. Every structure is completely tested.

How are they used?

Using the structures is extremely easy once installed. For example, this is how you create and use a set:

Or if we want to overwrite the object with the copy, we just reassign it:

$set = $set->withValue('orange');

Once the set is created, we can just as easily remove values:

$set = $set->withoutValue('orange');

If we add a duplicate value to the set, nothing will be changed:

$copy = $set->withValue('apple');
var_dump($copy === $set); // true

But what if we try to create a set with duplicate values?

$set = new Set(['car', 'car', 'truck']);

This will throw an InvalidArgumentException because a set can only contain unique values! This ensures that the structures are always in a consistent state and helps prevent mistakes in application logic.

As of version 0.3.0, Set automatically removes duplicate values on create or when using withData. As was pointed out to me on r/php this is more consistent with other languages that have native implementations of sets.

Where's the data?

When you want to extract the underlying data from the structure, there are multiple options:

And the others?

The other data structures have very similar usage, with some minor differences. For instance, the Dictionary type takes a key and a value:

$dict = (new Dictionary)->withValue('dog', 'fetches ball');

The usage of the structures should be fairly intuitive and you can always read the tests for complete usage examples.

Conclusion

More advanced data structures offer some nice benefits and more safety when compared to simple arrays. By using immutability, our code is easier to reason about and less prone to side effects. Together immutable data structures offer significant benefits over using plain arrays to pass data through your application.

Once the injector is configured it can be passed to Spark for additional bootstrapping:

$app = Spark\Application::boot($injector);

This works well and does what we need. But we probably don't want to check this into source control with the database username and password exposed. And we might want to use a different database in development or testing than in production. A good solution to secrets is environment configuration.

Environment Variables

There are two common packages used to for environment configuration loading: josegonzalez/dotenv and vlucas/phpdotenv. Both are very similar, the primary difference at this time is that the package by josegonzalez is much more strict about where it declares the variables it loads from .env. In this example I'll be using the former.

Now we'll create a .env file with our database secrets in the project root:

db_database=demo
db_username=demo
db_password=secret

Since this file should never be added to git history, add it to .gitignore before proceeding:

$ echo ".env" >> .gitignore

Now we can use the env loader to parse this configuration in index.php. It is a good idea to add a check to make sure that anyone running the app will create a the .env file before we attempt to parse it:

This is quite simple and works okay when you only need to add one or two definitions, but what if you need to configure 5 or more classes? Or what if your test bootstrapping is different? Pretty quickly we will need a better way to configure the injector and the application. As @elazar pointed out to me, this can be done very cleanly with a configuration class. Let's see how it works.

Separation of Concerns

Instead of having all our configuration directly in the front controller, let's move it into a class that can be extended for more flexibility. This class will live in src/Configuration.php:

Now we can replace our configuration in index.php by using this class instead:

(new Spark\Project\Configuration)->apply($injector, $env);

With this structure, if we had some kind of special database configuration for a testing environment we could simply create a src/Configuration/Testing.php file and load it separately in the test bootstrap:

Conclusion

By using environment variables and classes to apply configuration we can keep our "front matter" separated from the application. In the process we improved security by keeping our sensitive configuration out of source control and gain all the benefits of inheritance and composition for injector configuration. This same technique could be applied to routing, logging, or other dynamic aspects of application configuration.

]]>

Dependency Inversion is Hard

One of the hardest things to do properly when following SOLID principles is Dependency Inversion. I struggled to understand and implement this concept for years. Often I wondered if it was really worth the trouble to write all of that extra configuration just to simplify testing.

Dependency Inversion is Hard

One of the hardest things to do properly when following SOLID principles is Dependency Inversion. I struggled to understand and implement this concept for years. Often I wondered if it was really worth the trouble to write all of that extra configuration just to simplify testing. And then I stumbled on Auryn and everything changed.

Service Locators vs Injectors

The first thing to understand about Aruyn is that it is not a service locator. This is an example of service location:

The primary problem with this approach is that you have absolutely no assurances as to what will come out of the get('db') call. It might be slightly better if we didn't use an alias and wrote:

$db = $this->container->get('PDO`);

This still has the same problem though: there is no assurance what will come out of the locator, even if we are theoretically using a class name. A cleaner approach is to use true dependency injection. Instead of injecting a container we can inject actual class instances on construction:

public function __construct(PDO $db)
{
$this->db = $db;
}

Now we can be absolutely sure that the database is an instance of PDO. If another class is used, the type hint will cause a fatal error and we will immediately know what is wrong. When we want to test this class, simply provide a mock PDO object and verify that the correct calls are being made.

Creating Instances

At this point, you may be wondering where the injected objects come from. The answer is deceptively simple: the entire dependency graph for a class is resolved as the object is created.

Once we have defined the PDO class, we can simply create anything that depends on it:

$users = $injector->make('UserRepository');

Notice that we didn't have to define the class before creating an instance of it? Auryn automatically resolves dependencies whenever it can by discovery with Reflection. So long as dependencies are managed properly there is very little performance impact.

Now what happens if we have another repository such as BookRepository? With the current configuration, every time a PDO dependency is seen, a new instance will be created. To prevent this, all we have to do is tell the injector to treat it as a shared instance:

$injector->share('PDO');

Now the same instance of PDO will be used everywhere!

Turtles All The Way Down

While this is the most basic usage of Auryn, even complex classes with multiple dependencies and sub-dependencies can be resolved with minimal effort. This is one of the main reasons that we choose to use Auryn when developing the Spark framework.

The Spark application is represented by $app and the addRoutes method takes a closure that receives the Router when the application is ready to begin routing. The router is based on FastRoute with some convenience added by having separate methods for creating different HTTP requests.

The first parameter of get is the URL path that will be matched. Anything wrapped with [brackets] is optional and anything wrapped with {braces} is a variable parameter.

The second parameter of get is the name of the Domain class that will be used to handle the request.