Download the PHP package x3p0-dev/x3p0-framework without Composer

On this page you can find all versions of the php package x3p0-dev/x3p0-framework. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package x3p0-framework

X3P0: Framework

Nova, a blue alien, as a construction worker wearing a toolbelt and holding a wrench in a city construction zone.

A lightweight, modern dependency injection framework for WordPress plugins and themes. Built with PHP 8.1+, it provides a robust DI container and abstract application layer to help you write cleaner, more maintainable WordPress code.

PHP Version

Features

Table of Contents

Requirements

Installation

Distributing a plugin or theme? Vendor-prefix your dependencies with a tool like PHP-Scoper so your copy of the framework can't collide with another plugin's.

Quick Start

The framework leans on declarative configuration: you describe what your providers contribute using class constants, list those providers on your application, and decide when registration and booting happen.

1. Define your services

Write plain classes. Constructor dependencies are autowired, so you rarely wire anything by hand.

2. Register them with a service provider

Prefer the declarative constants — SINGLETONS, TRANSIENTS, ALIASES, TAGS, BOOTABLE — over imperative calls. The base register() and boot() handle them for you.

3. Create your application

List your providers on the PROVIDERS constant. They're registered when the application is constructed.

4. Bootstrap it

The framework fires no hooks of its own — you choose when to register and boot. A typical plugin instantiates the application, fires a registration hook so third parties can add providers, then boots:

That's the whole loop. The rest of this document covers what each piece can do.

Service Providers

A service provider is the home for a slice of your project's wiring. Extend ServiceProvider and describe its contributions with constants. You only override register() or boot() when a binding needs real logic (a closure factory, a conditional, etc.).

When you need code

Override register() for bindings that need a closure or runtime decisions. The constant-driven bindings aren't processed by register() itself — a separate, final registerDeclarations() method handles them, and the application always calls it first — so nothing declared via the constants is lost, whether or not you override register() or call its parent:

Override boot() the same way when you need to do more than boot the BOOTABLE services — for example, hooking into WordPress. bootDeclarations() boots them first, regardless:

Provider dependencies

Providers given by class name are resolved through the container, so they can type-hint their own dependencies. Accept the Container, pass it to the parent, and add whatever else you need:

The Container

ServiceContainer is the framework's implementation of the Container contract. Inside a provider it's available as $this->container; elsewhere, via plugin()->container().

Binding services

The *If variants register a binding only if the identifier isn't already bound, which makes them ideal for defaults an extension may override regardless of load order:

The *When variants register a binding only if the given condition evaluates truthy, and register nothing at all otherwise — unlike *If, they don't guard against overwriting an existing binding:

A condition is a bool, a Closure invoked with the container, or any other callable — run through call() so it's autowired like any other container callback.

Re-binding an identifier with singleton()/transient() replaces any existing binding and clears its cached instance, so the replacement takes effect on the next resolution.

Resolving services

A parameterized make() (one given overrides) is never cached.

Autowiring

When the container builds a class, it resolves each constructor parameter from its type — including union and intersection types, falling back to a default value or null when a parameter allows it. Most classes need no binding at all:

Mark a class #[Singleton] to have the container share a single instance whenever it autowires the class, without an explicit binding:

Use #[SingletonWhen] instead when the shared lifetime should only apply conditionally — it takes the same kind of condition as singletonWhen():

Note: values that can't be constructed — enums, interfaces, and abstract classes — can't be autowired. Provide them with an explicit binding, a make() override, or an attribute (below).

Attribute-based injection

Parameter attributes configure how a single dependency is resolved, right where it's declared.

Attribute Target Injects
#[Get($id)] parameter the result of get($id)
#[Make($id, $params)] parameter make($id, $params) — resolves $id, honoring a cached singleton when $params is omitted
#[Defer($id)] parameter a Closure that resolves $id on each call
#[Tagged($tag)] parameter an array of the tag's resolved services
#[TaggedWith($tag, $attr)] parameter resolved services keyed by a chosen tag attribute's value
#[DeferTagged($tag)] parameter array<class-string, Closure> of deferred resolvers, keyed by abstract
#[DeferTaggedWith($tag, $attr)] parameter array<mixed, Closure> of deferred resolvers, keyed by a tag attribute's value
#[TaggedAbstracts($tag)] parameter the tag's unresolved abstracts, for building only what's needed
#[TaggedAbstractsWith($tag, $attr)] parameter unresolved abstracts keyed by a chosen tag attribute's value
#[Build($id, $params)] parameter build($id, $params) — a fresh, unshared instance with literal overrides
#[Param($name)] parameter a container-backed named parameter value set via setParam()
#[NoAutowire] parameter nothing — skips autowiring so the declared default (or null) is kept
#[Singleton] class opts an autowired class into a shared lifetime
#[SingletonWhen($condition)] class opts an autowired class into a shared lifetime when $condition is truthy
#[Tag($tag, $attributes = [])] class declares the class's own tag membership, applied via tagFromAttributes()

