php: additional output from foreach of array - php

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();

Related

php laravel foreach loop giving only 1 result from the array

what I want to do is to print the data with foreach, but whatever I have done, it prints the last element and not the other one,
where am i going wrong?
I want "PartyIdentification" to return up to each element.
I don't understand if I'm making a mistake in get and sets. Is there a short solution? I want to print more than one property.
the result of my output
i want to do
$aa = array(
0 => ['ID' => ['val' => '4000068418', 'attrs' => ['schemeID="VKN"']]],
1 => ['ID' => ['val' => '12345678901', 'attrs' => ['schemeID="TICARETSICILNO"']]],
2 => ['ID' => ['val' => '132546555', 'attrs' => ['schemeID="MERSISNO"']]]
);
$invoice_AccountSupplierParty_Party = new \Pvs\eFaturaUBL\Party();
$invoice_AccountSupplierParty_Party->PartyIdentification = InvoiceBuilder::getasd($aa);
public static function getasd(array $data)
{
$asd = new Olusturma();
$date = array();
foreach ($data as $datum) {
$asd->getID($data);
}
return $asd->getResult();
}
namespace App\Support\Invoice;
class Olusturma
{
public $contactDetails = array();
public function __construct()
{
$this->contactDetails = new \Erkan\eFaturaUBL\PartyIdentification();
}
public function setOlusturma(): Olusturma
{
return $this;
}
public function getID($data)
{
foreach ($data as $row => $innerArray) {
foreach ($innerArray as $innerRow => $value) {
$this->setID($value);
}
}
return $this;
}
public function setID($data): Olusturma
{
$this->contactDetails->ID = $data;
return $this;
}
public function getResult(): \Erkan\eFaturaUBL\PartyIdentification
{
return $this->contactDetails;
}

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 with Nested JSON

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

Retrieving Data from an object of an array of arrays

I know this question is more data structures but since I am doing it in Symfony there might be a simpler way. I have a recursive function treeBuilder() I want to call on some data to create a hierarchy. Say a database of people and I want to create a tree structure if they live with their parents. I know I am passing an array of object to the function but it needs to be an array. I am pretty sure I need to rewrite this function so that it handles the the array of object but am stumped. I am not sure how to access the elements of the array to check the parentid. I know the code below is not correct but that is where I am at now.
Controller:
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('CompanyMyBundle:Org')->findAll();
var_dump($entities);
$tree=$this->treeBuilder($entities);
return array(
'entities' => $tree,
);
}
private function treeBuilder($ar, $pid=null)
{
$op=array();
foreach( $ar as $item ) {
// I know I have an array of objects
if( $item['ParentId'] == $pid ) {
$op[$item['Id']] = array(
'Street' => $item['Street'],
'ParentId' => $item['ParentId']
);
$children = self::treeBuilder( $ar, $item['Id'] );
if( $children ) {
$op[$item['Id']]['children'] = $children;
}
}
}
return $op;
}
var_dump($entities) from indexAction():
/export/www/working/symfony/src/Company/MyBundle/Controller/DepController.php:34:
array (size=60)
0 =>
object(Company\MyBundle\Entity\Org)[1556]
private 'Name' => string 'Me' (length=46)
private 'Street' => string '123 Sesame' (length=255)
private 'City' => string 'Myhometown' (length=255)
private 'ParentId' => int 0
private 'Id' => int 1
1 =>
object(Company\MyBundle\Entity\Org)[1557]
private 'Name' => string 'Me2' (length=46)
private 'Street' => string '123 Sesame' (length=255)
private 'City' => string 'Myhometown' (length=255)
private 'ParentId' => int 1
private 'Id' => int 2
If you need to get entities as arrays instead of objects, you would need to use Doctrine's hydrator:
$em = $this->getDoctrine()->getManager();
$orgRepo = $em->getRepository('CompanyMyBundle:Org');
$entities = $orgRepo->createQueryBuilder('org')
->getQuery()
->getResult(\Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY);
Note:
I would suggest to leave entities as objects and use getters:
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('CompanyMyBundle:Org')->findAll();
$tree = $this->treeBuilder($entities);
return array(
'entities' => $tree,
);
}
private function treeBuilder($entities, $pid = null)
{
$op = array();
/** Org $entity */ //Type hinting, if you use autocompletion
foreach ($entities as $entity) {
if ($entity->getParentId() == $pid) {
$op[$entity->getId()] = [
'Street' => $entity->getStreet(),
'ParentId' => $entity->getParentId()
];
$children = self::treeBuilder($entities, $entity->getId());
if (!empty($children)) {
$op[$entity->geId()]['children'] = $children;
}
}
}
return $op;
}

