Coder Social home page Coder Social logo

retrofit-php-bundle's Introduction

Retrofit PHP Bundle

This Symfony2 bundle aims to provide an easy way to use the tebru/retrofit-php library. Please review the documentation for functionality.

Installation

composer require tebru/retrofit-bundle

As Retrofit does not include an http client, install Guzzle.

composer require guzzlehttp/guzzle

Add a line to your AppKernel.php

new Tebru\RetrofitBundle\TebruRetrofitBundle()

Usage

You will need to create providers for each API you want to consume. They should be created with the builder and return a RestAdapter. Here is an example:

<?php

namespace AppBundle;

use Tebru\Retrofit\Adapter\Rest\RestAdapter;

class FooBarRestAdapterProvider
{
    public static function get($baseUrl)
    {
        // setup additional dependencies like an http client here and use
        // the setters to add them to the builder
        
        // build the rest adapter
        return RestAdapter::builder()
            ->setBaseUrl($baseUrl)
            ->build();
    }
}

Create annotated interfaces. A simple example is shown below, more detailed examples are available here.

<?php

namespace AppBundle;

use Tebru\Retrofit\Annotation as Rest;

interface Foo
{
    /**
     * @Rest\GET("/get/{id}")
     */
    public function getFoo($id);
}

Everything else can be configured in your service definition. A yaml example is shown.

parameters:
    foo.class: AppBundle\Foo
    bar.class: AppBundle\Bar
    
services:
    # create a rest adapter
    foobar_rest_adapter:
        class: %tebru_retrofit.rest_adapter.class%
        factory: [AppBundle\FooBarRestAdapterProvider, get]
        arguments:
             - "https://foobar.com"
        
    # use the rest adapter to create clients
    # clients must be tagged with 'tebru_retrofit.register'
    foo_service:
        class: %foo.class%
        factory: [@foobar_rest_adapter, create]
        arguments: [%foo.class%]
        tags:
            - { name: tebru_retrofit.register }
            
    bar_service:
        class: %bar.class%
        factory: [@foobar_rest_adapter, create]
        arguments: [%bar.class%]
        tags:
            - { name: tebru_retrofit.register }

    # inject your client services anywhere
    baz:
        class: AppBundle\Baz
        arguments: [@foo_service, @bar_service]

Mocking

Because Retrofit uses interfaces, it's easy to create mock implementations if you do not want to hit a real API.

services:
    foo_service:
        class: %foo.class%
        factory: [@foobar_rest_adapter, create]
        arguments: ['AppBundle\MockFoo']
        tags:
            - { name: tebru_retrofit.register }
services:
    foo_service:
        class: %foo.class%
        factory: [@foobar_rest_adapter, create]
        arguments: [@mock_foo]
        tags:
            - { name: tebru_retrofit.register }

Take note of the arguments key in the above example. You may pass in a concrete class as a string or service to use that instead of the generated class. This is especially useful during development.

retrofit-php-bundle's People

Contributors

natebrunette avatar toxygene avatar

Stargazers

yāλu avatar Jesus Manuel Olivas avatar Jonathan Martin avatar Amine Matmati avatar

Watchers

James Cloos avatar  avatar

retrofit-php-bundle's Issues

Instructions do not lead to a working client

Guessing this is not compatible with Symfony 3.2 as all I get from the instructions is:

ClassNotFoundException in RestAdapter.php line 110:
Attempted to load class "GoogleTokenAdapter" from namespace "Tebru\Retrofit\Generated\OAuthBundle\RestAdapter".
Did you forget a "use" statement for another namespace?

I'm familiar with the square.io RetroFit for Java (and Android) and figured I'd use this for a PHP project I'm working on, but I can't get past the setup instructions.

Here's my services.yml

parameters:
    # Adapters
    o_auth.google_token.adapter.class: OAuthBundle\RestAdapter\GoogleTokenAdapter

    # Providers
    o_auth.google_token.provider.class: OAuthBundle\RestAdapter\GoogleTokenProvider

    # Services
    o_auth.google_credentials.class: OAuthBundle\Service\GoogleCredentialsService
