Why does my php function not get data from JSON array? - php

I have a page that pulls information about TV shows from the TMDB as a json array with the help of the TMDB-API Wrapper. I am trying to get the page to display information on a tv shows's ['network'].
I have written a function for this that loops through the network array but I can't get it to work. Can anyone tell me what I'm doing wrong? Thanks.
This is my function that does not work.
//Get networks
public function getNetworks() {
$networks = array();
foreach($this->_data['networks'] as $data){
$networks[] = new Network($data, $this->getName());
}
return $networks;
}
Display.php
//Call the function and loop though results
echo ' <li>Networks: <ul>';
$networks = $tvShow->getNetworks();
foreach($networks as $network){
echo '<li>'. $network->getID() .'</li>';
}
This does work (written in the wrapper not me)
public function getSeasons() {
$seasons = array();
foreach($this->_data['seasons'] as $data){
$seasons[] = new Season($data, $this->getID());
}
return $seasons;
}
This does work
//Get Network
public function getNetworks() {
return $this->_data['networks'][0]['name'];
}
And then on display.php
echo '<b>'. $tvShow->getNetworks() .'</b>';
This is the json array
{
"backdrop_path": "/c8A5IYqIT1ez15sqA8wX5tCDTmF.jpg",
"created_by": [
{
"id": 1187819,
"name": "Matthew Weiner",
"profile_path": null
}
],
"episode_run_time": [
47,
45
],
"first_air_date": "2007-07-19",
"genres": [
{
"id": 18,
"name": "Drama"
}
],
"homepage": "http://www.amc.com/shows/mad-men",
"id": 1104,
"in_production": false,
"languages": [
"en"
],
"last_air_date": "2015-05-17",
"name": "Mad Men",
"networks": [
{
"id": 174,
"name": "AMC"
}
],
Tvshow Class
class TVShow{
//------------------------------------------------------------------------------
// Class Variables
//------------------------------------------------------------------------------
private $_data;
/**
* Construct Class
*
* #param array $data An array with the data of the TVShow
*/
public function __construct($data) {
$this->_data = $data;
}

Related

php | dynamic api call

I am trying to create a dynamic endpoint for a API I am creating in order to include some data but only if it is required so I can use it in multiple places.
The idea is to have api.domain.com/vehicle to bring back basic vehicle information but if I did api.domain.com/vehicle?with=owners,history then the idea is to have a function which maps the owners and history to a class which will return data but only if it is required.
This is what I currently have.
public static function vehicle()
{
$with = isset($_GET['with']) ? $_GET['with'] : null;
$properties = explode(',', $with);
$result = ['vehicle' => Vehicle::data($id)];
foreach ($properties as $property) {
array_push($result, static::getPropertyResponse($property));
}
echo json_encode($result);
}
Which will then call this function.
protected static function getPropertyResponse($property)
{
$propertyMap = [
'owners' => Vehicle::owner($id),
'history' => Vehicle::history($id)
];
if (array_key_exists($property, $propertyMap)) {
return $propertyMap[$property];
}
return null;
}
However, the response I'm getting is being nested within a index, which I don't want it to be. The format I want is...
{
"vehicle": {
"make": "vehicle make"
},
"owners": {
"name": "owner name"
},
"history": {
"year": "26/01/2018"
}
}
But the format I am getting is this...
{
"vehicle": {
"make": "vehicle make"
},
"0": {
"owners": {
"name": "owner name"
}
},
"1": {
"history": {
"year": "26/01/2018"
}
}
}
How would I do this so it doesn't return with the index?
Vehicle::history($id) seems to return ['history'=>['year' => '26/01/2018']], ...etc.
foreach ($properties as $property) {
$out = static::getPropertyResponse($property) ;
$result[$property] = $out[$property] ;
}
Or your methods should returns something like ['year' => '26/01/2018'] and use :
foreach ($properties as $property) {
$result[$property] = static::getPropertyResponse($property) ;
}

many layer nest in php

{
"errorMessage": null,
"hotels": [{
"hotelId": 1177,
"hotelName": "Marriott",
"hotelFilters": [{
"filterName": "pool",
"message": "yes"
}]
}, {
"hotelId": 1542,
"hotelName": "Hilton",
"hotelFilters": [{
"filterName": "pool",
"message": "no"
}, {
"filterName": "spa",
"message": "yes"
}]
}
How do I traverse the array to get a table with hotelID, hotel Name and message? I'm lost in the levels of the array.
Take this as a first approach ;)
/**
* Transforms JSON Hotel data to PHP array
*
* #param $data The data as JSON String
* #return array|bool
*/
public function transformHotelDataFromJson($data)
{
$_data = json_decode($data);
if (array_key_exists('hotels', $_data) === false) {
return false;
}
$myData = [];
foreach ($_data['hotels'] as $hotel) {
$myData[] = [
'id' => $hotel['hotelId'],
'name' => $hotel['hotelName'],
'message' => $hotel['hotelFilters']['message'],
];
}
return $myData;
}

Add extra key in laravel eloquent result

I have a laravel query builder result that looks like this
{
"data": [
{
"id": "",
"awardID": 2,
"title": "Dummy title",
"status": "active",
"raceStart":"",
"raceEnd:":""
}
]
}
What i want to output is something like this
{
"data": [
{
"id": "",
"awardID": 2,
"title": "Dummy title",
"status": "active",
"period": {
"raceStart":"",
"raceEnd:":""
}
}
]
}
This would have been much easier if the period was a table with a 1 to 1 relationship with parent table but this is not the case here.
How can this be achieved?
Check if this will work. I haven't tried though but according to documentation we can add accessor and mutators. But it will change every response you are doing with the model.
Using Eloquent
// Your Model
class Race extends Model
{
{...}
protected $appends = ['period'];
// accessor
public function getPeriodAttribute($value)
{
$this->attributes['period'] = (object)[];
$this->attributes['period']['raceStart'] = $this->attributes['raceStart'];
$this->attributes['period']['raceEnd'] = $this->attributes['raceEnd'];
unset($this->attributes['raceStart']); = $value;
unset($this->attributes['raceEnd']);
return $this->attributes['period'];
}
}
Now when you will access $race->period will give the raceStart and raceEnd value.
Ref: https://laravel.com/docs/5.4/eloquent-mutators#accessors-and-mutators
else another option is after query, do a map
{...}
->map(function($data) {
$data->period = (object)[];
$data->period['raceStart'] = $data->raceStart;
$data->period['raceEnd'] = $data->raceEnd;
unset($data->raceStart);
unset($data->raceEnd);
return $data;
});
Ref: https://laravel.com/docs/5.4/eloquent-collections#introduction
Using QueryBuilder
$races = DB::table('races')->get();
$races = array_map(function ($data) {
$data->period = (object)[
"raceStart" => $data->raceStart,
"raceEnd" => $data->raceEnd
];
unset($data->raceStart);
unset($data->raceEnd);
return $data;
}, $races->data);

Remove model name from json array in cakephp

I've set up a custom search action in my cakephp controller
public function search() {
$results = [];
$results['data'] = $this->Content->find('first',
array(
'conditions' => array($this->request->params['pass'][0] . ' like' => "%" . $this->request->params['pass'][1] . "%")), array('contain' => false)
);
if(count($results['data'])>0){
$results['success'] = true;
$this->set(compact('results'));
$this->set('_serialize', array('results'));
}
else{
$results['success'] = false;
}
}
The issue I'm running into is that the rest of my API formats data like this:
{
"success": true,
"data": [
{
"id": "5509be6c-9ef8-42c3-af39-2d492773a233",
"title": "test2",
},
{
"id": "5509be6c-9ef8-42c3-af39-2d492773a233",
"title": "test1"
}
]
}
but what I'm getting from cakephp right now for my search action is this:
{
"results": {
"success": true,
"data": {
"Content": {
"id": "52efcbeb-e984-4a2e-b76f-0cc34056922c",
"title": "Homeasdfasdf",
}
}
}}
How do I get rid of the extra "results" array wrapper so that my data is coming out in the same format?
Use the current() php function. In your controller make
$results = current($results);
before the set() call

Threaded App.net Conversation Into Tree

I want to create a JSON tree from a flat structure - in this case an App.net Thread.
I want JSON like this
"id": "12345",
"name": "Ringo",
"data":
{
"avatar": "",
"text": "We All Live",
},
"children": [{
"id": "34567",
"name": "John",
"data":
{
"avatar": "",
"text": "In a pink submarine?",
},
"children": [{
"id": "35555",
"name": "George",
"data":
{
"avatar": "",
"text": "Don't be daft",
},
"children": []
}]
},{
"id": "98765",
"name": "Paul",
"data":
{
"avatar": "",
"text": "In a yellow submarine?",
},
"children": []
}]
So, each post can have multiple children. Each child can have children.
The JSON coming back from App.net is not threaded.
{
"id": "98765",
"parent": "12345"
"details": {
...}
},
{
"id": "34567",
"parent": "12345"
"details": {
...}
},
I've used json_decode() to get the JSON response in to an array. I can iterate through using foreach.
How do I put each post in the correct part of the multi dimensional array?
Parent
|_
|-child
|-child
| |-child
|-child
etc
I would use references, the oft forgotten hard link of PHP. Something like this:
I'm assuming you have a $posts array that you've gotten back from an App.net API call.
(untested, may not compile / run / may have errors / may be more efficient ways to do this)
// first throw everything into an associative array for easy access
$references = array();
foreach ($posts as $post) {
$id = $post['id'];
$post['children'] = array();
$references[$id] = $post;
}
// now create the tree
$tree = array();
foreach ($references as &$post) {
$id = $post['id'];
$parentId = $post['parent'];
// if it's a top level object, add it to the tree
if (!$parentId) {
$tree[] =& $references[$id];
}
// else add it to the parent
else {
$references[$parentId]['children'][] =& $post;
}
// avoid bad things by clearing the reference
unset($post);
}
// encode it
print json_encode($tree);
Just sketching out an answer here: all assuming you can hold all entries in RAM otherwise you will have to make some ordering assumptions and clear our your array when a full unit is done.
Create an array posts indexed by id holding structures with the details and an array of children.
Then iterate over your input array and for each element:
create posts[id] if it hasn't been created yet
fill in details for post[id]
if there is a parent, lookup (creating it if needed -- no idea how the ordering is) posts[parent_id] and add this structure to the children there.
At the end you can iterate over all posts and those without a parent are the roots with their children properly filled in.
I wrote a class and example script to accomplish what I think you wanted.
It converts a flat structure into a hierarchical one, and also accounts for orphan updates (ones without parent updates available).
Update.php
<?php
/**
* An App.net update.
*/
class Update extends ArrayObject
{
/**
* The update's children.
*
* #var array
*/
private $children = array();
/**
* The parent update.
*
* #var Update
*/
private $parent;
/**
* Adds a child to this update.
*
* #param Update The child update.
*/
public function addChild(self $child)
{
$child->setParent($this);
$this->children[] = $child;
}
/**
* Sets the parent update.
*
* #param Update The parent update.
*/
public function setParent(self $parent = null)
{
$this->parent = $parent;
}
/**
* Converts the update and its children to JSON.
*
* #param boolean $encode Automatically encode?
*
* #return string The JSON-encoded update.
*/
public function toJson($encode = true)
{
$data = $this->getArrayCopy();
if ($this->children) {
$data['children'] = array();
foreach ($this->children as $child) {
$data['children'][] = $child->toJSON(false);
}
}
if ($encode) {
return json_encode($data);
}
return $data;
}
}
build.php
<?php
require 'Update.php';
$updates = <<<UPDATES
[
{
"id": "12345",
"name": "Ringo",
"data": {
"avatar": "",
"text": "We All Live"
}
},
{
"id": "34567",
"parent": "12345",
"name": "John",
"data": {
"avatar": "",
"text": "In a pink submarine?"
}
},
{
"id": "98765",
"parent": "12345",
"name": "Paul",
"data": {
"avatar": "",
"text": "In a yellow submarine?"
}
}
]
UPDATES;
$original = json_decode($updates, true);
$parents = array();
$children = array();
foreach ($original as $update) {
if (empty($update['parent'])) {
$parents[$update['id']] = $parent = new Update($update);
if (isset($children[$update['id']])) {
foreach ($children[$update['id']] as $child) {
$parent->addChild($child);
}
unset($children[$update['id']]);
}
} else {
$child = new Update($update);
if (isset($parents[$update['parent']])) {
$parents[$update['parent']]->addChild($child);
} else {
if (false === isset($children[$update['parent']])) {
$children[$update['parent']] = array();
}
$children[$update['parent']][] = $child;
}
}
}
// Anything in children at this point are orphans
echo "Parents:\n";
foreach ($parents as $parent) {
echo $parent->toJson();
}
echo "\n\nOrphans:\n";
foreach ($children as $parent => $orphans) {
foreach ($orphans as $orphan) {
echo $orphan->toJson();
}
}

Categories