shetabit / extractor
a `micro client` generator to communicate between `micro services` in laravel apps
Requires
- php: ^8.4
- guzzlehttp/guzzle: ^7.8.2|^8.0
- illuminate/console: ^12.0|^13.0
- illuminate/support: ^12.0|^13.0
Requires (Dev)
- larastan/larastan: ^3.10
- orchestra/testbench: ^10.0|^11.0
- phpcsstandards/php_codesniffer: ^4.0
- phpstan/phpstan: ^2.2
- phpunit/phpunit: ^11.5|^12.0|^13.0
- rector/rector: ^2.6
README
Laravel Extractor
Communicate with remote servers or microservices in an easy way.
All requests and responses can be cached and manipulated on runtime using middlewares.
This package requires PHP 8.4+ and supports Laravel 12+.
Donate me if you like this package 😎 ![]()
List of contents
Install
Via Composer
$ composer require shetabit/extractor
The service provider is registered by Laravel's package discovery, so there is nothing to add to config/app.php
(or to bootstrap/providers.php).
How to use
Send requests
you can send requests to remote API using Request class, see the below example:
// at the top use Shetabit\Extractor\Classes\Request; //... // create new request $request = new Request(); // set api's url and method $request->setUri($url)->setMethod('get'); // run the request and get data $response = $request->fetch(); var_dump($response); // show given response
as you see, you can work with remote API in an easy way.
the Request has more methods to add fields, headers and etc.
use Shetabit\Extractor\Classes\Request; //... $request = new Request(); # Example 1: $request ->setUri('http://your-site.com') ->setMethod('post') // add some headers ->addHeader('Authorization', "Bearer dfaerfaeaeva1351adsfaecva") ->addHeader('Accept', 'application/json') // add form parameters ->addFormParam('email', $email) ->addFormParam('password', $password); $response = $request->fetch(); // run request # Example 2: $request ->setUri('http://your-site.com') ->setMethod('get') // add query string ->addQuery('page', $page) ->addQuery('s', $search); $response = $request->fetch(); // run request
Send concurrent requests
you can send concurrent requests like the below
use Shetabit\Extractor\Classes\Request; use Shetabit\Extractor\Contracts\RequestInterface; // ... $request = new Request; $responses = $request ->createBag() ->addRequest(function(RequestInterface $request) { $request->setUri('http://google.com/'); }) ->addRequest(function(RequestInterface $request) { $request->setUri('http://bing.com/'); }) ->fetch();
Event listeners
you can set success and error listener for each requests seperately. here is another example that uses onSuccess and onError listeners.
use Shetabit\Extractor\Classes\Request; use Shetabit\Extractor\Contracts\RequestInterface; // ... $request = new Request; # Example 1: using on success $response = $request ->setUri('http://google.com/') ->onSuccess(function (ResponseInterface $response, RequestInterface $request) { echo $response->getBody(); }) ->fetch(); # Example 2: using on error $response = $request ->setUri('http://yahoo.com/') ->onSuccess(function (ResponseInterface $response, RequestInterface $request) { echo 'success'; }) ->onError(function (ResponseInterface $response, RequestInterface $request) { echo 'fail'; }); # Example 3: using request's bag $response = $request ->createBag() ->addRequest(function (RequestInterface $request) { $request ->setUri('http://google.com/') ->onSuccess(function (ResponseInterface $response, RequestInterface $request) { echo $response->getBody(); }); }) ->addRequest(function (RequestInterface $request) { $request ->setUri('http://yahoo.com/') ->onSuccess(function (ResponseInterface $response, RequestInterface $request) { echo 'success'; }) ->onError(function (ResponseInterface $response, RequestInterface $request) { echo 'fail'; }); }) ->fetch();
Middlewares
How to create
Middlewares can be created by running the below command
php artisan make:extractor-middleware test
The former command will create a middleware named test in app\Http\RemoteRequests\Middlewares path.
You can add a middleware to request like the below:
$request ->setUri('http://your-site.com') ->setMethod('get') ->middleware(new AuthMiddleware) ->fetch();
Multiple middlewares can be used by calling middleware method multiple times:
$request ->setUri('http://your-site.com') ->setMethod('get') ->middleware(new Test1) ->middleware(new Test2) ->fetch();
Each middleware has a handle method that can be used to handle requests and responses.
The following middleware would perform some task before the request is handled by the application:
public function handle(RequestInterface $request, Closure $next) : ?ResponseInterface { if ($user->name == 'john') { $request->addQuery('name', 'john'); } return $next($request); }
However, this middleware would perform its task after the request is handled by the application:
public function handle(RequestInterface $request, Closure $next) : ?ResponseInterface { $response = $next($request); // Perform action return $response; }
A middleware can also answer on its own, without letting the request through — return a ResponseInterface instead of
calling $next. Answering with null ends the request in a RuntimeException, since there is no response to hand back.
Global middlewares
You can use Request::withGlobalMiddlewares to add global middlewares.
global middlewares will be binded to all requests.
// in your AppServiceProvider protected boot() { Request::withGlobalMiddlewares([ // list of middlewares ]); }
in each request, you can unbind global middlewares, if you need them just use withoutMiddleware like the below:
// at the top use Shetabit\Extractor\Classes\Request; $url = 'http://google.com/'; $response = (new Request) ->setUri($url) ->withoutMiddleware(new TestMiddleware) ->fetch();
Cache
you can cache responses according to requests.
// at the top use Shetabit\Extractor\Classes\Request; $url = 'http://google.com/'; $ttl = 5; // 5 seconds $response = (new Request)->setUri($url)->cache($ttl)->fetch();
Notice: TTL (Time To Live) is the same as Laravel cache.
// at the top use Shetabit\Extractor\Classes\Request; $url = 'http://google.com/'; $ttl = now()->addMinutes(10); // 10 minutes $response = (new Request)->setUri($url)->cache($ttl)->fetch();
Conditional configs
Sometimes you need to add some configs when a condition happens, in this kind of situations you can use the when method to add conditional configs.
# Example 1: simple $request ->when('condition1', function($request) { $request ->setUri('http://your-site.com') ->setMethod('get') ->middleware(new AuthMiddleware); }); // Example 2: nested $request ->when('condition1', function($request) { $request ->setUri('http://your-site.com') ->setMethod('get') ->middleware(new AuthMiddleware); }) ->when('condition2', function($request) { $request ->setUri('http://shop-site.com') ->setMethod('get'); }) ->whenNot('condition3', function($request) { $request ->setUri('http://shop-site.com') ->setMethod('patch') ->when('condition4', function($request) { $request->setMethod('delete'); // sets method to delete }); }) ->fetch();
Client
You can encapsulate any request that exists between the current microservice and the remote microservice within a Client.
Create clients
Clients can be created using a simple command
php artisan make:extractor-client clientName
Clients will saved in app/Http/RemoteRequests/Clients by default.
lets create and example, imagine you have and remote Api (or microservice) and need to login into it.
then, your Login micro-client can be similar to below codes:
namespace App\Http\RemoteRequests\Clients\Auth; use Shetabit\Extractor\Abstracts\MicroClientAbstract; use Shetabit\Extractor\Contracts\ResponseInterface; class Login extends MicroClientAbstract { protected $mobile; protected $password; public function __construct($username, $password = null) { $this->username = $username; $this->password = $password; parent::__construct(); } /** * Get requests' endpoint * * @return string */ protected function getEndPoint() { return 'http://yoursite.com/api/v1/auth'; } /** * Run client * * @return ResponseInterface * @throws \Exception */ public function run() : ResponseInterface { $response = $this ->request ->setUri($this->getEndPoint()) ->setMethod('post') ->addFormParam('username', $this->username) ->addFormParam('password', $this->password) ->fetch(); return $response; } }
Run a client
you can run the Login micro-client like the below (we have Login client example at the top)
// dump data $username = 'test'; $password = 'something'; $client = new Login($username, $password); // run client and login into remote service (remote api) $response = $client->run(); // dump show response's body var_dump($response->getBody());
as you see, client starts to work as you call the run method, fetches and returns a response.
On progress features
- internal error exceptions
- resource and API resource clients
- proxy requests to another server (middleware)
Testing
Every pull request and every push to master is checked by GitHub Actions: the test suite runs on
PHP 8.4 and 8.5, against Laravel 12 and 13 and against both the lowest and the highest supported dependencies, the
coding style is checked with PHP_CodeSniffer, the sources are analysed with PHPStan (level 7, with larastan) and the
code coverage of the test suite is measured and has to stay above 95%.
The suite has two parts: tests/Unit covers the classes of the package on their own, and tests/Feature sends real
requests over a real connection to a stub server the suite starts (tests/Support/StubServer.php), which answers with
an echo of the request it received.
You can run the same checks locally. With PHP and Composer installed on your machine:
composer install composer test # run the test suite composer test-coverage # run the test suite and report code coverage composer check-style # check the coding style composer fix-style # fix the coding style where possible composer analyse # run static analysis composer ci # run all of the checks above
If you would rather not install PHP on your machine, the shipped Dockerfile and Makefile run everything inside a
container:
make test # run the test suite make coverage # run the test suite and report code coverage make check-style # check the coding style make fix-style # fix the coding style where possible make analyse # run static analysis make ci # run all of the checks above make shell # open a shell inside the container make help # list every available target
Another PHP version can be used with make test PHP_VERSION=8.5, and a single Laravel version with
make test-laravel LARAVEL=12.
Change log
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING and CONDUCT for details.
Security
If you discover any security related issues, please email khanzadimahdi@gmail.com instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see License File for more information.

