Retrofit implementation in PHP. A REST client for PHP.

Related tags

HTTP retrofit-php
Overview

Retrofit PHP

Build Status Code Coverage Scrutinizer Code Quality SensioLabsInsight

Retrofit is a type-safe REST client. It is blatantly stolen from square/retrofit and implemented in PHP.

UPGRADE NOTICE

Version 3 introduces many breaking changes. Please review the upgrade guide before upgrading.

Overview

The following is for version 3, please check out the corresponding tag for version 2 documentation

Retrofit allows you to define your REST API with a simple interface. The follow example will attempt to display a typical use-case, but requires two additional libraries. The first uses Guzzle to make http requests as Retrofit does not ship with any default way to make network requests. The second uses a serializer (Gson) to hook into Retrofit's Converter functionality. This allows for automatic serialization of request bodies and deserialization of response bodies.

interface GitHubService
{
    /**
     * @GET("/users/{user}/list")
     * @Path("user")
     * @ResponseBody("App\GithubService\ListRepo")
     * @ErrorBody("App\GitHubService\ApiError")
     */
    public function listRepos(string $user): Call;
}

Annotations are used to configure the endpoint. Then, the Retrofit class generates a working implementation of the service interface.

$retrofit = Retrofit::builder()
    ->setBaseUrl('https://api.github.com')
    ->setHttpClient(new Guzzle6HttpClient(new Client())) // requires a separate library
    ->addConverterFactory(new GsonConverterFactory(Gson::builder()->build())) // requies a separate library
    ->build();
    
$gitHubService = $retrofit->create(GitHubService::class);

Our newly created service is capable of making GET requests to /users/{user}/list, which returns a Call object.

$call = $gitHubService->listRepos('octocat');

The Call object is then used to execute the request synchronously or asynchronously, returning a response.

$response = $call->execute();

// or

$call->enqueue(
    function(Response $response) { }, // response callback (optional)
    function(Throwable $throwable) { } // error callback (optional)
);
$call->wait();

You can then check to see if the request was successful and get the deserialized response body.

if (!$response->isSuccessful()) {
    throw new ApiException($response->errorBody());
}

$responseBody = $response->body();

Usage examples are referenced from Square's documentation

Installation & Usage

Retrofit 3 requires PHP 7.1

composer require tebru/retrofit-php

Please make sure you also install an http client.

composer require tebru/retrofit-php-http-guzzle6

Install a converter to handle more advanced request and response body conversions.

composer require tebru/retrofit-php-converter-gson

Documentation

License

This project is licensed under the MIT license. Please see the LICENSE file for more information.