You can build your own by implementing ContextualAttribute:

Contextual bindings

Sometimes a single consumer needs a value that differs from the rest of the app — a scalar the container can't autowire, or a different implementation of an interface. Contextual bindings say "when the container builds this class, supply this for that parameter." The consumer is the concrete class being built.

Bind by parameter name to supply a value the container can't resolve by type (a scalar, an array). The name is given without a leading $, and the value is passed as-is — or, if it's a closure, its return value is used:

Bind by type to give one consumer a different implementation than everyone else. The concrete is a class-string resolved through the container (honoring its own binding, lifetime, and hooks), or a closure:

A contextual binding sits below an explicit make() override and any parameter attribute, but above ordinary type autowiring — so make(Mailer::class, ['apiKey' => '…']) still wins, and a binding registered for one consumer never leaks to another.

Named parameters

Named parameters give the container a place to hold scalar or array configuration values that any consumer can opt into by name — a lighter alternative to whenNeedsParam() for a value that isn't specific to one consumer.

A value is only injected when the constructor parameter is explicitly marked with #[Param] — matching the name alone is never enough:

If the named parameter was never set, resolution falls back to the constructor parameter's own default value or null (when nullable), the same way an unsatisfiable autowired type does.

Tagging

Tagging groups related abstracts under a label so they can be resolved together — blocks, widgets, REST controllers, CLI commands, and the like — without maintaining a master list by hand.

Tagged abstracts resolve through the container like anything else, so singletons stay shared and unbound classes are autowired. An unknown tag resolves to an empty array.

Method Returns
tag($abstracts, $tag, $attrs = []) — assigns one or more abstracts to a tag, optionally recording per-member attributes
tagFromAttributes($class) — assigns $class to every tag declared on it with #[Tag]
untag($abstracts, $tag) — removes abstracts from a tag
tagged($tag) the tag's services, resolved
taggedWith($tag, $attribute) the tag's resolved services, keyed by an attribute's value
taggedAbstracts($tag) the tag's abstracts, without resolving them
taggedAbstractsWith($tag, $attribute) the tag's abstracts, keyed by an attribute's value, without resolving them
setTagContract($tag, $contract) — declares that every member of $tag must be a concrete class of $contract
hasTag($tag) whether any abstracts are currently assigned

Because tags accumulate, several providers — or third-party code hooking your registration action — can contribute to the same tag without touching the provider that consumes it:

For large or expensive collections, pair a tag with #[DeferTagged] so consumers receive per-service resolver closures (keyed by class name) and build only what they need.

Tagging with attributes

tag() accepts an optional attribute map recorded alongside each member. Pair it with taggedWith() or taggedAbstractsWith() to look a service up by something other than its class name — a slug, say — instead of resolving the whole tag:

A class can declare its own tag membership with the #[Tag] attribute instead of a provider hand-wiring it. tagFromAttributes() reads the attribute and calls tag() on the class's behalf:

For a tag whose members should all satisfy one contract, setTagContract() validates every member — past or future — as a concrete class of it, catching a mistagged member as soon as it's added rather than at resolution:

Lifecycle hooks

Observe or transform services as they're built.

Introspection

The Application

Application is the hub that registers and boots your service providers. Subclass it, list providers on PROVIDERS, and drive the lifecycle from your plugin or theme.

Registering and booting

register() is variadic and accepts provider instances or class names. Class names are resolved through the container, so providers can declare their own dependencies.

boot() boots every registered-but-unbooted provider and is safe to call repeatedly — each provider boots only once. Once the application has booted, a provider registered afterward boots immediately, so nothing registered late is left dormant. A batch passed to register() is registered in full before any of it boots.

Multiple load phases

To register across more than one WordPress phase, call begin() to open each pass. It clears the booted state (so that pass's providers register as a batch before booting) and returns the application, ready to hand to a registration hook:

A single register-then-boot pass doesn't need begin(); it's required only to open each additional pass (and harmless on the first).

Contracts

The X3P0\Framework\Contracts namespace holds small, dependency-free interfaces.

Exceptions

All container failures surface as X3P0\Framework\Container\ContainerException; an unknown identifier throws NotFoundException (a subtype, so catching the base covers both). On the application side, InvalidProviderException is thrown when a registered class isn't a ServiceProvider, and UnbootableServiceException when a BOOTABLE entry doesn't implement Bootable. Both extend ApplicationException.

License

X3P0 Framework is licensed under the GPL-2.0-or-later license.

Credits

Created and maintained by Justin Tadlock under the X3P0 umbrella.

Support


All versions of x3p0-framework with dependencies

PHP Build Version
Package Version
Requires php Version >=8.1
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package x3p0-dev/x3p0-framework contains the following files

Loading the files please wait ...