Creating php classes tree from a json object - php

EDIT
Ok it seems I'm really bad at describing my problem. I found this generator on the web, and what I'm looking for it's the exact same thing but for php code. any idea ?
ORIGINAL QUESTION
I am willing to build many php classes from a json representation (API mapping to object), and to do that I'd like to convert this:
{
"success": true,
"domains": [
{
"id": "13",
"manual": "0",
"name": "silo3.mobi",
"lastname": "Doe",
"firstname": "John",
"cid": "1",
"period": "1",
"recurring_amount": "9.95",
"currency_id": "0",
"module": "namesilo",
"next_due": "2012-12-12",
"expires": "2012-12-12",
"status": "Active",
"type": "Register",
"date_created": "2011-12-12",
"autorenew": "1",
"reglock": "1",
"idprotection": "1"
},
{
"id": "11",
"manual": "0",
"name": "netearthorg.org",
"lastname": "Doe",
"firstname": "John",
"cid": "1",
"period": "1",
"recurring_amount": "9.95",
"currency_id": "0",
"module": "NetEarthOne",
"next_due": "2012-11-22",
"expires": "2012-11-22",
"status": "Active",
"type": "Register",
"date_created": "2011-11-22",
"autorenew": "1",
"reglock": "1",
"idprotection": "0"
},
{
"id": "10",
"manual": "0",
"name": "hbappreseller.co.uk",
"lastname": "Blue",
"firstname": "Mike",
"cid": "6",
"period": "2",
"recurring_amount": "9.95",
"currency_id": "0",
"module": "NetEarthOne",
"next_due": "2012-11-22",
"expires": "0000-00-00",
"status": "Pending",
"type": "Register",
"date_created": "0000-00-00",
"autorenew": "1",
"reglock": "0",
"idprotection": "0"
}
],
"call": "getDomains",
"server_time": 1323793581
}
to an object with a bool:success property, an array of "domain" object and so on.
It's not that hard to do, I could develop that myself, but I'm wondering if there is some php libs that take care of that, haven't found any
EDIT
Ok I haven't explained myself so well I guess, what I'd like to do it's build a php class file, with dependencies on other classes and so on so I can match the json structure.
For instance, the given json should generate the following:
class Domain {
protected $id;
protected $manual;
protected $name;
protected $lastname;
protected $firstname;
protected $cid;
protected $period;
protected $recurring_amount;
// and so on
}
The purpose is to serve a WSDL with complex objects, and avoid making the wsdl signature evolve if any modifications are made on the original API (custom classes won't change dinamically, only when wanted so the WSDL will stay the same)
The api generate hundred of json objects, some of them sharing properties, so the purpose of this is to have a global way to handle all json strings and build or get builded objects, for example two json can have the "domains" property, so the first time I want to generate a class named Domain (if property=array then create file with property name -S and fill with attributes then save to file for further usage)

Lets say your JSON object is stored in $json, then you can create a class on the fly like this -
$data = json_decode($json, true);
$class = new Domain();
foreach ($data AS $key => $value) $class->{$key} = $value;
If you want a more generic way, let's say you want to change the class name on the fly -
$data = json_decode($json, true);
$className = "Domain"; // Or assign it to something else like pick from DB, from JSON from anywhere.
$class = new {$className}();
foreach ($data AS $key => $value) $class->{$key} = $value;

Ok, finally I found nothing to do the job of json2csharp tool, so I developed mine:
namespace Hostbill\Api\Generator;
use Zend\Code\Generator\ClassGenerator;
use Zend\Code\Generator\PropertyValueGenerator;
use Zend\Code\Reflection\ClassReflection;
use Zend\Json\Json;
use Zend\Json\Exception\RuntimeException as JsonRuntimeException;
class DataGenerator extends AbstractGenerator
{
const DATA_NAMESPACE = 'Hostbill\Api\Data';
const RESPONSE_SUFFIX = 'Response';
const DATA_ABSTRACT_CLASS = 'AbstractData';
/**
* #var ClassGenerator[]
*/
protected $classes = array();
/**
* #var ClassGenerator
*/
protected $responseClass;
/**
* Build classes from a source json string
* #param string $json
*/
public function fromSource($json)
{
try {
$data = Json::decode($json, Json::TYPE_ARRAY);
} catch (JsonRuntimeException $e) {
$this->err(sprintf('Could not generate classes for given Json, err:"%s"', $e->getMessage()));
return;
}
$this->parse($data);
// write classes files
$this->write($this->responseClass, sprintf('%s/../Data/', __DIR__));
foreach ($this->classes as $class) {
if (self::RESPONSE_SUFFIX === substr($class->getName(), -strlen(self::RESPONSE_SUFFIX))) {
$this->write($class, sprintf('%s/../Data/Response/', __DIR__));
} else {
$this->write($class, sprintf('%s/../Data/', __DIR__));
}
}
}
/**
* Parse json decoded object and generate corresponding classes
* #param array $data associative array retrieved from json_decode
* #return DataGenerator
*/
public function parse($data)
{
$responseClassNamespace = sprintf('%s\%s', self::DATA_NAMESPACE, self::RESPONSE_SUFFIX);
// get "call" property and build Response class name on it: getClientDetails => ClientDetailResponse
$parts = preg_split('/(?=[A-Z])/', $data['call'], -1, PREG_SPLIT_NO_EMPTY);
array_shift($parts); // remove verb
$parts[] = $this->inflector()->singularize(array_pop($parts));
$parts[] = self::RESPONSE_SUFFIX;
$baseResponseClassName = sprintf('%s\%s', self::DATA_NAMESPACE, self::RESPONSE_SUFFIX);
$responseClass = new ClassGenerator(
implode('', $parts),
$responseClassNamespace,
null,
self::RESPONSE_SUFFIX
);
$responseClass->addUse($baseResponseClassName);
$this->addClass($responseClass);
if (!class_exists($baseResponseClassName)) {
$baseResponseClassGenerated = true;
$baseResponseClass = new ClassGenerator(
self::RESPONSE_SUFFIX,
self::DATA_NAMESPACE,
ClassGenerator::FLAG_ABSTRACT
);
} else {
$baseResponseClassGenerated = false;
$baseResponseClass = ClassGenerator::fromReflection(new ClassReflection($baseResponseClassName));
}
$this->responseClass = $baseResponseClass;
foreach ($data as $key => $value) {
$key = $this->inflector()->pascalize($key);
if (is_scalar($value)) {
// thoses properties belongs to the response class
// if we just have generated the "base" response class (Response.php)
// store properties there (there are only 3 basic properties: success, call, serverTime)
// otherwise store them in the child response class, but avoid any overriding of the
// 3 properties which are stored in base Response class
if ($baseResponseClassGenerated) {
$responseClassToUpdate = $baseResponseClass;
} else {
$responseClassToUpdate = $responseClass;
}
// update base response class
if (!$responseClassToUpdate->hasProperty($key) && !$baseResponseClass->hasProperty($key)) {
$responseClassToUpdate->addProperty($key);
}
} else {
// object
if ($this->isArrayAssociative($value)) {
if (!$responseClass->hasProperty($key)) {
$responseClass->addProperty($key);
}
$this->parseObject($key, $value);
// array
} else {
if (!$responseClass->hasProperty($key)) {
$responseClass->addProperty($key, new PropertyValueGenerator(array(), PropertyValueGenerator::TYPE_ARRAY));
}
// if array is simple array, do nothing
if (!is_scalar(reset($value))) {
$this->parseArrayOfObjects($key, $value);
}
}
}
}
return $this;
}
/**
* Parse ordered array and create class object
* #param string $name key name
* #param array $data
* #return DataGenerator
*/
public function parseArrayOfObjects($name, $data)
{
$class = $this->getOrCreateClass($this->inflector()->singularize($name));
foreach ($data as $object) {
foreach ($object as $key => $value) {
if (!$class->hasProperty($key)) {
$class->addProperty($key);
}
}
}
return $this;
}
/**
* Parse associative array and create class object
* #param string $name key name
* #param array $data
* #return DataGenerator
*/
public function parseObject($name, $data)
{
$class = $this->getOrCreateClass($this->inflector()->singularize($name));
foreach ($data as $key => $value) {
if (!$class->hasProperty($key)) {
$class->addProperty($key);
}
}
return $this;
}
/**
* Add class to current stack
* #param ClassGenerator $class
* #return DataGenerator
*/
protected function addClass(ClassGenerator $class)
{
$this->classes[$this->inflector()->lowerize($class->getName())] = $class;
return $this;
}
/**
* Get class from current stack
* #param string $name
* #return false|ClassGenerator False if not found
*/
protected function getClass($name)
{
$id = $this->inflector()->lowerize($name);
if (!isset($this->classes[$id])) {
return false;
}
return $this->classes[$id];
}
/**
* Try to retrievea class from current stack, create it if not found
* #param string $name
* #return ClassGenerator
*/
protected function getOrCreateClass($name)
{
if (!$class = $this->getClass($name)) {
$class = new ClassGenerator(
$this->inflector()->camelize($name),
self::DATA_NAMESPACE,
null,
self::DATA_ABSTRACT_CLASS
);
$this->addClass($class);
}
return $class;
}
/**
* Check if the given array is associative
* #param array $array
* #return bool
*/
protected function isArrayAssociative($array)
{
return (bool)count(array_filter(array_keys($array), 'is_string'));
}
}
This code is so oriented for my needs, but it can easily be adapted to any json file, here the result:
JSON
{
"success": true,
"client": {
"id": "1",
"email": "jondoe#email.com",
"password": "474bf122c92de249ace867a003cb7196",
"lastlogin": "2011-11-25 04:32:40",
"ip": "213.54.21.3",
"host": "cmt-random.uk",
"status": "Active",
"parent_id": "0",
"firstname": "John",
"lastname": "Doe",
"companyname": "",
"address1": "Address 54",
"address2": "",
"city": "Soullans",
"state": "Birmingham",
"postcode": "B33 8TH",
"country": "GB",
"phonenumber": "357755733",
"datecreated": "2011-09-24",
"notes": "",
"language": "spanish",
"company": "0",
"credit": "0.00",
"taxexempt": "0",
"latefeeoveride": "0",
"cardtype": "Visa",
"cardnum": null,
"expdate": null,
"overideduenotices": "0",
"client_id": "1",
"currency_id": "0",
"countryname": "United Kingdom"
},
"call": "getClientDetails",
"server_time": 1323442995
}
GENERATED FILES (docblocks are missing but will be integrated so the WSDL is served correctly)
ClientResponse.php (base object)
namespace Hostbill\Api\Data\Response;
use Hostbill\Api\Data\Response;
class ClientResponse extends Response
{
public $clientId = null;
public $info = array(
);
}
Client.php
namespace Hostbill\Api\Data;
class Client extends AbstractData
{
public $id = null;
public $email = null;
public $password = null;
public $lastlogin = null;
public $ip = null;
public $host = null;
public $status = null;
public $parent_id = null;
public $firstname = null;
public $lastname = null;
public $companyname = null;
public $address1 = null;
public $address2 = null;
public $city = null;
public $state = null;
public $postcode = null;
public $country = null;
public $phonenumber = null;
public $datecreated = null;
public $notes = null;
public $language = null;
public $company = null;
public $credit = null;
public $taxexempt = null;
public $latefeeoveride = null;
public $cardtype = null;
public $cardnum = null;
public $expdate = null;
public $overideduenotices = null;
public $client_id = null;
public $currency_id = null;
public $countryname = null;
public $services = null;
}

I made a PHP class generator that will make models with JSON https://json2php.strikebit.io/. It will recursively inspect your JSON and make corresponding classes.

In my opinion, you should not create objects for generic data like this. You could easily map this against a generic data object.
So your framework would be just standard PHP. Like :
class JsonObject
{
protected $data = array();
public function __construct($data)
{
$this->data = $data;
}
public function __get($var)
{
if (array_key_exists($var, $this->data)) {
return $this->data[$var];
} else {
throw new Exception($var . ' not found in ' . __CLASS__);
}
}
public function __set($var, $val)
{
if (array_key_exists($var, $this->data)) {
return $this->data[$var];
} else {
throw new Exception($var . ' not found in ' . __CLASS__);
}
}
}
class Domain extends JsonObject
{
//some domain specific functionality
}
class getDomainResult
{
public $domains = array();
public $success = false;
public $lastTime = 0;
//some methods to do the calls
public function callback($result)
{
$res = json_decode($result, true);
$this->success = $res['success'];
$this->lastTime = $res['server_time'];
foreach ($res['domains'] as $domain) {
$this->domains[] = new Domain($domain);
}
}
}

Related

create json model and api for array of object in android

I want to create JSON model and API for array of JSON object.
my PHP code:
<?php
$response = array();
require_once __DIR__ . '/db_connect.php';
$db = new DB_CONNECT();
if (isset($_POST['type'])) {
$type = $_POST['type'];
$result = mysql_query("SELECT *FROM bidsproject WHERE type='$type'
ORDER BY createTime ") ;
if (mysql_num_rows($result)>0) {
$response["products"] = array();
while ($row = mysql_fetch_array($result)) {
$product = array();
$product["projectId"] = $row["projectId"];
$product["title"] = $row["title"];
$product["createTime"] = $row["createTime"];
array_push($response["products"], $product);
}
echo json_encode($response);
}
else {
}
}
else {
}
?>
and my JSON model:
public class browsprojectJm {
int success;
public int getSuccess() {
return success;
}
public void setSuccess(int success) {
this.success = success;
}
DataToken project;
public class DataToken{
int projectId;
String title;
String creaeteTime;
public int getId() {
return projectId;
}
public void setId(int id) {
this.projectId = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDate() {
return creaeteTime;
}
public void setDate(String date) {
this.creaeteTime=date;
}
}
}
and my API:
#FormUrlEncoded
#POST("project/searchBidProject.php")
Call<List<browsprojectJm>> browsproject(#Field("type") int
type_register);
output with postman:
{
"products": [
{
"projectId": "1",
"title": "خرید خانه",
"createTime": "2018-09-05"
},
{
"projectId": "3",
"title": "خرید خانه شخصی",
"createTime": "2018-09-05"
},
{
"projectId": "4",
"title": "خرید من",
"createTime": "2018-09-05"
}
]
}
but this not working and i don't know what's wrong. it fails without errors but I think this problem is from JSON model or api.I'm new in android developing and please explain for me clearly

Symfony 2 denormalization of nested objects with custom denormalizers

Here I'm building Symfony SDK for REST API. Most of data are JSON objects with nested other JSON objects. Like here
{
"id": "eng_pl",
"name": "Premier League",
"_links": {
"self": {
"href": "/tournaments/eng_pl"
},
"seasons": {
"href": "/tournaments/eng_pl/seasons/"
}
},
"coverage": {
"id": "eng",
"name": "England",
"_links": {
"self": {
"href": "/territories/eng"
}
}
}
}
Deserialization must produce an object equal to object produced by the code listed below:
$tournament = new Tournament();
$tournament->setId('eng_pl');
$tournament->setName('Premier League');
$coverage = new Territory();
$coverage->setId('eng');
$coverage->setName('England');
$tournament->setCoverage($coverage);
I'm using my own custom Denormalizers, below the fragment of code of denormalizer for Tournament objects:
class TournamentDenormalizer implements DenormalizerInterface
{
/**
* #inheritdoc
*/
public function supportsDenormalization($object, $type, $format = null)
{
if ($type != Tournament::class) {
return false;
}
return true;
}
/**
* #inheritdoc
* #return Tournament
*/
public function denormalize($object, $class, $format = null, array $context = array())
{
$tournament = new Tournament();
$tournament->setId($object->id);
$tournament->setName($object->name);
if (isset($object->coverage)) {
/** #var Territory $coverage */
$coverage = ???; //HOWTO how to implement Territory denormalization here???
$tournament->setCoverage(
$coverage
);
}
return $tournament;
}
}
The question is how should I access TerritoryDenormalizer inside TournamentDenormalizer? I see two options:
First one (I'm using now) is to add implements DenormalizerAwareInterface to signature of denormalizer class and rely on Symfony\Component\Serializer\Serializer class:
$serializer = new Symfony\Component\Serializer\Serializer(
[
new TournamentDenormalizer(),
new TerritoryDenormalizer()
], [
new Symfony\Component\Serializer\Encoder\JsonDecode()
]
);
$serializer->deserialize($json, Tournament::class, 'json');
So in TournamentDeserializer it will be like here:
if (isset($object->coverage)) {
/** #var Territory $coverage */
$coverage = $this->denormalizer->denormalize(
$object->coverage,
Territory::class,
$format,
$context
);
$tournament->setCoverage(
$coverage
);
}
}
The second approach
Is to inject necessary denormalizers explicitly
$tournamentDenormalizer = new TournamentDenormalizer();
$tournamentDenormalizer->setTerritoryDenormalizer(new TerritoryDenormalizer());
So in TournamentDeserializer it will be like here:
if (isset($object->coverage)) {
/** #var Territory $coverage */
$coverage = $this->territoryDenormalizer->denormalize(
$object->coverage,
Territory::class,
$format,
$context
);
$tournament->setCoverage(
$coverage
);
}
}
Which of approaches is the best? What alternative approaches are possible?
Making your normalizer implement NormalizerAwareInterface (and eventually use NormalizerAwareTrait) is the way to go, this interface has been introduced for this specific use case.

Denormalize nested structure in objects with Symfony 2 serializer

I'm working on a Symfony 2 project with version 2.8 and I'm using the build-in component Serializer -> http://symfony.com/doc/current/components/serializer.html
I have a JSON structure provided by a web service.
After deserialization, I want to denormalize my content in objects. Here is my structure (model/make in a car application context).
[{
"0": {
"id": 0,
"code": 1,
"model": "modelA",
"make": {
"id": 0,
"code": 1,
"name": "makeA"
}
}
} , {
"1": {
"id": 1,
"code": 2,
"model": "modelB",
"make": {
"id": 0,
"code": 1,
"name": "makeA"
}
}
}]
My idea is to populate a VehicleModel object which contains a reference to a VehicleMake object.
class VehicleModel {
public $id;
public $code;
public $model;
public $make; // VehicleMake
}
Here is what I do:
// Retrieve data in JSON
$data = ...
$serializer = new Serializer([new ObjectNormalizer(), new ArrayDenormalizer()], [new JsonEncoder()]);
$models = $serializer->deserialize($data, '\Namespace\VehicleModel[]', 'json');
In result, my object VehicleModel is correctly populated but $make is logically a key/value array. Here I want a VehicleMake instead.
Is there a way to do that?
The ObjectNormalizer needs more configuration. You will at least need to supply the fourth parameter of type PropertyTypeExtractorInterface.
Here's a (rather hacky) example:
<?php
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use Symfony\Component\PropertyInfo\Type;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
$a = new VehicleModel();
$a->id = 0;
$a->code = 1;
$a->model = 'modalA';
$a->make = new VehicleMake();
$a->make->id = 0;
$a->make->code = 1;
$a->make->name = 'makeA';
$b = new VehicleModel();
$b->id = 1;
$b->code = 2;
$b->model = 'modelB';
$b->make = new VehicleMake();
$b->make->id = 0;
$b->make->code = 1;
$b->make->name = 'makeA';
$data = [$a, $b];
$serializer = new Serializer(
[new ObjectNormalizer(null, null, null, new class implements PropertyTypeExtractorInterface {
/**
* {#inheritdoc}
*/
public function getTypes($class, $property, array $context = array())
{
if (!is_a($class, VehicleModel::class, true)) {
return null;
}
if ('make' !== $property) {
return null;
}
return [
new Type(Type::BUILTIN_TYPE_OBJECT, true, VehicleMake::class)
];
}
}), new ArrayDenormalizer()],
[new JsonEncoder()]
);
$json = $serializer->serialize($data, 'json');
print_r($json);
$models = $serializer->deserialize($json, VehicleModel::class . '[]', 'json');
print_r($models);
Note that in your example json, the first entry has an array as value for make. I took this to be a typo, if it's deliberate, please leave a comment.
To make this more automatic you might want to experiment with the PhpDocExtractor.
In cases when you need more flexibility in denormalization it's good to create your own denormalizers.
$serializer = new Serializer(
[
new ArrayNormalizer(),
new VehicleDenormalizer(),
new VehicleMakeDenormalizer()
], [
new JsonEncoder()
]
);
$models = $serializer->deserialize(
$data,
'\Namespace\VehicleModel[]',
'json'
);
Here the rough code of such denormalizer
class VehicleDenormalizer implements DenormalizerInterface, DenormalizerAwareInterface
{
public function denormalize($data, $class, $format, $context)
{
$vehicle = new VehicleModel();
...
$vehicleMake = $this->denormalizer->denormalize(
$data->make,
VehicleMake::class,
$format,
$context
);
$vehicle->setMake($vehicleMake);
...
}
}
I only have doubts on should we rely on $this->denormalizer->denormalize (which works properly just because we use Symfony\Component\Serializer\Serializer) or we must explicitly inject VehicleMakeDenormalizer into VehicleDenormalizer
$vehicleDenormalizer = new VehicleDenormalizer();
$vehicleDenormalizer->setVehicleMakeDenormalizer(new VehicleMakeDenormalizer());
The easiest way would be to use the ReflectionExtractor if your Vehicle class has some type hints.
class VehicleModel {
public $id;
public $code;
public $model;
/** #var VehicleMake */
public $make;
}
You can pass the Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor as argument to the ObjectNormalizer when you initialize the Serializer
$serializer = new Serializer([new ObjectNormalizer(null, null, null, new ReflectionExtractor()), new ArrayDenormalizer()], [new JsonEncoder()]);
$models = $serializer->deserialize($data, '\Namespace\VehicleModel[]', 'json');
In Symfony4+, you can inject the serializer and it will do the job for you based on either your phpdoc (eg #var) or type hinting. Phpdoc seems safer as it manages collections of objects.
Example:
App\Model\Skill.php
<?php
namespace App\Model;
class Skill
{
public $name = 'Taxi Driver';
/** #var Category */
public $category;
/** #var Person[] */
public $people = [];
}
App\Model\Category.php
<?php
namespace App\Model;
class Category
{
public $label = 'Transports';
}
App\Model\Person.php
<?php
namespace App\Model;
class Person
{
public $firstname;
}
App\Command\TestCommand.php
<?php
namespace App\Command;
use App\Model\Category;
use App\Model\Person;
use App\Model\Skill;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Serializer\SerializerInterface;
class TestCommand extends Command
{
/**
* #var SerializerInterface
*/
private $serializer;
public function __construct(SerializerInterface $serializer)
{
parent::__construct();
$this->serializer = $serializer;
}
protected function configure()
{
parent::configure();
$this
->setName('test')
->setDescription('Does stuff');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$personA = new Person();
$personA->firstname = 'bruno';
$personB = new Person();
$personB->firstname = 'alice';
$badge = new Skill();
$badge->name = 'foo';
$badge->category = new Category();
$badge->people = [$personA, $personB];
$output->writeln(
$serialized = $this->serializer->serialize($badge, 'json')
);
$test = $this->serializer->deserialize($serialized, Skill::class, 'json');
dump($test);
return 0;
}
}
Will give the following expected result:
{"name":"foo","category":{"label":"Transports"},"people":[{"firstname":"bruno"},{"firstname":"alice"}]}
^ App\Model\BadgeFacade^ {#2531
+name: "foo"
+category: App\Model\CategoryFacade^ {#2540
+label: "Transports"
}
+people: array:2 [
0 => App\Model\PersonFacade^ {#2644
+firstname: "bruno"
}
1 => App\Model\PersonFacade^ {#2623
+firstname: "alice"
}
]
}

How can I parse json data with sql query in PHP classes?

I have a php json creater. That is a web service and I use it in android. I have sql datas, classes and would like run querys in clasess.
This is my json parser without classes.
<?php
/$sql_query = blabla{
$dolaplar= array();
/* fetch object array */
while ($obj = $result->fetch_object()) {
// printf ("%d - %s - %s\n", $obj->id, $obj->tanim, $obj->tipi);
$dolaplar[]= $obj;
}
$kodlanmis= json_encode($dolaplar);
echo $kodlanmis;
/* free result set */
$result->close();
}
?>
And It's json data.
[
{
malzeme_id: "9",
malzeme_adi: "10 kohm direnc",
malzeme_miktari: "580"
},
{
malzeme_id: "8",
malzeme_adi: "Hdmi Kablosu",
malzeme_miktari: "128"
},
{
malzeme_id: "7",
malzeme_adi: "Kirmizi Led",
malzeme_miktari: "-653"
}
]
Here is classes.
<?php
class A {
public $Message = "Success";
public $MessageInfo = "";
public $Payload = array();
function __construct(){
for ( $i=3; $i-->0;){
array_push($this->Payload, new B);
}
}
}
class B {
public $a = 3;
public $b = 4;
}
echo json_encode(new A);
?>
And I would like to see like that json data.
{
Message: "Success",
MessageInfo: "",
Payload: [
{
malzeme_id: "9",
malzeme_adi: "10 kohm direnc",
malzeme_miktari: "580"
},
{
malzeme_id: "8",
malzeme_adi: "Hdmi Kablosu",
malzeme_miktari: "128"
},
{
malzeme_id: "7",
malzeme_adi: "Kirmizi Led",
malzeme_miktari: "-653"
}
]
}
I am not really good about php. Is it possible ?
You could add a parameter to your Class A and Class B constructors:
Class A:
class A {
public $Message = "Success";
public $MessageInfo = "";
public $Payload = array();
function __construct($data){
foreach ($data as $d) {
array_push($this->Payload, new B($d));
}
}
}
Class B:
class B {
public function __construct($data) {
array_walk($data, function($value, $key){
$this->$key = $value;
});
}
}
Then your call would look something like:
$data = $dolapla // ???
echo json_encode(new A($data));

Add Elements Dynamically With JSON

I would like to add buttons dynamically to my JSON string with PHP and JsonSerializable Interface.
To test, I have a database with a "apps" table who contain "id", "token" and "json" columns.
A View element contains Buttons elements, Buttons elements contain Toto element.
I have a class for each element and I serialize to JSON all class attributes.
I created a little form to add buttons, buttons are appended but not at the same level in JSON.
Here my code:
<?php
header('Content-Type: text/html; charset=utf-8');
require_once('init.php'); // Database connection
class View implements JsonSerializable
{
private $name;
private $id;
private $Button;
function __construct($name, $id, $buttons)
{
$this->name = $name;
$this->id = $id;
$this->Button = array($buttons);
}
public function setButton($buttons) { array_push($this->Button, $buttons); }
public function jsonSerialize() { return (get_object_vars($this)); }
}
class Toto implements JsonSerializable
{
private $name;
function __construct($name)
{
$this->name = $name;
}
public function jsonSerialize() { return (get_object_vars($this)); }
}
class Button implements JsonSerializable
{
private $name;
private $id;
private $Element;
function __construct($name, $id)
{
$this->name = $name;
$this->id = $id;
$this->Element = new Toto('Titi');
}
public function jsonSerialize() { return (get_object_vars($this)); }
}
?>
<form action="" method="post">
<?php
$q = $mysqli->query('
SELECT json
FROM apps
WHERE token = "abc"');
if ($q->num_rows >= 1)
{
$d = $q->fetch_object();
$result = $d->json;
var_dump(json_decode($result)->Button);
}
else
$result = null;
if (isset($_POST['add']))
{
if ($q->num_rows >= 1)
{
$view = new View('Home', 1, json_decode($result)->Button);
$view->setButton(new Button($_POST['name'], 12));
$newJSON = json_encode($view, (JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE));
$mysqli->query('
UPDATE apps
SET token = "abc",
json = "' . $mysqli->real_escape_string($newJSON) . '"
WHERE token = "abc"');
}
else
{
$view = new View('Home', 1, new Button($_POST['name'], 12));
$newJSON = json_encode($view, (JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE));
$mysqli->query('
INSERT INTO apps
SET token = "abc",
json = "' . $mysqli->real_escape_string($newJSON) . '"');
}
header('Location: archi.php');
exit;
}
?>
<pre><?php print_r($result); ?></pre>
<input type="text" name="name" placeholder="Name" />
<button type="submit" name="add">Add button</button>
</form>
Here my currently output with three buttons added:
{
"name": "Home",
"id": 1,
"Button": [
[
[
{
"name": "Send",
"id": 12,
"Element": {
"name": "Titi"
}
}
],
{
"name": "Cancel",
"id": 12,
"Element": {
"name": "Titi"
}
}
],
{
"name": "Invite",
"id": 12,
"Element": {
"name": "Titi"
}
}
]
}
I would like this result:
{
"name": "Home",
"id": 1,
"Button": [
{
"name": "Send",
"id": 12,
"Element": {
"name": "Titi"
}
},
{
"name": "Cancel",
"id": 12,
"Element": {
"name": "Titi"
}
},
{
"name": "Invite",
"id": 12,
"Element": {
"name": "Titi"
}
}
]
}
How can I arrived to this result ? I'm stuck.
Mickey42.

Categories