Comments
  • feat(cache): support multiple versions of symfony/cache

    feat(cache): support multiple versions of symfony/cache

    Create a CacheProvider to create the appropriate instance of cache depending on symfony cache version. This is to support versions ^3.3|^4.0|^5.0 of symfony/cache (since 4.3, classes in Simple namespace are deprecated, and removed in 5.x)

    opened by Gounlaf 11
  • Is it possible to use lambdas as a callbacks instead of Callback object?

    Is it possible to use lambdas as a callbacks instead of Callback object?

    I found that retrofit-php supports asynchronous calls but as callbacks it requires an instance of \Tebru\Retrofit\Http\Callback Such a callback is OK in Java since it supports lambdas only starting from 8 version but it supports anonymous classes. In php though it's not OK because php supports lambdas very long time but it supports anonymous classes only starting from php7. So I need to create a class which implements Callback interface somewhere else then create an instance of this class and only after that pass it to my client function. It's very inconvenient. So I wonder if it possible to use success/failure lambdas to handle response asynchronously?

    opened by molchanoviv 7
  • Dynamic Headers

    Dynamic Headers

    It would be useful to set headers using logic instead of just being a simple string. One use case of this is to set X-Forwarded-For to the end user's IP.

    opened by mloberg 6
  • Update to Guzzle 6

    Update to Guzzle 6

    Updated the library to use guzzle 6 and the tests to rely on the PSR-7 messaging interfaces. All tests pass at this point, but there may be more work to do here.

    @natebrunette Do you see any other issues with this change? I can't find any places where the client interfaces leak out of the library, so it doesn't seem to cause any BC breaks. Do we currently allow service methods to return Response objects? That would be the only thing I could think of.

    | Q | A | | --- | --- | | Bug fix? | no | | New feature? | no | | BC breaks? | yes (php version req update) | | Deprecations? | no | | Fixed tickets | n/a |

    opened by ReneeVandervelde 6
  • Bump JMS Serializer to Latest Release

    Bump JMS Serializer to Latest Release

    This flies directly in the face of #22, but it'd be great to see the composer dependency for jms/serializer updated to ~1.0. Not sure what implications that has on the library, but suspecting that's a quicker thing to investigate than adding in all the adapters for serializer behavior that the other ticket will require.

    opened by ReservedDeveloper 5
  • Fix project tool binaries.

    Fix project tool binaries.

    Updated composer-wrapper to alpha-10 (required by config) fixed bin directory of 3rd party tools such as phpunit so they can be executed by calling bin/phpunit

    | Q | A | | --- | --- | | Bug fix? | no | | New feature? | no | | BC breaks? | no | | Deprecations? | no | | Fixed tickets | n/a |

    opened by ReneeVandervelde 5
  • Using @ResponseBody with arrays?

    Using @ResponseBody with arrays?

    Hello, I'm trying to use the ResponseBody annotation to transform a response that returns an array of objects. Does the annotation support array syntax? I was expecting to use something like…

    @ResponseBody("MyNamespace/MyClass[]")
    

    …but I'm getting a ResponseHandlingFailedException: "Retrofit: Could not convert response body" exception.

    opened by nrutman 4
  • Include request and response in the ReturnEvent

    Include request and response in the ReturnEvent

    This pull request updates the ReturnEvent to include the request and response.

    Justification The current mechanism to modify the response of a generated service is to use the ReturnEvent. There are use-cases where having the request and response may be necessary when subscribing to the ReturnEvent.

    For example: A request is made and the response includes headers containing valuable information. Adding the information from the headers to the returned data is necessary. A real-world example of this would be consuming the default Wordpress JSON APIs, which include pagination information only in response headers.

    opened by joesexton00 3
  • Support for optional query parameters

    Support for optional query parameters

    Currently, all @Query parameters are sent to the server, regardless of if they are required or not. It would be nice to be able to specify some @Query annotations as optional so they are not sent to the server if they are null.

    opened by toxygene 2
  • Bump symfony/cache from 4.1.4 to 4.2.12

    Bump symfony/cache from 4.1.4 to 4.2.12

    Bumps symfony/cache from 4.1.4 to 4.2.12.

    Changelog

    Sourced from symfony/cache's changelog.

    CHANGELOG

    5.1.0

    • added max-items + LRU + max-lifetime capabilities to ArrayCache
    • added CouchbaseBucketAdapter

    5.0.0

    • removed all PSR-16 implementations in the Simple namespace
    • removed SimpleCacheAdapter
    • removed AbstractAdapter::unserialize()
    • removed CacheItem::getPreviousTags()

    4.4.0

    • added support for connecting to Redis Sentinel clusters
    • added argument $prefix to AdapterInterface::clear()
    • improved RedisTagAwareAdapter to support Redis server >= 2.8 and up to 4B items per tag
    • added TagAwareMarshaller for optimized data storage when using AbstractTagAwareAdapter
    • added DeflateMarshaller to compress serialized values
    • removed support for phpredis 4 compression
    • [BC BREAK] RedisTagAwareAdapter is not compatible with RedisCluster from Predis anymore, use phpredis instead
    • Marked the CacheDataCollector class as @final.
    • added SodiumMarshaller to encrypt/decrypt values using libsodium

    4.3.0

    • removed psr/simple-cache dependency, run composer require psr/simple-cache if you need it
    • deprecated all PSR-16 adapters, use Psr16Cache or Symfony\Contracts\Cache\CacheInterface implementations instead
    • deprecated SimpleCacheAdapter, use Psr16Adapter instead

    4.2.0

    • added support for connecting to Redis clusters via DSN
    • added support for configuring multiple Memcached servers via DSN
    • added MarshallerInterface and DefaultMarshaller to allow changing the serializer and provide one that automatically uses igbinary when available
    • implemented CacheInterface, which provides stampede protection via probabilistic early expiration and should become the preferred way to use a cache
    • added sub-second expiry accuracy for backends that support it
    • added support for phpredis 4 compression and tcp_keepalive options
    • added automatic table creation when using Doctrine DBAL with PDO-based backends
    • throw LogicException when CacheItem::tag() is called on an item coming from a non tag-aware pool
    • deprecated CacheItem::getPreviousTags(), use CacheItem::getMetadata() instead
    • deprecated the AbstractAdapter::unserialize() and AbstractCache::unserialize() methods
    ... (truncated)
    Commits
    • 2828638 [Cache] forbid serializing AbstractAdapter and TagAwareAdapter instances
    • 2a139a2 [Cache] work aroung PHP memory leak
    • 02de00b Merge branch '3.4' into 4.2
    • 8c6e162 [Cache] replace getNsSeparator by NS_SEPARATOR on AbstractTrait
    • b71f045 [Cache] fix versioning with SimpleCacheAdapter
    • a3623f6 Merge branch '3.4' into 4.2
    • 717c286 SimpleCacheAdapter fails to cache any item if a namespace is used
    • 84fc8dc fixed CS
    • 4efb7fa fixed CS
    • 3bb8fd7 [Cache] Pass arg to get callback everywhere
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 1
  • Use `ReflectionNamedType::getName` instead of casting the type to `string`

    Use `ReflectionNamedType::getName` instead of casting the type to `string`

    Because the string casting is deprecated since PHP 7.4.

    As this project has PHP 7.1 as minimum and ReflectionNamedType::getName exists since PHP 7.1 it can safely be used.

    Fixes #81

    opened by jdreesen 1
  • Had to call `AnnotationRegistry::registerLoader()` manually

    Had to call `AnnotationRegistry::registerLoader()` manually

    For some reason every time the annotations were loaded while my cache was empty, they worked. Perhaps because my app was also loading @Route annotations at the same time.

    But once the cache was warmed, every subsequent load failed:

    AnnotationException::semanticalError('The annotation "@Tebru\\Retrofit\\Annotation\\GET" in method App\\Azure\\AzureSdkInterface::listDeployments() does not exist, or could not be auto-loaded.')
    in DocParser.php line 734
    

    I added this to my index.php and bin/console to make it work again:

    $loader = require dirname(__DIR__).'/vendor/autoload.php';
    AnnotationRegistry::registerLoader([$loader, 'loadClass']);
    
    opened by mattjanssen 1
