I'm trying to explain this as best as I can, please ask i'm im unclear about something.
I'm using a API where i get a bunch of information about a sensor.
This is a method in a class
public function getSensors()
{
$params = array();
return json_decode($this->consumer->sendRequest(constant('REQUEST_URI').'/sensors/list', $params, 'GET')->getBody());
And in my index.php
$params = array('id'=> XXXXXX);
$response = $consumer->sendRequest(constant('REQUEST_URI').'/sensor/info', $params,'GET');
echo json_decode($response->getBody());
This gives me a chunk of information like this:
{"id":"xxxxx","client":"xxxx","name":"xxxxx","lastUpdated": xxxx}
I only want to use some of this information.
This is the getBody() method-
public function getBody() {
if (self::METHOD_POST == $this->method && (!empty($this->postParams) || !empty($this->uploads))) {
if (0 === strpos($this->headers['content-type'], 'application/x-www-form-urlencoded')) {
$body = http_build_query($this->postParams, '', '&');
if (!$this->getConfig('use_brackets')) {
$body = preg_replace('/%5B\d+%5D=/', '=', $body);
}
// support RFC 3986 by not encoding '~' symbol (request #15368)
return str_replace('%7E', '~', $body);
} elseif (0 === strpos($this->headers['content-type'], 'multipart/form-data')) {
require_once 'HTTP/Request2/MultipartBody.php';
return new HTTP_Request2_MultipartBody(
$this->postParams, $this->uploads, $this->getConfig('use_brackets')
);
}
}
return $this->body;
}
If you're using an API you can't control what information you get unless the API defines a method to do so. If you're reading sensors then it's unlikely that will be an option.
Nevertheless, you can just ignore what you don't need.
For example:
$myArray = json_decode('{"id":"xxxxx","client":"xxxx","name":"xxxxx","lastUpdated": xxxx}');
$mySubset = array($myArray['id'], $myArray['lastUpdated']);
I just use json_decode to illustrate the point. From your comments it looks like getBody() is returning an array, but the error message you report points to an object.
For an array you can use
$myResp = $response->getBody();
$myId = $myResp['id'];
For an object you can use
$myResp = $response->getBody();
$myId = $myResp->id;
Apologies if I don't quite hit the mark - I'm firing a little blind here!
Related
I am making a REST method with Zend Framework 2 which returns JSON response. For that I'm using the following code:
return new JsonModel($result);
In some cases, result is an empty array and JsonModel outputs that as []. Is it possible to force JsonModel to display empty array as an object, i.e. {}?
In PHP, you can do the following:
echo json_encode(array(), JSON_FORCE_OBJECT);
Is there a similar option to JSON_FORCE_OBJECT that I could use with JsonModel in zf2? I have tried all combinations of the following, but with no luck.
return new JsonModel(array(), JSON_FORCE_OBJECT);
If you'd've followed the code, you would've found that it's not possible with the provided JsonModel by Zend.
Zend\View\Model\JsonModel has this serialize function:
public function serialize()
{
$variables = $this->getVariables();
if ($variables instanceof Traversable) {
$variables = ArrayUtils::iteratorToArray($variables);
}
$options = [
'prettyPrint' => $this->getOption('prettyPrint'),
];
if (null !== $this->jsonpCallback) {
return $this->jsonpCallback.'('.Json::encode($variables, false, $options).');';
}
return Json::encode($variables, false, $options);
}
The Json::encode leads to Zend\Json\Json, and the encode() function
public static function encode($valueToEncode, $cycleCheck = false, array $options = [])
{
if (is_object($valueToEncode)) {
if (method_exists($valueToEncode, 'toJson')) {
return $valueToEncode->toJson();
}
if (method_exists($valueToEncode, 'toArray')) {
return static::encode($valueToEncode->toArray(), $cycleCheck, $options);
}
}
// Pre-process and replace javascript expressions with placeholders
$javascriptExpressions = new SplQueue();
if (isset($options['enableJsonExprFinder'])
&& $options['enableJsonExprFinder'] == true
) {
$valueToEncode = static::recursiveJsonExprFinder($valueToEncode, $javascriptExpressions);
}
// Encoding
$prettyPrint = (isset($options['prettyPrint']) && ($options['prettyPrint'] === true));
$encodedResult = self::encodeValue($valueToEncode, $cycleCheck, $options, $prettyPrint);
// Post-process to revert back any Zend\Json\Expr instances.
$encodedResult = self::injectJavascriptExpressions($encodedResult, $javascriptExpressions);
return $encodedResult;
}
As you can see, the encoding function has been commented for you, so we need the self::encodeValue function, clicking through on that leads to:
private static function encodeValue($valueToEncode, $cycleCheck, array $options, $prettyPrint)
{
if (function_exists('json_encode') && static::$useBuiltinEncoderDecoder !== true) {
return self::encodeViaPhpBuiltIn($valueToEncode, $prettyPrint);
}
return self::encodeViaEncoder($valueToEncode, $cycleCheck, $options, $prettyPrint);
}
Judging by your question, you have json_encode built-in function available, so we step into the if() and execute the self::encodeViaPhpBuiltIn() function:
private static function encodeViaPhpBuiltIn($valueToEncode, $prettyPrint = false)
{
if (! function_exists('json_encode') || static::$useBuiltinEncoderDecoder === true) {
return false;
}
$encodeOptions = JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP;
if ($prettyPrint) {
$encodeOptions |= JSON_PRETTY_PRINT;
}
return json_encode($valueToEncode, $encodeOptions);
}
This has the same check again, but finally ends up with:
return json_encode($valueToEncode, $encodeOptions);
The options are set hardcoded in the function, with the exception of the optional "JSON_PRETTY_PRINT" option.
The answer you're looking for is: no, it's not possible.
However, you could, technically, write your own replacement for JsonModel, make sure that your own model is used by the JsonViewStrategy and use it then... Just an option.
Use the response object:
$result = array();
$data = json_encode($result, JSON_FORCE_OBJECT);
$response = $this->getResponse();
return $response->setContent($data);
We will need to add status code in to the response.
Like
public function withArray(array $array, array $headers = array()) {
if ($this->statusCode == '200') {
$array = array('code' => $this->statusCode , 'success' => TRUE) + $array;
} else {
$array = array('code' => $this->statusCode, 'success' => FALSE) + $array;
}
return response()->json($array, $this->statusCode, $headers);
}
For now, we had modified library code on "ellipsesynergie/api-response/src/Laravel/Response.php".
But I feel. Its not good way.
Could you please suggest me how can i add this to all response without change library code ?
Or Is there any way to add the status code from controller for final response.
Actually, we will need final response like "http://screencast.com/t/nmWF7PYU".
Please help us on this.
Thanks in advance
Just make your own Response class wich extends EllipseSynergie\ApiResponse\Laravel\Response. Let's call it App\ApiResponse\MyResponse
Overwrite all methods in EllipseSynergie\ApiResponse\Laravel\Response with your own.
For example:
public function withArray(array $array, array $headers = array())
{
$array['code'] = $this->statusCode;
$array['success'] = true;
return parent::withArray($array, $headers);
}
Then in your app\Providers\AppServiceProvider.php register you class something like:
$myResponse = new \App\ApiResponse\MyResponse(new \League\Fractal\Manager());
$this->app->instance('EllipseSynergie\ApiResponse\Contracts\Response', $myResponse);
Im trying to begin to work with a API to call a few bits of information
The documentation for it is quite scarse and the support is quite slim however it is quite good in its way
Ive recently started to learn bits about arrays etc however im not too sure if that would be my hurdle on this specific question
the one part of the API im struggling on is this:
// Get the character object. Will return FALSE if the
// character could not be found or character is frozen.
$character = $armory->getCharacter('xxxx');
Now im quite stuck on how to find if its "FALSE"
This is an extract from the class file if its any help for you guys:
function __construct($region, $realm, $character, $ignoreFields = FALSE) {
if ($ignoreFields != FALSE){
$this->excludeFields($ignoreFields);
}
$this->region = strtolower($region);
$this->realm = $realm;
$this->name = $character;
$jsonConnect = new jsonConnect();
$this->characterData = $jsonConnect->getCharacter($character, $realm, $region, implode(",",$this->fields));
if ($this->characterData != FALSE){
$this->name = $this->characterData['name'];
$this->setTitles();
$this->setTalentTreeSelected();
$this->race = new Races($region);
$this->class = new Classes($region);
} else {
return FALSE;
}
return TRUE;
}
https://sourceforge.net/p/wowarmoryapi/home/ is the API if any of you wish to see the full api or command list
thanks
if ($character->isValid() === false) {
//your code that runs if there is no character
}
else {
//your code that runs if everything is fine
}
if ($character) {
// true stuff
} else {
// false stuff
}
Many things evaluate to logical "false" in php:
Numeric value 0,
Empty string,
Undefined/uninitialized variable
Empty array etc. etc.
I'm using Slim PHP as a framework for a RESTful API.
How do I grab GET params from the URL in Slim PHP?
For example, if I wanted to use the following:
http://api.example.com/dataset/schools?zip=99999&radius=5
You can do this very easily within the Slim framework, you can use:
$paramValue = $app->request()->params('paramName');
$app here is a Slim instance.
Or if you want to be more specific
//GET parameter
$paramValue = $app->request()->get('paramName');
//POST parameter
$paramValue = $app->request()->post('paramName');
You would use it like so in a specific route
$app->get('/route', function () use ($app) {
$paramValue = $app->request()->params('paramName');
});
You can read the documentation on the request object
http://docs.slimframework.com/request/variables/
As of Slim v3:
$app->get('/route', function ($request, $response, $args) {
$paramValue = $request->params(''); // equal to $_REQUEST
$paramValue = $request->post(''); // equal to $_POST
$paramValue = $request->get(''); // equal to $_GET
// ...
return $response;
});
For Slim 3/4 you need to use the method getQueryParams() on the PSR 7 Request object.
Citing Slim 3 / Slim 4 documentation:
You can get the query parameters as an associative array on the
Request object using getQueryParams().
I fixed my api to receive a json body OR url parameter like this.
$data = json_decode($request->getBody()) ?: $request->params();
This might not suit everyone but it worked for me.
Slim 3
$request->getQueryParam('page')
or
$app->request->getQueryParam('page')
IF YOU WANT TO GET PARAMS WITH PARAM NAME
$value = $app->request->params('key');
The params() method will first search PUT variables, then POST variables, then GET variables. If no variables are found, null is returned. If you only want to search for a specific type of variable, you can use these methods instead:
//--- GET variable
$paramValue = $app->request->get('paramName');
//--- POST variable
$paramValue = $app->request->post('paramName');
//--- PUT variable
$paramValue = $app->request->put('paramName');
IF YOU WANT TO GET ALL PARAMETERS FROM REQUEST WITHOUT SPECIFYING PARAM NAME,
YOU CAN GET ALL OF THEM INTO ARRAY IN FORMAT KEY => VALUE
$data = json_decode( $app->request->getBody() ) ?: $app->request->params();
$data will be an array that contains all fields from request as below
$data = array(
'key' => 'value',
'key' => 'value',
//...
);
Hope it helps you!
Use $id = $request->getAttribute('id'); //where id is the name of the param
In Slim 3.0 the following also works:
routes.php
require_once 'user.php';
$app->get('/user/create', '\UserController:create');
user.php
class UserController
{
public function create($request, $response, array $args)
{
$username = $request->getParam('username'));
$password = $request->getParam('password'));
// ...
}
}
Not sure much about Slim PHP, but if you want to access the parameters from a URL then you should use the:
$_SERVER['QUERY_STRING']
You'll find a bunch of blog posts on Google to solve this. You can also use the PHP function parse_url.
Inside your api controller function write the following code of line:
public function your_api_function_name(Request $request, Response $response)
{
$data = $request->getQueryParams();
$zip = $data['zip'];
$radius = $data['radius'];
}
The variable $data contains all the query parameters.
Probably obvious to most, but just in case, building on vip's answer concerning Slim 3, you can use something like the following to get the values for the parameters.
$logger = $this->getService('logger');
$params = $request->getQueryParams();
if ($params) {
foreach ($params as $key => $param) {
if (is_array($param)) {
foreach ($param as $value) {
$logger->info("param[" . $key . "] = " . $value);
}
}
else {
$logger->info("param[" . $key . "] = " . $param);
}
}
}
I have Logger-Class which is logging everything. Objects will be logged with print_r to a human-readable state. My Problem is that I have a big MVC-Object. Everytime an Exception or Error occurs, the MVC-Object will also be printed in the Log by print_r. This results in a very very long Logfile that is not really friendly to read.
I tried to set a __toString() method to my MVC-Class but this don't work. I also get the complete MVC-Object in Log. The MVC is a Singleton and is referenced on every Object. So to simple exclude the Object before it cames into the print_r is not that easy.
Is there any way to exclude Objects from print_r?
My Methods:
LOG-Class errorHandler-Method:
public static function errorHandler($errno, $errstr, $errfile, $errline, $vars) {
//If # is set, don't do anything!
if(error_reporting() === 0) {
return;
}
//Get StackTrace with low memory usage ;)
$e = new Exception();
$stackStr = $e->getTraceAsString();
//Build ErrorMessage for Log
$message = 'File: '.$errfile.' - L: '.$errline."\n".
'Code: '.$errno."\n".
'Message: '.$errstr."\n".
'Vars: '.print_r($vars, true)."\n".
'Stacktrace: '.$stackStr;
self::error($message);
}
LOG-Class exceptionHandler-Method:
public static function exceptionHandler(Exception $e) {
$message = get_class($e).': '.$e->getMessage()."\n".
'File: '.$e->getFile().' - L: '.$e->getLine()."\n".
'Code: '.$e->getCode()."\n".
'Message: '.$e->getMessage()."\n".
'Stacktrace: '.$e->getTraceAsString();
self::error($message);
}
LOG-Class error-Method:
public static function error($data, $file='system.log') {
$config = Megaira_PropertyConfiguration::getInstance();
switch($config->get('LOG_MODE')) {
case'DEEPDEBUG':
case'ERROR':
case'WARNING':
case'INFO':
case'DEBUG':
self::writeToLog('ERROR', $data, $file);
break;
}
}
LOG-Class writeToLog-Method:
private static function writeToLog($mode='', $text='', $file=''){
if(!is_string($text) && !is_numeric($text)) {
$text = print_r($text, true);
}
$config = Megaira_PropertyConfiguration::getInstance();
if(!$config->get('LOGGINGACTIVE')) { return; }
self::writeLineToFile($mode, $text, $file);
}
Setup the Error- and Exception-handler:
//Set Error and Exception Handler
set_error_handler(array(new LOG(), 'errorHandler'));
set_exception_handler(array(new LOG(), 'exceptionHandler'));
Thanks
Some Testing:
public static function print_r_filtered($object, $ret=false) {
$filtered = array(
'Megaira_MVC'
);
$text = print_r($object, true);
foreach($filtered as $filter) {
$search = '#('.$filter.'\sObject)\n(\s+)\).*?\n\2\)\n#s';
$replace = "$1";
$text = preg_replace($search, $replace, $text);
}
if($ret)
return $text;
echo $text;
}
Did not work. Maybe RegEx fail?
Solution:
It was a Design flaw. The errorHandler is Logging all Objects that are used on the place the error occurs. So in the index.php are the following code:
$mvc = Megaira_MVC::getInstance();
So this peace of code produced a logging of the Var $mvc with print_r through the errorHandler in LOG-Class.
Conclusion for me: Don't use Variables on big Singleton-Objects or use unset() if the Var is not needed anymore.
__toString() is called, when the object is casted to a string. You may try something like
$objectString = method_exists($object, '__toString')
? (string) $object
: print_r($object, true);
Use is_object() to find out, if a value is an object or not.
At all
$string = !is_object($value) || method_exists($value, '__toString')
? (string) $value
: print_r($value, true);
You could wrap print_r with your own function that checks whether the provided data includes any objects, using the is_object() function. Similarly, you could use is_a() if you only want to exclude certain classes of objects.
as a html solution you can use:
<pre><?=print_r(log_content);?></pre>
to display your log file better. I am displaying the log files in this way.
if (is_object( $foo ))
{
print_r( $foo->__toString() );
} else {
print_r( $foo );
}
If you can alter the Logger class, you can check for the class befpre you print it:
if(!($var instanceof HeavyMVCObject)){
print_r($var);
}