php with Nested JSON - php

These Items should be put together into a JSON variable, including shop details:
{
"Name": "Shop 1",
"Time": "2015-12-01 12:50",
"Items": [
{
"Name": "Item-1",
"Count": "4",
"Charge": "100"
},
{
"Name": "Item-3",
"Count": "4",
"Charge": "100"
}
],
"Total": "800"
}
To get the outer JSON part I use:
class PrintData {
public $Name = "";
public $Time = "";
// ??
public $Total = "";
}
$printdata = new PrintData();
$printdata->Name=$shop_name;
$printdata->Time=$os_tsready;
// ?? $printdata->Item=$printitems;
$printdata->Total=1007;
However, I cannot figure out how I can get the two Item lines into JSON.
foreach($orderrecords as $or) {
$o_name=escape($or->o_name);
$o_cout=escape($or->o_count);
$o_charge=escape($or->o_charge);
How can I add the Item records correctly?

Fully OOP approach:
class Item {
public $Name;
public $Count;
public $Charge;
public function __construct($name, $count, $charge) {
$this->Name = $name;
$this->Count = $count;
$this->Charge = $charge;
}
}
class PrintData {
public $Items;
public $Name;
public $Time;
public $Total;
public function __construct($name, $time, $items, $total) {
$this->Name = $name;
$this->Time = $time;
$this->Total = $total;
$this->Items = $items;
}
}
$res = new PrintData(
"Shop 1",
"2015-12-01 12:50",
array(
new Item("Item-1", "4", "100"),
new Item("Item-3", "4", "100"),
),
"800"
);
echo json_encode($res);

Try this:
class PrintData {
public $Name = "";
public $Time = "";
public $Items = [];
public $Total = "";
}
$printdata = new PrintData();
$printdata->Name=$shop_name;
$printdata->Time=$os_tsready;
$printdata->Items=$printitems;
$printdata->Total=1007;
Where $printitems is an array of $item elements (like below)
And individually,
$item = array(
"Name" => "Item-1",
"Count" => "4",
"Charge" => "100"
);
$printdata->Items[0] = $item;
Online code: https://3v4l.org/R4s2C

$printitems should be an array here.
$printitems = array(
array('Name' => 'Item-1', 'Count' => '4', 'Charge' => '100'),
array('Name' => 'Item-3', 'Count' => '4', 'Charge' => '100')
);
Final Code
<?php
class PrintData {
public $Name = "";
public $Time = "";
// ??
public $Total = "";
}
$printdata = new PrintData();
$printdata->Name= 'Shop 1';
$printdata->Time='2015-12-01 12:50';
// ?? $printdata->Item=$printitems;
$printdata->Total='800';
$printitems = array(
array('Name' => 'Item-1', 'Count' => '4', 'Charge' => '100'),
array('Name' => 'Item-3', 'Count' => '4', 'Charge' => '100')
);
$printdata->Item = $printitems;
echo '<pre>';
// TILL NOW $printdata is an Object
// json_encode() converts $printdata into JSON Object
print_r(json_encode($printdata)); // THIS WILL GIVE YOUR DESIRED RESULT

Related

String to array transformation [PHP]

Simple question how can i transform this string:
"'One' => 1,'Two' => 2,'Three' => 3,'Four' => 4,"
To an array like this :
array['One'] = 1;
array['Two'] = 2;
array['Three'] = 3;
array['Four'] = 4;
Use regex and array_combine
preg_match_all('/\'(\w+)\'\s*=>\s*(\d+)/', $str, $m);
print_r(array_combine($m[1], $m[2]));
demo
$string = "'One' => 1,'Two' => 2,'Three' => 3,'Four' => 4,";
$array = explode(',',$string);
foreach($array as $item){
$new_items = explode(' => ', $item);
$key = $new_items[0];
$value = $new_items[1];
$new_array[][$key] = $value;
}
var_dump($new_array);
Here a tested solution:
$input = "'One' => 1,'Two' => 2,'Three' => 3,'Four' => 4,";
$gen = new ArrayGenerator($input);
$this->assertSame([
'One' => 1,
'Two' => 2,
'Three' => 3,
'Four' => 4,
], $gen->translate());
and here complete code
use PHPUnit\Framework\TestCase;
class FooTest extends TestCase
{
public function testItems()
{
$input = "'One' => 1,'Two' => 2,'Three' => 3,'Four' => 4,";
$parser = new Parser($input);
$this->assertEquals([
"'One' => 1",
"'Two' => 2",
"'Three' => 3",
"'Four' => 4"
], $parser->items());
}
public function testKeyValue()
{
$input = "'One' => 1";
$parser = new KeyValue($input);
$this->assertEquals([
"'One'",
"1",
], $parser->items());
}
public function testKeyValueWithoutQuotas()
{
$input = "'One' => 1";
$parser = new KeyValue($input);
$this->assertEquals([
"One",
"1",
], $parser->itemsWithoutQuotas());
}
public function test()
{
$input = "'One' => 1,'Two' => 2,'Three' => 3,'Four' => 4,";
$gen = new ArrayGenerator($input);
$this->assertSame([
'One' => 1,
'Two' => 2,
'Three' => 3,
'Four' => 4,
], $gen->translate());
}
}
class ArrayGenerator
{
private $input;
public function __construct(string $input)
{
$this->input = $input;
}
public function translate()
{
$parser = new Parser($this->input);
$parsed = $parser->items();
$trans = [];
foreach ($parsed as $item) {
$pair = new KeyValue($item);
$trans[$pair->itemsWithoutQuotas()[0]] = (int) $pair->itemsWithoutQuotas()[1];
}
return $trans;
}
}
class KeyValue
{
private $input;
public function __construct(string $input)
{
$this->input = $input;
}
public function items()
{
$exploded = explode(' => ', $this->input);
return $exploded;
}
public function itemsWithoutQuotas()
{
$items = $this->items();
foreach ($items as $key => $item) {
$items[$key] = str_replace("'", "", $item);
}
return $items;
}
}
class Parser
{
private $input;
public function __construct(string $input)
{
$this->input = $input;
}
public function items()
{
$exploded = explode(',', $this->input);
$exploded = array_filter($exploded, function ($item) {
return $item != "";
});
return $exploded;
}
}
You can simply use the php function array_flip:
array_flip — Exchanges all keys with their associated values in an
array
Warning on collision:
If a value has several occurrences, the latest key will be used as its
value, and all others will be lost.
Example #2 array_flip() example : collision
<?php
$input = array("a" => 1, "b" => 1, "c" => 2);
$flipped = array_flip($input);
print_r($flipped);
?>
The above example will output:
Array
(
[1] => b
[2] => c
)

How to get join table data and pass inside array in php

I have two tables order and orderDetail. i have multiple delivery address in order detail table based on id of order table
i want to display id from order table and deliveryAddress from order detail table.i am getting below output when i print..
but unable to display delivery_address.please anyone can suggest how i display delivery_address..
{
"responseData": {
"status": 1,
"message": "",
"result": [
{
"Order": {
"id": "677",
"detail_location_instructions": "Near Inox"
},
"OrderDetail": [
{
"order_id": "677",
"delivery_address": "Smart Club Gimnasio - Avenida Álvarez Thomas, Buenos Aires, Autonomous City of Buenos Aires, Argentina"
},
{
"order_id": "677",
"delivery_address": "Lower Fort Street, Dawes Point, New South Wales, Australia"
}
]
},
{
"Order": {
"id": "680"
},
"OrderDetail": []
},
{
"Order": {
"id": "684"
},
"OrderDetail": [
{
"order_id": "684",
"delivery_address": "Four Seasons - Posadas"
}
]
}
]
}
}
below is my code
public function getOrderlist(){
if($this->processRequest){
$err = false;
if(empty($this->requestData['id'])){
$this->responceData['message'] = "Please provide User ID";
$err = true;
}
if(!$err){
$id = trim($this->requestData['id']);
$conditions = array('Order.user_id'=>$id);
$data = $this->Order->find('all',array('conditions'=>$conditions));
if(!empty($data)){
$c = array();
foreach ($data as $key => $value) {
$c[] = array(
'Id' => $value['Order']['id'],
'deliveryAddress' => $value['OrderDetail']['delivery_address']
);
}
}
$this->responceData['result'] = $c;
$this->responceData['status'] = 1;
}
}
}
You have to put the deliveryAddress in array
$c = array();
foreach ($data as $key => $value) {
$myOrders = [
'Id'=>$value['Order']['id'],
'deliveryAddress'=>[]
];
foreach($value['OrderDetail'] as $address){
$myOrders['deliveryAddress'][] = $address['delivery_address'];
}
$c[] = $myOrders;
}
Hope this will help
can you trying below code.
foreach ($data as $key => $value) {
$c[] = array(
'Order' => array(
'id'=>$value['Order']['id'],
'detail_location_instructions' => $value['Order']['detail_location_instructions'],
),
'OrderDetail' => array(
'order_id'=>$value['Order']['id'],
'deliveryAddress' => $value['OrderDetail']['delivery_address'],
),
)
}
There is cases where you dont get the delivery address, in that case, you need to check if it exists first. use the Hash utility for that purpose.
I transformed the data to an array, in order for the class Hash to work.
public function getOrderlist(){
if($this->processRequest){
$err = false;
if(empty($this->requestData['id'])){
$this->responceData['message'] = "Please provide User ID";
$err = true;
}
if(!$err){
$id = trim($this->requestData['id']);
$conditions = array('Order.user_id'=>$id);
$data =(array) $this->Order->find('all',array('conditions'=>$conditions));
if(!empty($data)){
$c = array();
foreach ($data as $key => $value) {
$c[] = array(
'Id' => Hash::get($value, 'Order.id'),
'deliveryAddress' => current(Hash::extract($value, 'OrderDetail.{n}.delivery_address', array()))
);
}
}
$this->responceData['result'] = $c;
$this->responceData['status'] = 1;
}
}
}

OOP and switch statements

I have this OOP code in php
class SSE {
static function setSection($opt_name,array $settings){
var_dump($settings["fields"]);
foreach ($settings["fields"] as $field){
self::processField($opt_name,$field);
}
}
static function processField($opt_name,array $field){
switch ($field["type"]){
case "number":
$number = new Number($field["title"],$field["desc"],$field["id"]);
echo "<br>$number";
break;
case "checkbox":
$checkbox = new Checkbox($field["title"],$field["desc"],$field["id"],$field["color"]);
echo "<br>$checkbox";
break;
}
}
}
class Input {
protected $title;
protected $desc;
protected $id;
}
class Number extends Input {
//protected $fields = array();
function __toString(){
return $this->title;
}
public function __construct($title,$desc,$id){
$this->title = $title;
$this->desc = $desc;
$this->id = $id;
}
}
class Checkbox extends Input {
//protected $fields = array();
protected $color;
function __toString(){
return $this->title;
}
public function __construct($title,$desc,$id,$color){
$this->title = $title;
$this->desc = $desc;
$this->id = $id;
$this->color = $color;
}
}
$test1 = array(
"title" => "Ssadassa",
"id" => "basic",
"desc" =>"this is a test",
"fields" => array(
array(
"title" => "Checkbox input",
"id" => "ba32132sic",
"desc" =>"this is a test",
"type" => "checkbox",
"color" => "This is only for checkbox no another input should have this"
),
array(
"title" => "Number input",
"id" => "basic",
"desc" =>"this is a test",
"type" => "number"
)
)
);
SSE::setSection("da",$test1);
What to do about the switch statement?Later I may add textarea input and I have to go and edit the switch statemt.I have looked here https://sourcemaking.com/design_patterns but I don't know with one fits this case maybe factory no idea.This is my first OOP try.
By the way the array $test1 must not be changed I mean the way some one uses those clases must be the same.Any help really appreciated.Thank you.
Edit:The question is:Is anything wrong if I use the switch statement?Is a better way to do this?
You could create class map, and special methods to create inputs from options.
class SSE { // please rename this
static private $mapClass = ['number' => 'Number', 'checkbox' => 'Checkbox'];
static function setSection($opt_name, array $settings) {
// var_dump($settings["fields"]);
foreach ($settings["fields"] as $field) {
self::processField($opt_name, $field);
}
}
static function processField($opt_name, array $field) {
// recognize class from class map
$class = self::$mapClass[$field["type"]];
$input = $class::createFromOptions($field);
echo "<br>$input";
}
}
class Input {
protected $title;
protected $desc;
protected $id;
}
class Number extends Input {
//protected $fields = array();
function __toString() {
return $this->title;
}
public function __construct($title, $desc, $id) {
$this->title = $title;
$this->desc = $desc;
$this->id = $id;
}
// create object from array
static public function createFromOptions(array $options) {
return new self($options["title"], $options["desc"], $options["id"]);
}
}
class Checkbox extends Input {
//protected $fields = array();
protected $color;
function __toString() {
return $this->title;
}
public function __construct($title, $desc, $id, $color) {
$this->title = $title;
$this->desc = $desc;
$this->id = $id;
$this->color = $color;
}
// create object from array
static public function createFromOptions(array $options) {
return new self($options["title"], $options["desc"], $options["id"], $options["color"]);
}
}
$test1 = array(
"title" => "Ssadassa",
"id" => "basic",
"desc" => "this is a test",
"fields" => array(
array(
"title" => "Checkbox input",
"id" => "ba32132sic",
"desc" => "this is a test",
"type" => "checkbox",
"color" => "This is only for checkbox no another input should have this"
),
array(
"title" => "Number input",
"id" => "basic",
"desc" => "this is a test",
"type" => "number"
)
)
);
SSE::setSection("da", $test1);
Also, you could add options validator to make sure that all mandatory options has passed and there is no extra options.
Why not ucfirst? Because you are able to use camel case class name, for example RichText (textarea with wysiwyg). Or write more smart class recognizer.

php: additional output from foreach of array

i'm trying to refresh my memory of OO & array structure. i have,
class room{
private $people = array(
'name' => array(
'height' => null,
'age' => null
)
);
function set($list){
foreach($list as $person){
$this->people[$person['name']]['height'] = $person['height'];
$this->people[$person['name']]['age'] = $person['age'];
}
}
function print(){
foreach($this->people as $k => $v){
echo $k . "<br>";
echo $v['height'] . ":" . $v['age'] . "<br><br>";
}
}
}
$input = array( array('name' => 'John', 'height' => '6.4', 'age' => '20'),
array('name' => 'Jane', 'height' => '5.2', 'age' => '21')
);
$i = new room;
$i->set($input);
$i->print();
the output is,
name
:
John
6.4:20
Jane
5.2:21
i'm confused as why name : appears first, when the input array only contains 2 values of each person. i am unsure if i am using my arrays correctly, could someone point out my mistake?
My overall aim of this is to have correct understanding of arrays within arrays & how to best set & get the values
It's because you've initialised the $people array to contain those values
private $people = array(
'name' => array(
'height' => null,
'age' => null
)
);
Change it to:
private $people = array();
that's the good way to do it
your people class
class people {
//properties
private $name;
private $height;
private $age;
//setters
public function setName($name) {
$this->name = $name;
}
public function setHeight($height) {
$this->height = $height;
}
public function setAge($age) {
$this->age = $age;
}
//getters
public function getName() {
return $this->name;
}
public function getHeight() {
return $this->height;
}
public function getAge() {
return $this->age;
}
}
your room class
class room {
//properties
private $people = array();
//setters
public function setPeople($people) {
$this->people[] = $people;
}
//getters
public function getPeoples() {
return $this->people;
}
}
and how to control it in OOP
$people1 = new people();
$people1->setName('John');
$people1->setHeight('6.4');
$people1->setAge('20');
$people2 = new people();
$people2->setName('Jane');
$people2->setHeight('5.2');
$people2->setAge('21');
$room = new room();
$room->setPeople($people1);
$room->setPeople($people2);
// Removing people array initial data will solve the issue :)
class room{
private $people = array();
function set($list){
foreach($list as $person){
$this->people[$person['name']]['height'] = $person['height'];
$this->people[$person['name']]['age'] = $person['age'];
}
}
function print(){
foreach($this->people as $k => $v){
echo $k . "<br>";
echo $v['height'] . ":" . $v['age'] . "<br><br>";
}
}
}
$input = array( array('name' => 'John', 'height' => '6.4', 'age' => '20'),
array('name' => 'Jane', 'height' => '5.2', 'age' => '21')
);
$i = new room;
$i->set($input);
$i->print();

Can't find the error behind the undefined index

I have the following code, and i keep getting undefined index error, the code is failing on test5() but i'm unable to find the error.
<?php
function test1() {
$vars = [0, 1, 2, 4, 3];
for ($i = 0; $i < count($vars); $i++) {
print $vars[$i] . "\n";
}
}
function test2() {
$flavors = ['vanilla', 'pistachio', 'banana', 'caramel', 'strawberry'];
$favorite = 'banana';
foreach ($flavors as $key => $flavor) {
if ($flavor === $favorite) {
print $key . "\n";
break;
}
}
}
function test3() {
$stuff = ['shoes', 33, null, false, true];
$selected = 0;
foreach ($stuff as $key => $thing) {
if ($thing == $selected) {
print $key . "\n";
break;
}
}
}
function test4() {
$four = 4;
$five = test4_helper($four);
print "four: $four\n";
print "five: $five\n";
}
function test4_helper(&$arg) {
$return = $arg++;
return $return;
}
function test5() {
$products = [
'Trek Fuel EX 8' => [
'price' => 2000,
'quantity' => 1
],
'Trek Remedy 9' => [
'price' => 2600,
'quantity' => 2
],
'Trek Scratch 8' => [
'price' => 3500,
'quantity' => 1
]
];
$total = 0;
$callback = function ($product, $name) {
//$total = 0;
$tax = 1.2;
$price = $product[$name]['price'];
$total += ($price * $product[$name]['quantity']) * $tax;
return $total;
};
array_walk($products, $callback);
print "$total\n";
}
/* * **********************************
* *** DO NOT EDIT BELOW THIS LINE ****
* *********************************** */
$tests = 5;
for ($i = 1; $i <= $tests; $i++) {
$function = "test$i";
print "\n\n==== Test $i ====\n";
$function();
print "==== END of test $i ====\n <br>";
}
what is the problem with this code?
it looks that it's failing on test 5
PHP closures are not like JavaScript ones in that they do not inherit the parent scope. You need to pass in any dependencies via the use construct. In your example...
$callback = function ($product, $name) use ($total) {
// etc
See http://php.net/manual/functions.anonymous.php#example-166
Arrays in PHP are defined like this:
$products = array(
'Trek Fuel EX 8' => array(
'price' => 2000,
'quantity' => 1
),
'Trek Remedy 9' => array(
'price' => 2600,
'quantity' => 2
),
'Trek Scratch 8' => array(
'price' => 3500,
'quantity' => 1
)
);
Which means you also need to look at $vars = [0, 1, 2, 4, 3]; and $flavors = ['vanilla', 'pistachio', 'banana', 'caramel', 'strawberry']; and fix them too.

Categories