PHP class to JSON on several levels

I have a PHP class I would like to transform in a JSON on several levels like this type:
{"interface":{"Version":"0"},"Container":[{"id":"1","Element":[{"text":"Test","id":"0"},{"text":"Toto","id":"1"}]}]}
In my PHP class I have a function who returns the JSON of my private attributes who are arrays:
return (json_encode((get_object_vars($this)), JSON_UNESCAPED_UNICODE));
Private attributes of my class:
private $interface = '';
private $Container = array(array('id' => '1'));
private $Element = array('text' => 'Test', 'id' => '0');
Do you know how I could have a JSON like above ?
In pleasure to read you.
Not sure about your class members but as long as they are accessible you can generate the JSON string. Below if the example of this
$Contenant = array(array('id' => '1'));
$Element = array('text' => 'Test', 'id' => '0');
$json = json_encode(array('inerrface'=>array(
'content'=>$Contenant,
"Element"=>$Element
)
)
);
echo $json ;
You could implement the IteratorAggregate interface like in the following example
class YourClass implements IteratorAggregate {
protected $member1 = array();
protected $member2 = array();
...
public function getIterator() {
$tmpArr = array();
// create the structure you want in $tmpArr
return new ArrayIterator($tmpArr);
}
}
$myClass = new MyClass();
$iterator = $myClass->getIterator();
$encodedData = json_encode($iterator);
As of PHP5.4 you have the JsonSerializable interface ready to use. With this interface, you cann use direct modifications like in the example given in: http://de2.php.net/manual/en/jsonserializable.jsonserialize.php
have fun! ;)
This will get you started, take a look at the constructor what data input requires. You could make a private function doing the same thing, assigning your values to the structure and then printing it:
class Test{
private $data;
public function __construct($version = 0, $records = array()){
$data['interface'] = array('Version' => $version);
$data['Container'] = array();
for ($i = 0; $i < count($records); $i++) {
$data['Container'][$i] = $records[$i];
}
// your test input
print_r(json_decode('{"interface":{"Version":"0"},"Container":[{"id":"1","Element":[{"text":"Test","id":"0"},{"text":"Toto","id":"1"}]}]}',true));
// actual input
print_r($data);
// printing our actual data as json string
echo json_encode($data);
}
public function __destruct(){
}
}
$element1 = array('text' => 'Test', 'id' => 0);
$element2 = array('text' => 'Toto', 'id' => 1);
$elements = array($element1, $element2);
$record = array('id' => 1, 'element' => $elements);
$records = array($record);
new Test(0, $records);
You need to structure it, working example: example
class test {
private $interface = '';
private $Contenant = array(array('id' => '1'));
//private $Element = array(array('text' => 'Test', 'id' => '0'));
public function json(){
$this->Contenant = array(
array('id' => '1',
'Element' => array(array('text' => 'Test', 'id' => '0'))
),
);
return json_encode((get_object_vars($this)), JSON_UNESCAPED_UNICODE);
}
}
$t = new test();
$encode = $t->json();
echo $encode;
OUTPUT
{"interface":"","Contenant":[{"id":"1","Element":[{"text":"Test","id":"0"}]}]}

Categories