Skip to content

Tutorial

Jason Napolitano edited this page Feb 13, 2026 · 67 revisions

Installing and configuring Framework Factory is very easy to do. This tutorial will walk you through the process of creating an application, installing Framework Factory, configuring your application to use it and show how to utilize its core features.

Requirements

The following requirements must be met in order to install and subsequently use Framework Factory.

  • Composer must be installed and properly configured
  • PHP 8.5 or greater must be installed

Project Setup

This step will walk you through a basic composer application setup process. If you already know how to setup a composer project, you can skip to the * installation* step below.

  1. Create your project's directory and cd into it.
  2. Create your composer project by running composer init in a terminal window and follow the prompts. At the end, it will generate a composer.json file that will look something like this:
{
  "name": "your-name/project-name",
  "description": "My first Composer project",
  "type": "project",
  "license": "MIT",
  "require": {}
}

Installation

  1. Now, we are going to install Framework Factory. In the root of your newly created project, run the following command:
composer require framework-factory/core

Project structure

  1. Create the following directories and files in your project.
|-- poject_root
|---- app\
|------- Accessors\Message.php
|------- Providers\MessageServiceProvider.php
|------- Services\MessageService.php
|---- bootstrap\app.php
|---- composer.json
|---- composer.lock
  1. Add the App namespace and the bootstrap/app.php to composer's autoload section.
{
  "name": "your-name/project-name",
  "description": "My first Composer project",
  "type": "project",
  "license": "MIT",
  "require": {},
  "autoload": {
    "psr-4": {
      "App\\": "app"
    },
    "files": [
      "bootstrap/app.php"
    ]
  }
}
  1. In your terminal window, run the following script:
composer dump-autoload -o

Configuration

Now, we are going to configure our project to use Framework Factory. The steps below will help us get our project started.

Initial bootstrap file

  1. First, we will want to go to the newly created bootstrap/app.php file and start by adding the following code:
use FrameworkFactory\Application;

// build the application
$app = Application::build(basePath: __DIR__ . '/../');
  • First thing we are doing is creating (building) the application and assigning it to the $app variable. This is how we will access the FrameworkFactory\Application API to add version control and service providers before we fire() the application up.
  • You'll notice that we are passing a basePath argument through. This is the exact file path that the our project resides in.

Customization

Framework Factory offers methods of customizing the core application before being bootstrapped. We will look into these customization options below.

Version Control

One of those methods, is to assign an application version. This step is completely optional and can be omitted. The application version defaults to null. Adjusting the application version can be done by passing its string value through the asVersion() method on the $app instance:

$app->asVersion('1.2.3');

If we want to return our version number later on in our application, we can do so by calling the version() helper method from the Application class:

return FrameworkFactory\Application::version(); // 1.2.3

Adding Providers

When building our application we will want to inject, or bind, services to our container. This will allow us to call these dependencies later on. In order to add the services, we must load them via service providers. Service providers grant us a way to contain and configure individual services, or groups of services. Once a provider has been created you will have access to methods which allow a service to be interacted with before, during, and after it has been loaded into the container.

There are two types of service providers we can create. There is the standard service provider, which gets instantiated when the container is built. Then there are deferred service providers which get loaded when the service is called. In order to defer a service provider, we must add it to the container using the singleton() method on the container instance and return the provides() method with the key(s) of the service(s) the provider knows about.

If we simply want to load a service into the container upon its creation, we would call the bind() method instead of singleton(), and omit the provides() method.

Below, we are using the deferred approach.

Updating our provider

  1. First, let's go to the App\Providers\MessageServiceProvider file we created earlier, and modify the code to represent the following:
namespace App\Providers;

use FrameworkFactory\Contracts\Providers\ServiceProvider;
use App\Services\MessageService;

class MessageServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->container->singleton('message', fn() => new MessageService());
    }

    public function provides(): array
    {
        return ['message'];
    }
}
  • In the class above we are extending the ServiceProvider base class. This will grant access to the resources required to register the service provider, give us access to lifecycle hooks and allow us to utilize the Context API.
  • Next we are creating the register() method. This method gives us access to the container instance, and allows us to bind a service to the container. In this example, we are creating a singleton instance of the service.
  • You'll also notice the provides() method being implemented. When we do this, we are telling the container that we want to "attach" any services created in this provider to the container instance, whose aliases / ID's are provided in that array.

Updating our service

In the following step, we are going to update our MessageService class by adding a method that we will want to call later on from within our codebase. After this step has been done, the MessageService class should look like we see below:

namespace App\Services;

class MessageService
{
    public function display(string $message): string
    {
        return $message;
    }
}

Updating the bootstrap file

Next we will perform the steps required to add the provider to the container. Let's go back to the bootstrap/app.php file, and modify it to represent the following:

use App\Providers\MessageServiceProvider;
use FrameworkFactory\Application;

// build the application
$app = Application::build(basePath: __DIR__ . '/../');

$app->withProviders([
    MessageServiceProvider::class
]);

// ...

With this step complete, the service provider has now been registered and the service(s) it contains to are loaded into the container.

Bootstrapping

Now that we have built our service provider and our service class and loaded them into the container, we are ready to bootstrap the application. This is done by calling the fire() method on the app instance. We will now go back to our bootstrap/app.php file and add the following line to the end of the script, to initiate this process:

// ...

$app->fire();

What we are doing here, is firing up the bootstrap process, therefor completing the last steps to get the application setup. Once this line has been added, the completed bootstrap/app.php file should represent the following:

use App\Providers\MessageServiceProvider;
use FrameworkFactory\Application;

// build the application
$app = Application::build(basePath: __DIR__ . '/../');

$app->withProviders([
    MessageServiceProvider::class
]);

$app->fire();

Once we run the application, the cache file will be created at bootstrap/cache/app.php. This will be used to load any services upon later execution.

Accessing Services

Once our application has been built and our service providers have been loaded, we will want to call those services later on. There are two main ways to perform this task. We will look at both methods below.

Accessors

In short, accessors act as facades. They allow us to tap into the container and retrieve services that have been loaded into it. Below, we will see an example of how to create, and utilize, an accessor class.

Creating an Accessor

First, we will want to open the App\Accessors\Message class we created earlier on and modify it to represent the class below.

namespace App\Accessors;

use FrameworkFactory\Application\Accessor;

/**
 * @method display(string $message)
 */
class Message extends Accessor
{
    protected static string $key = 'message';
}

You'll see that in the class above, we are doing a few of things.

  • First, we are extending FrameworkFactory\Application\Accessor. This base class has access to the container, and grants us the facade features we need to statically call the service later on.
  • Next, we are adding a type hinted method in the classes DocBlock called @method display(...). This represents the display(...) method we have in our MessageService class that we created earlier. This method allows our IDE to offer code completion when we are calling our accessor from within our codebase.
  • Lastly, we are assigning a value to the $key property. The value we assign to this property, is the same value that we assigned to our service as we loaded it into the container when we created our MessageServiceProvider. This key assignment tells the container which service(s) to load, and from which service provider.

Using an Accessor

Now that our accessor class has been created, we are able to use it within our application. To do this, we simply need to call it like we see below:

use App\Accessors\Message;

$message = Message::display('This is the message we are displaying');

echo $message; // 'This is the message we are displaying'

Helper function

Using the helper

Framework Factory gives us access to the container by way of a helper function. The get(...) helper function is available and helps us tap into the container to retrieve services that have been loaded into it. The use this feature, we will do the following.

use function FrameworkFactory\Helpers\Container\get;

/** @var \App\Services\MessageService $message */
$message = get('message');

echo $message->display('This is the message we are displaying'); // 'This is the message we are displaying'
  • In the script above, we are first importing the get() function from the container helper file. We are passing through the key that we'd assigned to the service within the MessageServiceProvider class we created earlier.
  • Next, we are assigning the function to the $message variable, with a type hinted comment telling our IDE which class that $message is referring to.
  • After that, we are accessing the MessageService's display(...) method, and returning its output.

TBC