Releases(v3.2.1)
Owner
null
Event-driven, streaming HTTP client and server implementation for ReactPHP

HTTP Event-driven, streaming HTTP client and server implementation for ReactPHP. This HTTP library provides re-usable implementations for an HTTP clie

ReactPHP 640 Dec 29, 2022
A PHP HttpClient for the Neo4j ReST API with MultiDB Support

NeoClient This repository has moved Neoxygen's NeoClient has been moved to https://github.com/graphaware/neo4j-php-client Version 3 of this library is

Neoxygen 120 Oct 19, 2022
PSR-7 HTTP Message implementation

zend-diactoros Repository abandoned 2019-12-31 This repository has moved to laminas/laminas-diactoros. Master: Develop: Diactoros (pronunciation: /dɪʌ

Zend Framework 1.6k Dec 9, 2022
A super lightweight PSR-7 implementation

PSR-7 implementation A super lightweight PSR-7 implementation. Very strict and very fast. Description Guzzle Laminas Slim Nyholm Lines of code 3.300 3

Tobias Nyholm 972 Jan 5, 2023
Guzzle, an extensible PHP HTTP client

Guzzle, PHP HTTP client Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and trivial to integrate with web services. Simple interf

Guzzle 22.3k Jan 2, 2023
PHP's lightweight HTTP client

Buzz - Scripted HTTP browser Buzz is a lightweight (<1000 lines of code) PHP 7.1 library for issuing HTTP requests. The library includes three clients

Kris Wallsmith 1.9k Jan 4, 2023
HTTPlug, the HTTP client abstraction for PHP

HTTPlug HTTPlug, the HTTP client abstraction for PHP. Intro HTTP client standard built on PSR-7 HTTP messages. The HTTPlug client interface is compati

The PHP HTTP group 2.4k Dec 30, 2022
Unirest in PHP: Simplified, lightweight HTTP client library.

Unirest for PHP Unirest is a set of lightweight HTTP libraries available in multiple languages, built and maintained by Mashape, who also maintain the

Kong 1.3k Dec 28, 2022
↪️ Bypass for PHP creates a custom HTTP Server to return predefined responses to client requests

Bypass for PHP provides a quick way to create a custom HTTP Server to return predefined responses to client requests.Useful for tests with Pest PHP or PHPUnit.

CiaReis 101 Dec 1, 2022
A PHP proxy to solve client browser HTTP CORS(cross-origin) restrictions.

cors-bypass-proxy A PHP proxy to solve client browser HTTP CORS(cross-origin) restrictions. A simple way to solve CORS issue when you have no access t

Gracious Emmanuel 15 Nov 17, 2022
Zenscrape package is a simple PHP HTTP client-provider that makes it easy to parsing site-pages

Zenscrape package is a simple PHP HTTP client-provider that makes it easy to parsing site-pages

Andrei 3 Jan 17, 2022
General purpose PHP SOAP-client

General purpose PHP SOAP-client Sick and tired of building crappy SOAP implementations? This package aims to help you with some common SOAP integratio

PHPro 695 Dec 26, 2022
Async HTTP/1.1+2 client for PHP based on Amp.

This package provides an asynchronous HTTP client for PHP based on Amp. Its API simplifies standards-compliant HTTP resource traversal and RESTful web

AMPHP 641 Dec 19, 2022
Simple HTTP cURL client for PHP 7.1+ based on PSR-18

Simple HTTP cURL client for PHP 7.1+ based on PSR-18 Installation composer require sunrise/http-client-curl QuickStart composer require sunrise/http-f

Sunrise // PHP 15 Sep 5, 2022
Goetas-webservices / soap-client

goetas-webservices / soap-client PHP implementation of SOAP 1.1 and 1.2 client specifications. Strengths: Pure PHP, no dependencies on ext-soap Extens

Goetas Web Services 173 Dec 11, 2022
HTTP header kit for PHP 7.1+ (incl. PHP 8) based on PSR-7

HTTP header kit for PHP 7.1+ (incl. PHP 8) based on PSR-7 Installation composer require sunrise/http-header-kit How to use? HTTP Header Collection Mor

Sunrise // PHP 63 Dec 31, 2022
Express.php is a new HTTP - Server especially made for RESTful APIs written in PHP.

express.php Express.php is a new HTTP - Server especially made for RESTful APIs written in PHP. Features Fast The Library is handles requests fast and

null 5 Aug 19, 2022
PHP Curl ile letgo api kütüphanesi oluşturuldu. php ile letgo giriş yap.

Kendi LETGO API ile işlemler gerçekleştirelim. // email işlemleri $server = 'imap.gmail.com'; $user = '[email protected]'; $pass = 'password'; $port = 9

Görkem Bayraktar 2 Nov 3, 2022
Requests for PHP is a humble HTTP request library. It simplifies how you interact with other sites and takes away all your worries.

Requests for PHP Requests is a HTTP library written in PHP, for human beings. It is roughly based on the API from the excellent Requests Python librar

null 3.5k Dec 31, 2022