Google Visualization JSON PHP - json

I spent the whole day trying to get a pie chart with Google Charts.
I am getting my results from a MySQL Database using PHP.
The result is a JSON which looks like this:
stdClass Object
(
[cols] => Array
(
[0] => stdClass Object
(
[label] => Firma
[type] => string
)
[1] => stdClass Object
(
[label] => Zeit
[type] => number
)
)
[rows] => Array
(
[0] => stdClass Object
(
[Firma] => Firma1
[Zeit] => 60
)
[1] => stdClass Object
(
[Firma] => Firma2
[Zeit] => 40
)
)
)
Javascript Code looks like this:
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable(<?=$jsongesamtzeiten;?>);
//data.addColumn('string', 'Firma');
//data.addColumn('number', 'Zeit');
//data.addRows([ ['Firma1',40], ['Firma2',60] ]);
var options = {
title: 'Arbeitsverteilung gesamt',
colors: ['#3B2BC1', '#7EBB58'],
width: 600,
height: 400,
backgroundColor: { stroke: "#CCC", strokeWidth: 2, fill: "#f5f5f5" }
};
var chart = new google.visualization.PieChart(document.getElementById('piechart'));
chart.draw(data, options);
};
I get a:
Cannot read property '1' of undefined
as reply.
If I uncomment the data.addColumn and data.addRows and remove the <?=$jsongesamtzeiten;?> it works. But that's not what I want, because I want to recieve the data from a MySQL-database.
I did many google-searches and found some similiar questions here, but nothing helped me.
Thanks.

I believe the problem lies in the JSON rows column value keys.
It appears you're naming the object keys according to their column labels.
However, the key for a value should simply be v
See the first example under the DataTable class reference
Try changing the JSON as follows...
stdClass Object
(
[cols] => Array
(
[0] => stdClass Object
(
[label] => Firma
[type] => string
)
[1] => stdClass Object
(
[label] => Zeit
[type] => number
)
)
[rows] => Array
(
[0] => stdClass Object
(
[v] => Firma1
[v] => 60
)
[1] => stdClass Object
(
[v] => Firma2
[v] => 40
)
)
)
Also, since you're already including the column and row definitions in your JSON,
you will not need to use data.addColumn or data.addRows
only need...
var data = new google.visualization.DataTable(<?=$jsongesamtzeiten;?>);
(once the format is correct)

Related

Laravel - How to sort external API in desc order and select set of records

