Call PHP API class with defined parameter - php

I am using this class https://github.com/ricog/coinbase-exchange-php/blob/master/lib/CoinbaseExchange/CoinbaseExchange.php
When I call it using
$listOrders = $exchange->listOrders();
print_r($listOrders);
This is my output:
[
{
"id": "d50ec984-77a8-460a-b958-66f114b0de9b",
"size": "3.0",
"price": "100.23",
"product_id": "BTC-USD",
"status": "open",
"filled_size": "1.23",
"fill_fees": "0.001",
"settled": false,
"side": "buy",
"created_at": "2014-11-14 06:39:55.189376+00"
}
]
By default all the pending or open orders are called. The documentation states "To specify multiple statuses, use the status query argument multiple times:
/orders?status=done&status=pending." How can I call the above class where the status is 'done' instead of 'open', without showing any pending transactions.
I tried this $listOrders = $exchange->listOrders('status'=>'done');
It didn't work.
Source: https://docs.exchange.coinbase.com/?php#list-orders

the class that you are using is not ment for sending multiple params (kind of stupidly written if you ask me). What you can do is to extend that class:
class MyExchange extends CoinbaseExchange {
public function request($endpoint, $params = array()){
return $response = parent::request($endpoint, $params);
}
}
And then use it like this:
$exchange = new MyExchange();
// any other methods required for authentikation and settings like $exchange->auth(...)
$listOrders = $exchange->request('orders', array('status'=>'done', 'status'=>'pending');

Related

Can I find unepexcted issues by creating dynamic properties on an object (via $this) on a callback function?

I have a question regarding the use of $this inside a Laravel routing.
Recently I'm trying to find a way to pass PHP variables between Route::group() and Route::get/put/post/anything-that-fits-inside-the-group(). So I tried to Google my way out and found most of the results always related to passing variable between routes and view (which is not the case). This result were closest to -- if not exactly -- what I'm trying to achieve, stating that variable passing can't be done in such way.
During my curiosity over this topic, I fiddled around with the routes, trying to pass the PHP variables between routes in a few ways until I found a solution to this case: by using $this
Here's a bit of my code just to give you some context:
...
Route::prefix("api")->middleware("verify_api_call")->group( function(){
[$this->success, $this->message, $this->data] = [false, "", null];
$this->ctx = [
"success" => &$this->success,
"message" => &$this->message,
"data" => &$this->data
];
Route::get("test", function(){
$this->success = true;
$this->message = "ok";
$this->data = [
"somekey" => "somevalue"
];
return response()->json(["Contextual" => $this->ctx, "All of this" => $this]);
});
...
Calling mysite.com/api/test gives the expected result as below:
{
"Contextual": {
"success": true,
"message": "ok",
"data": {
"somekey": "somevalue"
}
},
"All of this": {
"success": true,
"message": "ok",
"data": {
"somekey": "somevalue"
},
"ctx": {
"success": true,
"message": "ok",
"data": {
"somekey": "somevalue"
}
}
}
}
Now the question might be no longer about how it works, but rather: will there be any unexpected problems that I'm unaware of if I keep using $this this way?
TL;DR; Yes, you could cause undefined behaviour in future.
You're basically storing your custom variables on an instance of the class:
Illuminate\Routing\RouteFileRegistrar
And currently, said Class has only $router field, and each Group creates a new instance of said Class for itself.
But in future Laravel versions, said Class may have additional fields, which you may override by accident, or it could entirely change to another Class.
So, for now you are good to go, but consider using function () use($ctx) {} syntax instead, like:
Route::prefix("api")->middleware("verify_api_call")->group( function(){
[$success, $message, $data] = [false, "", null];
$ctx = [
"success" => & $success,
"message" => & $message,
"data" => & $data
];
Route::get("test", function() use($ctx) {
$ctx->success = true;
$ctx->message = "ok";
$ctx->data = [
"somekey" => "somevalue"
];
return response()->json(["Contextual" => $ctx]);
});
});
You are creating public dynamic properties on an object of class you don't control.
Two immediate problems:
The API of the class could change in the future, and your chosen properties may clash with whatever the class creator chooses.
Dynamic properties will be deprecated by PHP 8.2, and removed by PHP 9.0. So unless the class maintainer adds code to allow for developers to add random dynamic properties, your code will fail by then.
It's a bad idea and poor design.

Get () method to get specific data return in a post callback

I'm working on a project and I came across a problem, explain:
I'm doing a POST to a webserver using the Guzzle http, follows the :
public function sendPost($direction, array $data, array
$options = ['http_errors'=>false])
{
$url = $this->interpolate( self::BASE_PATH."/{direction}",
[
'direction' => $direction
]);
$options = array_merge($options,['body'=>json_encode($data)]);
return $this->client->post($url, $options);
}
The method is working correctly and I am returning the following:
{
"id": "jdhj9h830027hd73hs9q9js9",
"direction": "left",
"status": "Success",
"code": {
"id":"1",
"desc": "ok",
"error": false,
"msg":null
}
}
What I can not do is the following:
A method that returns only the given "jdhj9h830027hd73hs9q9js9", that is, the "id" parameter.
can anybody help me?
PS. By using the "sendPost ()" method I can access the data I need separately, however I can not do this through another method, such as a "getId ()".
Thank you in advance for your help.
Just try:
return ($this->client->post($url, $options))->id;

response()->json() returns with "resource" wrap - Laravel 5.6.*

I have a problem regarding the response JSON of my API. I used a resource, since I wanted to limit what data to send back to the client. It was properly giving my intended response before, but when I opened my project again, the response changed.
Here's are parts of my code:
api.php
Route::get('admin/adminuserdetails/{adminUser}', 'AdminsController#AdminUserDetails');
Sample URL:
http://localhost:8000/api/admin/adminuserdetails/1
Controller
public function AdminUserDetails(AdminUsers $adminUser){
return response()->json(new AdminUserAccessDetails($adminUser), 200);
}
AdminUsers Model
class AdminUsers extends Model
{
//
protected $table = 'AdminUsers';
protected $primaryKey = 'AdminUserId';
protected $guarded = [];
}
AdminUserAccessDetails Resource
class AdminUserAccessDetails extends JsonResource
{
public function toArray($request)
{
//return parent::toArray($request);
return [
'adminUserId' => $this->AdminUserId,
'adminFirstName' => $this->AdminFirstName,
'adminLastName' => $this->AdminLastName,
'modulesAllowed' => $this->ModulesAllowed,
'actionsAllowed' => $this->ActionsAllowed
];
}
}
Sample response (before, my intended response)
{
"adminUserId": 1,
"adminFirstName": "asdfasdf",
"adminLastName": "asdfsadf",
"modulesAllowed": "",
"actionsAllowed": ""
}
Sample response (now)
{
{
"resource": {
"adminUserId": 1,
"adminFirstName": "asdfasdf",
"adminLastName": "asdfsadf",
"adminEmail": "asdfsadf#fsafsa.com",
"adminPassword": "l6wfDtAaYAp6aM04TU++9A==",
"authToken": "68bbc9fc7eb08c9f6d96f6b63d30f056",
"fCMToken": null,
"profileImage": "https://www.gravatar.com/avatar/5d0d65256e8c2b15a8d00e8b208565f1?d=identicon&s=512",
"userTypeId": "0",
"status": "A",
"createDate": "2018-06-26 16:01:43.947",
"updateDate": "2018-06-26 16:01:44.143",
"modulesAllowed": "",
"actionsAllowed": ""
},
"with": [],
"additional": []
}
I didn't change anything, but when I tested it again (not only in this particular route), everything that uses any resource is now enclosed within that resource wrap, and I can't seem to find the reason why.
I tried implementing the same logic with another clean project, and it's working perfectly.
What's causing this and how do I get my intended response back?
Edit 1:
I tried to change my return, I removed the "response()->json()" code so my controller would look like:
public function AdminUserDetails(AdminUsers $adminUser){
//return response()->json(new AdminUserAccessDetails($adminUser), 200);
return new AdminUserAccessDetails($adminUser);
}
The response of this edit is now a bit closer to my intended output:
{
"data": {
"adminUserId": 1,
"adminFirstName": "asdfasdf",
"adminLastName": "asdfsadf",
"modulesAllowed": "",
"actionsAllowed": ""
}
}
However I still prefer using the response()->json() so that I can return a proper HTTP response code..
I think that the problem is you are sending a Laravel Object as API response. Remember, Laravel Core instance object add some properties/methods to manage/use easily inside your code.
I may recommend you create a new Class or Associative array to encapsulate specifics properties and later send it.
For Example:
public function AdminUserDetails(AdminUsers $adminUser){
// Example with Object
$Object = new YourClass(); // you can define with yours wished properties
$Object->PropertyA = $adminUser->Property1;
$Object->PropertyB = $adminUser->Property2;
// ...
return response()->json($Object, 200);
// Example with Associative Array
$AssociateArray = array(
"PropertyA" => $adminUser->Property1,
"PropertyB" => $adminUser->Property2,
// ...
);
return response()->json($AssociateArray, 200);
}
I hope be useful.

Class 'JsonValidator' not found

https://github.com/hasbridge/php-json-schema
Getting error Class 'JsonValidator' not found.
I did install composer.json as in git folder.
I did put my json schema, json data files in src/Json and created a php file to validate as mentioned in git.
getting error class Class 'JsonValidator' not found.
In their example, they're creating a JsonValidator object.
This is different from the actual namespace of the class, which is Json\Validator.
Try dropping use Json\Validator as JsonValidator at the top of your file so that you're able to refer to the class the same way the docs do.
I'd expand their docs from:
$someJson = '{"foo":"bar"}';
$jsonObject = json_decode($someJson);
$validator = new JsonValidator('/path/to/yourschema.json');
$validator->validate($jsonObject);
To
<?php
namespace Your\Domain;
use Json\Validator as JsonValidator;
require_once('./vendor/autoload.php');
$someJson = '{"foo": "bar"}';
$jsonObject = json_decode($someJson);
$validator = new JsonValidator('/path/to/yourschema.json');
$validator->validate($jsonObject);
Alternatively, you could substitute new JsonValidator('/path/to/yourschema.json') for new Json\Validator('/path/to/yourschema.json').
Edit: By the way - you might find the example schemas at json-schema.org helpful when using this library.
Here's the main one from that link:
{
"title": "Example Schema",
"type": "object",
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"age": {
"description": "Age in years",
"type": "integer",
"minimum": 0
}
},
"required": ["firstName", "lastName"]
}
Save this file somewhere in your project and refer to it instead of /path/to/yourschema.json.

How to to prevent doctrine2 from returning certain fields

What I have coded is a oneToMany relationship with doctrine
one user ---> has many notifications
This is how I get the data
/**
* #Route("/test")
*/
public function testRoute()
{
//get the user notifications
$notifications = $this->getUser()->getNotifications();
//return json response
$serializer = $this->get('serializer');
$json = $serializer->serialize($notifications, 'json');
$response = new Response($json);
$response->headers->set('Content-Type', 'application/json');
return $response;
}
This is what the controller returns
[
{
"id": 1,
"receiver": 1,
"notification_type": "new_comment",
"triggered_by": {
"id": 1,
"username": "gabriel",
"username_canonical": "gabriel",
"password": "3e6bS2I==",
"email": "ga#ga.de",
"first_name": "Gabriel",
"last_name": "ThaKid",
"likes_counter": 0,
"dislikes_counter": 2,
"favourites_counter": 0,
"profile_pic": "profilepic_60181.png",
"salt": "Lqch0N84UH1QmFI5O",
"form_token": "sO6NgWd",
"is_active": true,
"registration_confirmation": "success",
"secret_confirmation_id": "qTwNGm4CSKHzJOe8ry9DcXavt",
"socket_token": "KuMlxYHa"
},
"created_at": "2014-12-16T13:36:20+0100",
"link_to": "#test"
},
{
"id": 2,
"receiver": 1,
"notification_type": "new_comment",
"triggered_by": {
"id": 1,
"username": "gabriel",
"username_canonical": "gabriel",
"password": "3e6bS2IYX1DONLA/70a8hzMUQ==",
"email": "ga#ga.de",
"first_name": "Gabriel",
"last_name": "ThaKid",
"likes_counter": 0,
"dislikes_counter": 2,
"favourites_counter": 0,
"profile_pic": "profilepic_60181.png",
"profile_rank": "Beginner", (...)
},
"created_at": "2014-12-16T13:36:24+0100",
"link_to": "#test"
}
]
I think you get the point, it returns the notifications of a certain user which is allright,
I also need certain fields from the user, like the lastname and the firstname, so the returned data is usable in the application.
But doctrine also returns the hashed password and the salt along with tokens and information the user doesn't need to know.
how do I tell doctrine not to return those fields or not to fetch them to begin with?
This is not about Doctrine, this is the default Serializer that tries to fetch and return all of the values available.
Take a look at the Serializer component documentation to understand how to ignore properties. Basically, you'll have to pass a normalizer into your serializer's constructor:
<?php
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
$normalizer = new GetSetMethodNormalizer();
$normalizer->setIgnoredAttributes(array('age'));
$encoder = new JsonEncoder();
$serializer = new Serializer(array($normalizer), array($encoder));
$serializer->serialize($person, 'json');
Also, I'd strongly suggest to switch to JMSSerializer and/or use FOSRestBundle, as it gives a lot more flexibility for the serialization. The property list is configured against contexts, and has base exclusion strategies. This way, you'd only need to list properties to expose, not to exclude:
AppBundle\Entity\Car:
exclusion_policy: all
properties:
id:
expose: true
vendor:
expose: true
title:
expose: true
In the given example, all properties that were not listed would be excluded.
You should create a custom repository class.
In this class create a method like this:
// src/AppBundle/Entity/NotificationRepository.php
namespace AppBundle\Entity;
use Doctrine\ORM\EntityRepository;
class NotificationRepository extends EntityRepository
{
public function findAllByUser()
{
return $this->getEntityManager()
->createQuery(
'SELECT [only the fields you need] FROM [....]'
)
->getResult();
}
}
For the DQL query you could use the partial object syntax.

Categories