Download the PHP package antonioprimera/bapi without Composer

On this page you can find all versions of the php package antonioprimera/bapi. 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 bapi

BAPI - Business API

BAPI stands for Business API and is like an Action on steroids:

Just to clarify:

For example a BAPI for adding a car part to the inventory would be called like this:

The BAPIs are not meant to replace the controllers, but to be used by the controllers and other methods handling the business logic of your application (e.g. Livewire forms, Jobs, Commands etc.).

Why BAPIs?

If you have ever developed an application, you know that the logic tends to get more complicated with each functionality you add and with each user requirement.

In order to be able to rely on the previously written bits of business logic whenever using them in a more complex workflow (a list of steps), you should split them into atomic, reusable business steps and make sure they are thoroughly tested. Each such step can be implemented in a dedicated BAPI.

Usage

Installation

Import the bapi package through composer:

Creating a new Bapi

An artisan command to create a new Bapi will be available after installing the package.

For example, you can run the following artisan command in your console in order to create a new Bapi in app/Bapis/Posts/CreatePostBapi.php:

Advanced Bapi generation

Always create complex Bapis

This will create a new basic bapi class, in the app/Bapis folder of your Laravel app. If you wish to create a slightly more complex bapi class, with all the hooks and methods, you should use the --full flag on the command above.

If you want to always create complex bapi classes for your project, without always using the --full flag every time, you can add the following setting to your .env file:

Custom base class to be inherited by the generated Bapis

By default, the base Bapi class, inherited by the generated Bapis is AntonioPrimera\Bapi\Bapi. If you have another base class in your project, you can add it to your .env file like so:

TDD: create a test file for your BAPI

You have several options to let the make:bapi command create a unit test for your new bapi:

Implementing your Bapi & the Bapi run lifecycle

Whenever you instantiate the bapi, the setup() method is called, if implemented. By default, the setup method is not implemented. If you call the run method statically (check the chapter about running your bapi), an instance is created in the background, so the setup method will always be called, if implemented.

When you run your bapi, the following methods will be called, in exactly this order:

  1. authorize()
  2. validate()
  3. handle(...)
  4. processResult(mixed $result): mixed

The arguments provided when calling the BAPI run method must be named arguments and will be available throughout the entire lifecycle, directly on the Bapi instance, using the argument name from the handle method.

For example, if you want to call an UpdatePostBapi like this...

...your handle() method, must look something like this...

...then, when running your bapi, via the run() method, the arguments will be available as instance attributes inside all the Bapi methods, so you can use them like this...

In the end, the result of the handle() method will be provided as an argument to the processResult() method, which allows you to do any transformations and post-processing of the result. The return value of the processResult() method will be returned by the BAPI run(...) method. If you need, you can override the processResult() method and change the result of the Bapi, before it is returned.

Running your Bapi

You can call your bapi using the run() method, either statically or as an instance method after instancing your bapi. The run method doesn't exist in the Bapi and you should not create a run method. This call is intercepted by the corresponding magic method and the bapi run lifecycle is started. DO NOT CREATE a run() method in your bapi. The main business logic should go into the handle() method.

You can also invoke the Bapi if you prefer.

For example, if you have the UpdatePostBapi in the example above, you can call it in any of the following ways.

Skipping the authorization check

Sometimes, when you have a more complex scenario, where a bapi calls other Bapis as part of the business logic, you might want to do all necessary authorization checks in the complex Bapi and run the other Bapis inside, without an authorization check (it might be just a redundant check).

If you want to skip the authorization check, you can call the withoutAuthorizationCheck() method either statically or as an instance method.

For example, if you want to call the bapi in the previous example without running the authorization check, you could do the following:

While this is possible, it is risky, because Bapis should be atomic bits and pieces of code and should be completely independent. Thus, if a bapi calls other Bapis, which in turn call other Bapis and so on, it will be hard to ensure that every bapi covers all necessary authorization checks. This also rises the risk for duplicated authorization logic. There is no universal rule regarding the structure and authorization of your Bapis, so just use common sense and make sure to test your Bapis thoroughly, otherwise you miss the main benefit of the Bapis and might be better off using single file actions or just plain php classes, because these are easier to implement and understand, and they contain less magic.

Although you might never use it, a withAuthorizationCheck() method is available and can be called to re-enable the authorization check if it was disabled previously for a Bapi instance.

Skipping DB transactions

If you want to run a BAPI without a database transaction, you can call the withoutDbTransaction() method either statically or as an instance method.

For example, if you want to call the bapi in the previous example without running the database transaction, you could do the following:

While this is possible and necessary in some cases, it is risky, so you should use it with caution.

