Correct
getBlink
and any other methods just returns the result exactly as it is, in this case pure json. If you mean to get a stdClass object returned or a decoded json that is object, you can call $result->getResponseObject();
Please give more details and sample what you mean about HTTP and object.
No, not stdClass, actual objects with defined properties, like Iâve shown above.
The problem with the JSON array is that I canât see in my code whatâs in it. All I see is that itâs an array. Iâd have to go to the documentation website in order to see whatâs in there.
If instead of an array you return objects with named properties, like the Dto in my post above, I know what to expect, and itâs typed so tools like PHPStan etc can tell you when youâre using it incorrectly.
Also, I donât want to do $result->isOk()
when I call getBitlink
. I just want to get a bitlink, I donât want to have anything to do with HTTP. HTTP is an implentation details that is important to the Bitlink
service, but not for classes that use of the Bitlink
service. If a result is not ok, the getBitlink
method should just throw an exception of some sort (preferable without any references to HTTP in the name).
So basically what I am proposing is to not return the Result
object that is now being returned, but return a Dto instead.
I am unfamiliar with Dto objects, please give some links in documentations/guide.
It is basically just an object that only holds data to be moved from one spot in the code to another spot, without any methods on it (except for maybe a constructor).
The main difference between it and an array is that with a Dto I can know what to expect.
Like with the example I gave above:
class Bitlink
{
/**
* @var array<string, string>
*/
public $references;
/**
* @var bool
*/
public $archived;
/**
* @var string[]
*/
public $tags;
// etc
}
If I know I get an object of that type, I know that I can use $result->tags
to get the tags of my bitlink, and I can see itâs an array of strings.
When a Result
is returned (like now) I donât know that. I just know itâs an array. But I canât see from that definition where the tags are. I canât even see that tags may be in there. I donât know anything. It might be a completely empty array. Who knows?
How to convert json into Dto object, if this should not be stdClass object?
See their Auth service class constructor:
It uses flags to tell Api.php class that authorization is not bearer but basic and content of request is not json like other services. How to convert this to what you said?
public function __construct (ApiInterface $api, $clientid_username, $clientsecret_password)
{
// what to do with this?
parent::__construct(null, true);
$this->url = 'https://api-ssl.bitly.com/oauth/access_token';
$key = base64_encode($clientid_username.":".$clientsecret_password);
$this->setApiKey($key);
}
I guess it should be called like:
$config['clientid_username'] = "";
$config['clientsecret_password'] = "";
$api = new Api(null, true);
$auth = new Auth($api, $config);
and change constructor too:
public function __construct (ApiInterface $api, $config)
{
$this->api = $api;
$this->url = 'https://api-ssl.bitly.com/oauth/access_token';
$key = base64_encode($config['clientid_username'].":".$config['clientsecret_password']);
$api->setApiKey($key);
}
But there it will give Too few arguments for testcase. How to fix?
Is there any better way to change this all?
Well, manually
Since multiple methods return a Bitlink
it would probably be easiest to tell a Bitlink
how to construct itself from an array. So letâs say a Bitlink
only has fields references
, archived
and tags
, you could do this:
class Bitlink
{
/**
* @var array<string, string>
*/
public $references;
/**
* @var bool
*/
public $archived;
/**
* @var string[]
*/
public $tags;
public function __construct(array $references, bool $archived, array $tags)
{
$this->references = $references;
$this->archived = $archived;
$this->tags = $tags;
}
public static function fromArray(array $input): self
{
return new self(
$input['references'] ?? [],
$input['archived'] ?? false,
$input['tags'] ?? []
);
}
}
$result = $this->api->get(...);
if (!$result->isOk()) {
// might check multiple cases that could be wrong
// so check things like isNotFound(), isClientError(), etc.
// or just throw one exception for anything that goes wrong
throw new BitlyException('Unable to fetch bitlink');
}
return Bitlink::fromArray($$result->getResponseArray());
Give more arguments in the testcase
Define âbetterâ
For travis should I care to add hhvm and nightly?
HHVM probably not. Itâs not being used a lot anymore.
Nightly can be nice, but when you do add that allow it to fail. Itâs fine if it fails, but itâs good to have it to know what you can expect for future versions.
how to set in yml to allow it to fail?
Read the documentation. Itâs in there.
language: php
install: composer install
php:
- '7.2'
- '7.3'
- nightly
allow_failures:
- php: nightly
notifications:
email: false
But nightly always fail because it cannot find ApiInterface class, but 7.2. and 7.3 can find it! How to fix it?
phpunit is like this:
<phpunit bootstrap="vendor/autoload.php" colors="true">
<testsuites>
<testsuite name="tests">
<directory>lib/PHPLicengine/tests</directory>
</testsuite>
</testsuites>
</phpunit>
Looking at shields.io website, I did not understand how to get a shields.io packagist version badge. How to generate it?
That sounds like a question for a new thread
Please give more details about this structure
$input['references'] ?? [],
$input['archived'] ?? false,
$input['tags'] ?? []
Whatever needs a value uses and whatever needs to be false or true uses false? What if a property has some sub-properties and one of them is emty?
And since all Bitlink methods results donât have the same properties structur is it possible to use the fromArray for all of them if adding all possible properties to fromArray?
If a key was expected in the array but isnât there and we know it should be an array we can safely use an empty array. If a key was expected in the array but isnât there and we know it should be a boolean then 9 of 10 times false
is a safe default value. Depends on your use case, of course.
For results with a different structure you use a different object.
For example the method getClicksSummaryForBitlink
might return an object like BitlinkClicksSummary
.
So fo each different result structure I have to have a separate class with different constructor and fromArray method?
That is correct