In my Laravel-8, I am getting external API using Guzzle:
I got this set of records for dd($json) in the Controller:
array:554 [▼
0 => array:30 [▼
"PartitionKey" => "19SB22"
"RowKey" => "0000"
"Timestamp" => "2021-01-22T12:30:25.4698261Z"
"client_tracking_id" => "ddd3321"
"current_asset_position_name" => "2, Adelaide, Australia"
"service_tracking_id" => "19SB22"
"this_tracking_job_id" => "0000"
"trip_status" => "DISPATCHED"
]
1 => array:31 [▼
"PartitionKey" => "19SB22"
"RowKey" => "2233"
"Timestamp" => "2021-02-23T20:51:50.3066741Z"
"client_tracking_id" => "TRIP-20200621007"
"current_asset_position_name" => "20, Adelaide, Australia"
"service_tracking_id" => "19SB22"
"this_tracking_job_id" => "19SB22"
"trip_status" => "AROUND CUSTOMER LOCATION"
]
....
Here is the Controller:
public function index() {
$client = new Client();
$res = $client->request('GET','https://example.com/api/tracking/19SB22', [
'query' => ['key' => 'jkkmkf']
])->getBody();
$json = json_decode($res->getContents(), true);
return view('welcome', [
'json' => $json,
]);
How do I sort the result $json in descending order using Timestamp field and select the first set of record?
Thanks
Use Collections and Carbon to convert the date string into a correct timestamp.
Collections are laravels array extension, that makes it possible to do function calls on collections (arrays). There is an sortBy() and sortyByDesc() functions, these can be used and using Carbon::parse(), that should be able to parse your zulu date. After that you can use first() to get your element.
$firstElement = collect($yourData)->sortByDesc(function ($data) {
return Carbon::parse($data['Timestamp'])->timestamp;
})->first();

Issue with JSOn parsing - in Array

I am getting the data from DB as array and then outputting them as a JSON.
Some parts of my code:
private function getUsers( ){
$users = $this->db->resource(dbMapper::USER);
return $this->usersToArray( $users );}
private function usersToArray( $users ){
$result = array( );
foreach ($users as $user){
$result[] = array(
'id' => intval( $user->get('id') ),
'name' => $user->get('name')
);
}
return $result;
}
public function getAllData( ){
$result = array( );
$result['users'] = $this->getUsers( );
$results = print_r($result['users'], true); echo $results;
return $result;
}
and then I get the JSON from this result:
$data = $model->getAllData( );
$this->_helper->json( $data );
The JSON output looks like this (I removed the data for debugging), but even if there are no data I have a syntax error in first letter of Array:
In my browser I got this: SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
and if I put that JSOn to JSON validator, I got this:
Parse error on line 1:
Array( [0] => A
^
Expecting 'STRING', 'NUMBER', 'NULL', 'TRUE', 'FALSE', '{', '[', got 'undefined'
Array
(
[0] => Array
(
)
[1] => Array
(
)
[2] => Array
(
)
[3] => Array
(
)
[4] => Array
(
)
Not sure what is wrong with the Array in JSON...
The issue was with incorrect characters in the username field in DB, that caused the JSON error.

How to use custom php function to filter in ActiveDataProvider

I have this problem: I need to get data from database and filter them. but then I need to use custom php function to filter those filtered results using data from it.
Clasic search function in ActiveDataProvider
public function search($params) {
$query = Passenger::find();
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
// I guess my function would go like here
Passenger::filterResultsEvenMore($dataProvider);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'passenger_id' => $this->passenger_id,
// ...
'version' => $this->version,
'status' => $this->status,
]);
return $dataProvider;
}
So my question is how to work with results of dataProvider because if I vardump the variable it looks like this and no actual data there.
yii\data\ActiveDataProvider Object
(
[query] => common\models\PassengerQuery Object
(
[sql] =>
[on] =>
[joinWith] =>
[select] =>
[selectOption] =>
[distinct] =>
[from] =>
[groupBy] =>
[join] =>
[having] =>
[union] =>
[params] => Array()
[_events:yii\base\Component:private] => Array()
[_behaviors:yii\base\Component:private] => Array()
[where] => Array
(
[status] => 1
)
[limit] =>
[offset] =>
[orderBy] =>
[indexBy] =>
[emulateExecution] =>
[modelClass] => common\models\Passenger
[with] =>
[asArray] =>
[multiple] =>
[primaryModel] =>
[link] =>
[via] =>
[inverseOf] =>
)
[key] =>
[db] =>
[id] =>
[_sort:yii\data\BaseDataProvider:private] =>
[_pagination:yii\data\BaseDataProvider:private] =>
[_keys:yii\data\BaseDataProvider:private] =>
[_models:yii\data\BaseDataProvider:private] =>
[_totalCount:yii\data\BaseDataProvider:private] =>
[_events:yii\base\Component:private] => Array()
[_behaviors:yii\base\Component:private] =>
)
UPDATE
I need to use function like this for each record:
if (myFunction(table_column_1, table_column_2)) {
result_is_ok_return_it
} else {
do_not_return_this_record
}
Why do you don't add your additional filters to query object used in DataProvider?
You can parse your conditions to $query->andFilterWhere(). If you need custom function for it just modify $dataProvider->query object inside function. After execute query in data provider you can only filter results by manually filter array of models stored in $dataProvider->models
To get result use models property or getModels()
For example,
$dataProvider->models;
OR
$dataProvider->getModels();
I think I came across a solution, (looks like it is working)
http://www.yiiframework.com/doc-2.0/yii-data-basedataprovider.html#setModels()-detail
After I do all my usual search stuff as described in question at beginning, I would do something like this using setModels() function
class PassengerSearch extends Passenger
public $status; // virtual attribute not present in database table
public function rules()
{
return [
// ... some other rules
[['status'], 'safe'],
];
}
// ...
$filtered_models = [];
$filter_models = false; // if you only want to filter if there is some value
foreach ($dataProvider->models as $model) {
// if ($model->status == 1) // example
if (!empty($this->status) && $model->status == $this->status) { // better approach, using virtual attribute $status
$filter_models = true;
$filtered_models[] = $model;
}
}
if ($filter_models)
$dataProvider->setModels($filtered_models);
return $dataProvider;
}

Update a HasMany records

I am converting a working app from cakephp2 to cakephp3. I'm struggling to get a form that updates hasMany records to work.
The app has the following structure:
MODELS:
use Cake\ORM\Table;
use Cake\Validation\Validator;
class AwardsTable extends Table
{
public function initialize(array $config)
{
$this->hasMany('Levels', ['sort' => 'sort_order']);
}
}
namespace App\Model\Entity;
use Cake\Auth\DefaultPasswordHasher;
use Cake\ORM\Entity;
class Award extends Entity
{
protected $_accessible = [
'name' => true,
'url' => true,
'organisation' => true,
'detail' => true,
'logo' => true,
'levels' => true,
'Levels' => true
];
}
IN THE FORM:
<?= $this->Form->input("levels.$i.name", 'label'=>false,'type'=>'text','value' => $award->name]);?>
<?= $this->Form->input("levels.$i.id", ['value' => $award->id]); ?>
CONTROLLER
$this->Awards->patchEntity($award, $this->request->data, ['associated' => ['Levels']]);
if ($this->Awards->save($award)) {
$this->Flash->success(__('Your Award has been saved.'));
$this->redirect(['action' => 'index']);
}
This seems inline with what is recommended here: http://book.cakephp.org/3.0/en/views/helpers/form.html#associated-form-inputs
I've tried a few variations with capitalisation & pluralisation. The award data saves correctly but the associated levels data does not save.
What am I missing to get the has_many association data to save?
EDIT: Example Data array submitted:
2016-01-28 23:32:56 Error: Array
(
[id] => 4
[name] => test award
[organisation] => test org
[url] => http://www.example.com
[detail] =>
[levels] => Array
(
[0] => Array
(
[name] => test 1
[id] => 4
)
[11] => Array
(
[name] => test
[id] => 16
)
)
[image] => Array
(
[name] =>
[type] =>
[tmp_name] =>
[error] => 4
[size] => 0
)
)
In LevelEntity verify if 'id' is accessible
protected $_accessible = [
'*' => true,
'id' => true,
];

How can I access private value from object

I have the following object
[yii\authclient\clients\Twitter_ef71f520786335688cd762d29aaa2ac98b6bd42f_token] => yii\authclient\OAuthToken Object
(
[tokenParamKey] => oauth_token
[tokenSecretParamKey] => oauth_token_secret
[createTimestamp] => 1447473086
[_expireDurationParamKey:yii\authclient\OAuthToken:private] =>
[_params:yii\authclient\OAuthToken:private] => Array
(
[oauth_token] => 48575497-RTIItaMJBC5LrFl0I2TjYw0ihByC0QuRdRxf44tVX
[oauth_token_secret] => IcdvTgwiclWGNhX4TrsDjEkEdNwVF7l1XzXmgpNstGfkV
[user_id] => **********
[screen_name] => ***********
[x_auth_expires] => 0
)
)
and in the above object I want to access the parameter oauth_token and oauth_token_secret which are under _params:yii\authclient\OAuthToken:private
How do I get those values in php?
https://github.com/yiisoft/yii2-authclient/blob/master/OAuthToken.php#L86
yii\authclient\OAuthToken has public method getParams() and getParam($name)