If you want to completely disable the database transaction for a Bapi, you can set the $useDbTransaction property to false in the Bapi class, overriding the default value.

If you want to completely disable the database transaction for all Bapis, you can create a new base class for your Bapis and set the $useDbTransaction property to false in that base class. Then, you can set the BAPI_GENERATOR_BASE_CLASS environment variable to point to your new base class, so that all Bapis will inherit from it.

Validating the business data

While the controllers are responsible to validate user input data, these validations are usually not enough for complex business processes. Business validations are usually more complex and should be implemented together with the business logic, inside the Bapi, in the validate method.

If the validation passes, the validate() method must return boolean true. Any other return value, will be wrapped in a BapiValidationException, which will be thrown.

You can also throw a BapiValidationException directly from the validate() method.

BapiValidationIssue and the BapiValidationException

Whenever a Bapi validation issue occurs, you should generate a BapiValidationIssue instance, which you can pass on to the thrown BapiValidationException.

Each BapiValidationIssue must contain the name of the attribute that generated the issue, its value and the issue that occurred, as an issue code (e.g. "AGE-LT-18") as free text message ( e.g. "User is not of legal age!") or as a translation key (e.g. "exceptions.age.notLegal").

After generating one or more bapi validation issues, you can either throw a new BapiValidationException with these issues, or you can return an array of BapiValidationIssue instances from the validate() method.

By using these Bapi Validation Issues and the BapiValidationException, you can render a proper response in the \App\Exceptions\Handler::register() method of your application.

Another way to render a universal response for your business validation exceptions is to create a subclass of the BapiValidationException and implement the render() method. For this, you can check the Laravel documentation on Error Handling

Validating attributes

If you want to validate attributes and throw a ValidationException, like the form validation does, you can add the ValidatesAttributes trait to your Bapi. This trait overrides the default exception hadling mechanism in Bapis and transforms BapiValidationExceptions containing BapiValidationIssues into ValidationExceptions, which are handled by the default Laravel exception handler.

Concretely, this means that if you add the ValidatesAttributes trait to your Bapi and return a BapiValidationIssue or an array of BapiValidationIssues from the validate() method, a ValidationException will be thrown, which will add the validation issues to the $errors variable, which is available in the views.

For example, if you would want to validate the company name, you could do something like this...

... and then in your form, you would be able to display an error message for the company name, like this:

Authentication & Actors

The Bapi instance offers the public actor() method, which is just a wrapper for the Auth::user() method.

Calling a normal BAPI internally (from another BAPI)

Some Bapis should be called in controllers, maybe even blade views (e.g. when using Laravel Livewire), and these Bapis should always have an authorization check and should usually run inside a DB Transaction.

Other Bapis can also be called internally, from inside another bapi, which already started a DB transaction and handled the authorization check. When called from another bapi, a bapi should not run a DB transaction and should not do any other authorization checks by default (unless specifically requested to).

In order to use a Bapi internally, you should remove the authorization check or have it return false (so that when called from outside, it will fail) and always call it from another Bapi using the call(...) method instead of run(...).

For example, if you have a CreatePostBapi and you want to call a CreatePostNotificationBapi from inside the CreatePostBapi, you should do something like this:

If you want to call a bapi internally, but force the authorization check to run, you can use the callWithAuthorizationCheck(...) method.

Creating BAPIs which can only be called internally

In some cases, you want some BAPIs to only be called by other BAPIs and never from Controllers, Jobs, Commands, Blade views or other parts of your application. In order to achieve this, you can extend the InternalBapi class instead of the Bapi class.

These exclusively internal BAPIs will not run an authorization check, will not run within a DB Transaction and do not handle any Exceptions. They still offer validation and handling the result, using the same lifecycle as the normal BAPIs.

You can create an internal bapi using the same artisan command, with the "-I" or "--internal" flag.

Testing internal Bapis

Because internal bapis can only be called internally, you need a helper in order to test them. You can use the AntonioPrimera\Bapi\TestInternalBapi class to test your internal Bapis.

For example, if you have an internal bapi called CreatePostBapi (inheriting the InternalBapi class), you can test it like this:

Note that you must provide the full class name of the internal bapi as the first argument, followed by the named arguments you want to pass to the bapi. This helper will not run with classes other than Internal Bapis or outside the testing environment.


All versions of bapi with dependencies

PHP Build Version
Package Version
Requires php Version ^8.2
illuminate/support Version >=11.0
illuminate/console Version >=11.0
antonioprimera/laravel-generator-command Version ^2.4|^3.0
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 antonioprimera/bapi contains the following files

Loading the files please wait ....