[HN Gopher] Laravel Transporter
       ___________________________________________________________________
        
       Laravel Transporter
        
       Author : mooreds
       Score  : 35 points
       Date   : 2021-06-24 13:39 UTC (9 hours ago)
        
 (HTM) web link (www.juststeveking.uk)
 (TXT) w3m dump (www.juststeveking.uk)
        
       | zerof1l wrote:
       | I don't see value in using this wrapper library over Laravel's
       | HTTP Client or Guzzle. What Laravel includes is more than
       | adequate already. Also, I never hardcode URLs and tokens. There's
       | a config in Laravel for that. Nobody is going to call Guzzle or
       | HTTP directly every time anyway. It will be a Service or a Client
       | class that exposes each endpoint as a method and abstracts all
       | underlying logic.
       | 
       | What's more important when doing API implementation seriously is
       | defining and enforcing API contract and getting an exception as
       | soon as the contract is broken. I'm thinking about something
       | similar to BaseModel from pydantic in Python. This library
       | provides nothing of this kind.
        
       | preya2k wrote:
       | Please fix the contrast ratio of quotes and inline code segments
       | in dark mode on this website. It's black text on dark blue
       | background, which is barely readable.
        
       | cortexio wrote:
       | Hmm, baseurl shouldnt be a setting foreach request. And i think
       | ctrl+c / ctrl+v is probably as fast as using a generator.
        
       | grzes wrote:
       | totally agree with other commenters - guy just over-engineered
       | non-existent problem
        
       | spheroidmethod wrote:
       | I do appreciate the structural parity that this has with
       | Laravel's Eloquent ORM models--that is, a class to represent a
       | specific database resource. It makes API requests feel like a
       | close analogue to that Laravel-esque functionality.
       | 
       | That said, REST API endpoint are effectively just functions--you
       | pass in params, you get a response. They only have a single
       | operation possible on them, unlike ORM models which can do many
       | things.
       | 
       | Whenever I've implemented a custom API client in PHP, boring old
       | OOP seems to solve the problems stated in the article reasonably
       | well:                 class ApiConsumer {         function
       | __construct($baseUrl, $credentials);         function
       | operationFoo($paramOne, $paramTwo): FooResponse;         function
       | operationBar($paramOne, $paramTwo): BarResponse;       }
        
       | chipotle_coyote wrote:
       | I'll half-agree and half-disagree with other comments, I think.
       | 
       | First, I think this _is_ a clever way to wrap API requests in
       | what strikes me as the modern PHP style, which these days seem to
       | largely driven by the de facto standards of PHP-FIG in general
       | and Laravel and Symfony in particular. Use a CLI tool to generate
       | a class that extends your base class and adds configuration,
       | extend _that_ class to build new more granular methods, maybe
       | make a static facade to call everything. This is just super
       | Laravel-ish and absolutely what I expect from modern PHP apps in
       | 2021.
       | 
       | Second, it _is_ overengineered, because _that is what modern PHP
       | apps do._ Spend a bit of time tracing just how much goes into
       | encapsulating a PSR-7-compliant request, and think about how
       | often code that 's using those requests literally doesn't need
       | anything more than the $REQUEST superglobal. (Gasp! They said
       | "global!" Think of the children!) It's great to have standards
       | for packages, but it seems like I'm spending way, way more time
       | -- and occasionally writing more actual code -- figuring out how
       | to do things The Right Way (tm).
       | 
       | In the argument for Laravel Transporter, Mr. McDougall shows a
       | bit of pretty clear code and then says, "But, this is very
       | procedural." I mean, yes? It's kind of a procedure? "What happens
       | if the URL changes? What happens if the query parameters change?"
       | If I was insistent on wrapping this up in a class, I'd probably
       | just _write an API class_ that you call with something like
       | $api = new FooApi();         $todo = $api->getCompletedTodos();
       | // or if I am feeling all static         $todo =
       | Api::getCompletedTodos();
       | 
       | and if the URL changes or the query parameters change, I still
       | basically only have one place to change it.
       | 
       | I'm not saying I pine for the days of 100% Procedural All Pasta
       | All The Time. I'm just wondering whether maybe PHP developers
       | should spend some more time with languages that not only aren't
       | PHP, but aren't Java, then come back to PHP -- and start
       | questioning the orthodoxy a little.
        
         | dgb23 wrote:
         | On the other hand PHP has this wonderful feature in associative
         | arrays. Easily serializable, fast, deep equality, plain and
         | simple, generic and flexible data structures that seamlessly
         | convert to JSON (and thus schema) and have well supported
         | language constructs.
        
       | Liquidor wrote:
       | Isn't this package just a different solution for a Repository
       | Pattern?
       | 
       | Create a repository class which contains all the objects and
       | methods for the API and then use this repository as a bridge
       | between the API and your controllers.
       | 
       | Business and data access logic can be tested separately and it's
       | easier to maintain.
        
       | mtnGoat wrote:
       | I deal mostly in PHP and never thought that making API requests
       | was hard. Am I lost?
       | 
       | The hard part is dealing with the fact that APIs are not
       | standardized, even within the same company.
        
         | deweller wrote:
         | It is not difficult but it can end up being more hard-coded
         | than it should be.
         | 
         | The author of this package is attempting to help Laravel users
         | standardize their API client code and centralize those hard-
         | coded bits in one place.
         | 
         | It isn't groundbreaking, but it could be useful in larger
         | projects or across several projects.
        
           | 9dev wrote:
           | My feeling is the opposite- this is just overengineering,
           | adding more code to test and maintain. The simple solution is
           | what countless others have suggested - build a simple client,
           | configure it using standard Laravel mechanisms and dependency
           | injection. An API Call is just a method on the service class.
        
       | debarshri wrote:
       | A bit more standard way of generating HTTP API clients, would be
       | to use openapi spec [1] and then generate php client. It makes
       | you app client independent of framework and also language itself.
       | 
       | [1] https://github.com/OpenAPITools/openapi-generator
        
         | mradmin wrote:
         | This is the approach I use, but I've always found some sort of
         | issue in every generator I use. A valid openapi spec does not
         | imply a generator will be able to handle it. You'd think have a
         | specification would mean the generators are "bug free" but it's
         | not the case, and bug reports are lost in a sea of issues:
         | https://github.com/OpenAPITools/openapi-generator/issues so i
         | don't see things improving anytime soon.
         | 
         | I've also wondered if the "logic-less" template approach is the
         | right approach for these generators. You can't fix bugs or add
         | workarounds just by providing a custom template, you need to
         | change the underlying Java code to provide the correct data
         | models to the logic-less templates.
        
       | rob74 wrote:
       | I find the naming of "Laravel Forge" a bit unfortunate. When I
       | read code like "use App\Transporter\Forge\ForgeRequest", one of
       | two things come to mind:
       | 
       | - "what's a Forge? Is this a fancy name for the Factory pattern?"
       | 
       | - "are they forging (as in forgery) requests here? Or further on,
       | 'services.forge.token' - sounds strange?!"
        
       | jpswade wrote:
       | This feels like over-engineering a problem at it's finest. Taking
       | 3 lines of ubiquitous code and abstracting in a new way, when it
       | already does what you need out of the box.
       | 
       | The base url and header details such as api token can all be set
       | in the client in an OOP way already[1]
       | 
       | > What happens if the URL changes?
       | 
       | Cool urls don't change. Use configs.
       | 
       | [1] https://docs.guzzlephp.org/en/stable/quickstart.html
        
         | hospadar wrote:
         | >> What happens if the URL changes?
         | 
         | > Cool urls don't change. Use configs.
         | 
         | I also kinda think that for many webapps, the risk of this is
         | somewhat overstated. I've got tons of apps with a few hard-
         | coded URL paths that point at other internal apps that I own.
         | They don't break because I don't randomly remove URL paths from
         | services. When I do need to change something, find-and-replace
         | + an integration test keep me safe 99.99% of the time (and the
         | blast radius from a failure like this is usually very small -
         | obvious 404 error bubbles up immediately the first time someone
         | hits something broken).
         | 
         | That said, I agree that keeping constants like URL paths in
         | configs is a fine idea. I also feel that common sense is
         | required - a tiny webservice which makes a single request to
         | one URL path probably is fine to just hard-code it (and in fact
         | putting all constants into config might be overly obfuscating),
         | but a big app which makes dozens or hundreds of calls obviously
         | benefits from a config-oriented approach
        
         | theli0nheart wrote:
         | Exactly what I came here to say.
         | 
         | You don't sprinkle URLs throughout your codebase, as the OP
         | apparently assumes one would normally do. You create a single
         | class (or something similar) which abstracts the API calls. If
         | the endpoint changes, you change it in one place.
         | 
         | I honestly don't see how this solution makes this easier. If
         | anything, I feel like it makes things more complicated and
         | harder to understand.
        
           | dhbanes wrote:
           | The endpoint URL should probably be stored in the
           | environmental variable file.
        
             | theli0nheart wrote:
             | > _The endpoint URL should probably be stored in the
             | environmental variable file._
             | 
             | As I mentioned, _if the endpoint changes, you change it in
             | one place._ Storing your endpoint URLs in an env file is
             | your personal preference, but that 's all. _Should_ has no
             | place here.
             | 
             | It doesn't matter whether it's an environmental variable
             | file, a YAML configuration, a JSON file, or a secure remote
             | KV-store. Barring low water marks, it doesn't really matter
             | where you store your configuration--just make sure to store
             | it in one place.
        
           | that_guy_iain wrote:
           | To be fair it does seem to fit the way I think Laravel
           | applications are built.
        
       | CptKriechstrom wrote:
       | Seems like a Solution in search for a Problem. Instead of
       | hardcoding the URL to the Request it can be set in the config
       | like it was done with jsonplaceholder.api.token.
       | 
       | And creating a Request for every API-Endpoint instead of a single
       | API-Client Class seems overkill.
        
         | apocalyptic0n3 wrote:
         | I think it makes sense if you're doing the same 5 requests over
         | and over throughout your application. As it stands, I generally
         | build a service class for these scenarios:
         | class GoogleMapsApiService {           public function
         | geocodeAddress(string $address);           public function
         | getDirections(string $address);       }
         | 
         | That sort of thing. It's all reusable and I can just call
         | `app(GoogleMapsApiService::class)->getDirections('123 Main
         | St')` to request the data. This just goes a step further and
         | makes it more flexible (and probably more testable) by turning
         | it into a class. Creating the class is a simple command line
         | run (if you're familiar with Laravel, much of your application
         | is scaffolded this way).
         | 
         | I think it loses its effectiveness/value if you're using it for
         | 20 different requests that are only used once each, but for a
         | scenario where you're making 1 request in 10 different places
         | like you might be with geocoding, it's not a bad implementation
         | in my opinion.
        
       ___________________________________________________________________
       (page generated 2021-06-24 23:02 UTC)