services:
    # Services
    o_auth.google_credentials.service:
        class: '%o_auth.google_credentials.class%'
        arguments: ['%google.client_id%', '%google.client_secret%', '@foo_service']

    foobar_rest_adapter:
        class: '%tebru_retrofit.rest_adapter.class%'
        factory: ['OAuthBundle\RestAdapter\GoogleTokenProvider', 'get']

    foo_service:
        class: '%o_auth.google_token.adapter.class%'
        factory: ['@foobar_rest_adapter', 'create']
        arguments: ['%o_auth.google_token.adapter.class%']
        tags:
            - { name: tebru_retrofit.register }

Or, at least there are the parts that matter.

GoogleTokenAdapter:

interface GoogleTokenAdapter
{
    const BASE_URL = "https://accounts.google.com";

    /**
     * @Rest\GET("/o/oauth2/token")
     * @Rest\QueryMap("params")
     *
     * @param array $params
     *
     * @return
     */
    public function getToken(array $params);
}

GoogleTokenProvider:

class GoogleTokenProvider
{
    /**
     * Gets a RetroFit Adapter for Google oAuth Token Access
     *
     * @return RestAdapter
     */
    public function get()
    {
        return RestAdapter::builder()
            ->setBaseUrl(GoogleTokenAdapter::BASE_URL)
            ->build();
    }
}

GoogleCredentialsService constructor:

/**
     * GoogleCredentialsService constructor.
     *
     * @param string              $clientId
     * @param string              $clientSecret
     * @param GoogleTokenAdapter $tokenProvider
     */
    public function __construct(string $clientId, string $clientSecret, GoogleTokenAdapter $tokenProvider)
    {
        $this->client = new Client();
        $this->clientId = $clientId;
        $this->clientSecret = $clientSecret;
        $this->tokenProvider = $tokenProvider;
    }

Can't specify library separately.

If you specify the library separately, as recommended by the docs. If you do, you'll get a version conflict.

Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - tebru/retrofit-bundle dev-master requires tebru/retrofit-php 0.2.* -> no matching package found.
    - tebru/retrofit-bundle dev-master requires tebru/retrofit-php 0.2.* -> no matching package found.
    - Installation request for tebru/retrofit-bundle dev-master -> satisfiable by tebru/retrofit-bundle[dev-master].

Potential causes:
 - A typo in the package name
 - The package is not available in a stable-enough version according to your minimum-stability setting
   see <https://groups.google.com/d/topic/composer-dev/_g3ASeIFlrc/discussion> for more details.

Read <http://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.

Provider Service Factory has unecessary parameter.

The definition of the factory has a $baseUrl parameter that doesn't seem to be provided anywhere. Either this should be dropped and just manually specified (my preference) or the service configuration should specify how to set this.

    static public function get($baseUrl)
    {
        // setup additional dependencies like an http client here and use
        // the setters to add them to the builder

        // build the rest adapter
        return RestAdapter::builder()
            ->setBaseUrl($baseUrl)
            ->build();
    }

Cache clearing breaks when services change.

If you set up and use a working service, then change the definition of the service. The cache breaks and can no longer be cleared with the cache:clear command.

Steps to reproduce

  1. Create a valid service
  2. Warm cache
  3. Add an additional, valid, method to the service
  4. Attempt to clear cache, observe the following error:
PHP Fatal error:  Class Tebru\Retrofit\Service\NSGenerated_1acc84d6465b3c918d8baf845be4cc86\Generated_1acc84d6465b3c918d8baf845be4cc86 contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (FooService::newMethod) in ./app/cache/dev/retrofit/php_retrofit_cache.php on line 29

Fatal error: Class Tebru\Retrofit\Service\NSGenerated_1acc84d6465b3c918d8baf845be4cc86\Generated_1acc84d6465b3c918d8baf845be4cc86 contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (FooService::newMethod) in ./app/cache/dev/retrofit/php_retrofit_cache.php on line 29

Running cache:clear creates empty cache file

For some reason running the cache:clear command does not populate the cache file.

It appears to be running the warmup command. Look at whether compiling is happening, or it's bailing early for another reason.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.