return class properties as JSON - php

I'm trying to encode some properties in a class in php to JSON but all my method is returning is {}
Here's my code, where am I going wrong?
Thanks.
<?php
class Person
{
private $_photo;
private $_name;
private $_email;
public function __construct($photo, $name, $email)
{
$this->_photo = $photo;
$this->_name = $name;
$this->_email = $email;
}
public function getJsonData() {
$json = new stdClass;
foreach (get_object_vars($this) as $name => $value) {
$this->$name = $value;
}
return json_encode($json);
}
}
$person1 = new Person("mypicture.jpg", "john doe", "doeman#gmail.com");
print_r( $person1->getJsonData() );

That's is because you are not using the $json variable but instead you are using $this->$name. Which $this are you refering too? You aren't using the $json variable from what I am seeing.
class Person
{
private $_photo;
private $_name;
private $_email;
public function __construct($photo, $name, $email)
{
$this->_photo = $photo;
$this->_name = $name;
$this->_email = $email;
}
public function getJsonData() {
//I'd make this an array
//$json = new stdClass;
$json = array();
foreach (get_object_vars($this) as $name => $value) {
//Here is my change
//$this->$name = $value;
$json[$name] = $value
}
return json_encode($json);
}
}
$person1 = new Person("mypicture.jpg", "john doe", "doeman#gmail.com");
print_r( $person1->getJsonData() );
Hope it solves you problem. That's how I would do it.

Implement the JsonSerializable interface in your class, starting with PHP 5.4.

Related

Can't add data from php array to json database

I have got problem with array. When i add string to json_encode it save in db but $object give me [{},{},{}]Can you tell me guys what i am doing wrong?
$objects = array();
$objects[] = new Person(1, 'John', 'Smith','java');
$objects[] = new Person(2, 'Stacy', 'Smith','php');
$Db ='./DB.json';
$saveInBase = json_encode($objects);
file_put_contents($Db, $saveInBase);
$loadFromBase = file_get_contents($Db);
$loadFromBase = json_decode($loadFromBase, true);
Please implement JsonSerializable on Person class, you only will have to implement jsonSerialize method, here you have an example:
<?php
class Person implements JsonSerializable
{
private $id;
private $name;
private $last_name;
private $lang;
public function __construct($id, $name, $last_name, $lang)
{
$this->id = $id;
$this->name = $name;
$this->last_name = $last_name;
$this->lang = $lang;
}
public function jsonSerialize()
{
return get_object_vars($this);
}
}
$objects = array();
$objects[] = new Person(1, 'John', 'Smith','java');
$objects[] = new Person(2, 'Stacy', 'Smith','php');
$Db ='./DB.json';
$saveInBase = json_encode($objects);
file_put_contents($Db, $saveInBase);
$loadFromBase = file_get_contents($Db);
$loadFromBase = json_decode($loadFromBase, true);

json string to php object via reflection/ like jackson mapper

Im a fan of the jackson mapper in Java, and I'm a bit lost without it in php. I would like an equivalent.
So far the closest I have come across is this, however, it requires the fields to be declared as public, and I dont want to do that:
https://github.com/netresearch/jsonmapper
I want something that does everything that that does, with this sort of code:
<?php
class Contact
{
/**
* Full name
* #var string
*/
public $name; //<- I want this to be private
/**
* #var Address //<- and this
*/
public $address;
}
class Address
{
public $street;<- and this
public $city;<- and this
public function getGeoCoords()
{
//do something with the $street and $city
}
}
$json = json_decode(file_get_contents('http://example.org/bigbang.json'));
$mapper = new JsonMapper();
$contact = $mapper->map($json, new Contact());
Json from file_get_contents:
{
'name':'Sheldon Cooper',
'address': {
'street': '2311 N. Los Robles Avenue',
'city': 'Pasadena'
}
}
So I dont want to be writing individual constructors, or anything individual at all.
Im sure there would be something that does this out of the box using reflection?
You can provide a setter method for protected and private variables:
public function setName($name)
{
$this->name = $name;
}
JsonMapper will automatically use it.
Since version 1.1.0 JsonMapper supports mapping private and protected properties.
This can be achieved very easily and nicely using Closures.
There is even no need to create setter functions.
<?php
class A {
private $b;
public $c;
function d() {
}
}
$data = [
'b' => 'b-value',
'c' => 'c-value',
'd' => 'function',
];
class JsonMapper {
public function map( $data, $context ) {
$json_mapper = function() use ( $data ) {
foreach ($data as $key => $value) {
if ( property_exists( $this, $key ) ) {
$this->{$key} = $value;
}
}
};
$json_mapper = $json_mapper->bindTo( $context, $context );
$json_mapper();
return $context;
}
}
$mapper = new JsonMapper();
$a = $mapper->map( $data, new A );
print_r($a);
Sorry, I don't have enough 'reputation' so can't add a comment.
I've only been using Java for a few month, but my understanding is that your classes in Java will all have getters and settings, which is how Jackson is able to set the value of a private property.
To do the same in PHP, I suspect you would need to make your properties private, and create getter and setter methods...
public function setName($name) {
$this->name = name;
}
Then within your Mapper, use reflection to call the setter.
The way I would do this would be to look at the keys you have in the JSON, and try to put together a method name.
For example, if there's a key in the JSON labelled 'name'...
$className = "Contact";
$object = json_decode($jsonResponse);
$classObject = new $className();
foreach ($object as $key => $value) {
$methodName = "set" . ucfirst($key);
if (method_exists($classObject, $methodName)) {
$classObject->$methodName($value);
}
}
The above may not be exactly right, but I hope it gives you an idea.
To expand on the above, I've put together the following example which seems to do what you require?
class Contact {
private $name;
private $telephone;
public function setName($name) {
$this->name = $name;
}
public function setTelephone($telephone) {
$this->telephone = $telephone;
}
public function getName() {
return $this->name;
}
public function getTelephone() {
return $this->telephone;
}
}
class Mapper {
private $jsonObject;
public function map($jsonString, $object) {
$this->jsonObject = json_decode($jsonString);
if (count($this->jsonObject) > 0) {
foreach ($this->jsonObject as $key => $value) {
$methodName = "set" . ucfirst($key);
if (method_exists($object, $methodName)) {
$object->$methodName($value);
}
}
}
return $object;
}
}
$myContact = new stdClass();
$myContact->name = "John Doe";
$myContact->telephone = "0123 123 1234";
$jsonString = json_encode($myContact);
$mapper = new Mapper();
$contact = $mapper->map($jsonString, new Contact());
echo "Name: " . $contact->getName() . "<br>";
echo "Telephone: " . $contact->getTelephone();

how to get Factory Class to create object instances in PHP?

I have an XML file with many member entries, formatted like so:
<staff>
<member>
<name></name>
<image></image>
<title></title>
<email></email>
<phone></phone>
<location></location>
<info></info>
<webTitle></webTitle>
<webURL></webURL>
</member>
</staff>
setup
I've created 2 PHP classes, DisplayStaff and Employee.
Employee creates an Employee object, with private properties outlined in the XML above.
DisplayStaff is a factory class. It loads the above XML file, iterates through it, creating an Employee instance for each <member> element in the XML. It stores the Employee object in an array, $Employees[].
On the page where I want to output the Employee information, I'd like to be able to reference it like so.
$Employees = new DisplayStaff();
$John = Employees['John'];
echo "Hello, my name is $John->name";
code
<?php
class DisplayStaff
{
private var $staffList;
private var $placeholderImg;
private var $Employees;
public function __construct() {
$staffList = simplexml_load_file("../data/staff.xml");
$placeholderImg = $staffList->placeholderImg;
foreach ( $staffList->member as $member ) {
$employee = formatEmployeeObj( $member );
array_push( $Employees, $employee );
}
return $Employees;
}
private function formatEmployeeObj( $memberXML ) {
$Employee = new Employee();
$Employee->set( $name, $memberXML->name );
$Employee->set( $image, $memberXML->image );
$Employee->set( $title, $memberXML->title );
$Employee->set( $email, $memberXML->email );
$Employee->set( $phone, $memberXML->phone );
$Employee->set( $location, $memberXML->location );
$Employee->set( $info, $memberXML->info );
$Employee->set( $webTitle, $memberXML->webTitle );
$Employee->set( $webURL, $memberXML->webURL );
return $Employee;
}
}
?>
<?php
class Employee
{
private var $name = "";
private var $image = "";
private var $title = "";
private var $email = "";
private var $phone = "";
private var $location = "";
private var $info = "";
private var $webTitle = "";
private var $webURL = "";
public function get($propertyName) {
if( property_exists($this, $propertyName) ) {
return $this->$propertyName;
}
else{
return null;
}
}
public function set($propertyName, $propertyValue) {
if( property_exists($this, $propertyName) ){
$this->$propertyName = $propertyValue;
}
}
}
?>
problem
I can't seem to get this working. I'm new to working with classes. What do I need to change to have my classes behave how I desire them to?
Thank you in advanced for any help.
Remove var from each of your class fields. That is redundant with public and also deprecated as of PHP5. More on this
The constructor should not return anything. It will automatically return the object in question. Note, however, that there is no way of accessing any of the DisplayStaff fields since they are all private with no accessor functions. You could use the universal accessors like you do in Employee, but is there a reason for not simply using public fields?
Any time you are referring to an method or property of an object within the class declaration, you need to use the $this keyword, i.e.
public function __construct() {
$this->staffList = simplexml_load_file("staff.xml");
$this->placeholderImg = $this->staffList->placeholderImg
foreach ( $this->staffList->member as $member ) {
$employee = $this->formatEmployeeObj( $member );
array_push( $this->Employees, $employee );
}
//no need for a return
}
Your Employee property accessor method (Employee->get()) takes a string as the first parameter, i.e. 'name'. $name is an undefined variable so it won't work.
You need to initialize your Employees array before you can push to it.
private $Employees = array();
Note that I left out many of the Employee properties and methods for the sake of brevity.
class StaffFactory
{
public $employees = array();
public function __construct($xml)
{
$xml = simplexml_load_file($xml);
foreach ( $xml->member as $member ) {
$this->employees[(string) $member->name] = new Employee((array) $member);
}
}
public function getEmployee($name)
{
if ( isset($this->employees[$name]) ) {
return $this->employees[$name];
}
return false;
}
}
class Employee {
public $email;
public $name;
public $title;
public function __construct(array $employee)
{
foreach ( $employee as $k => $v ) {
if ( property_exists($this, $k) ) {
$this->{$k} = $v;
}
}
return $this;
}
}
$staffFactory = new StaffFactory('staff.xml');
$john = $staffFactory->getEmployee('John');
if ( $john ) {
echo '<pre>';
print_r($staffFactory);
print_r($john);
print_r($john->email);
echo '</pre>';
}

PHP: How to use dynamic variable name with a class' setter

I have a class with a private member "description" but that proposes a setter :
class Foo {
private $description;
public function setDescription($description) {
$this->description = $description;
}
}
I have the name of the member in a variable. I would like to access the field dynamically. If the field was simply public I could do :
$bar = "description";
$f = new Foo();
$f->$bar = "asdf";
but I don't know how to do in the case I have only a setter.
<?php
$bar = "description";
$f = new Foo();
$func="set"+ucwords($bar);
$f->$func("asdf");
?>
Try this:
$bar = 'description';
$f = new Foo();
$f->{'set'.ucwords($bar)}('test');
This function come do the job:
private function bindEntityValues(Product $entity, array $data) {
foreach ($data as $key => $value){
$funcName = 'set'+ucwords($key);
if(method_exists($entity, $funcName)) $entity->$funcName($value);
}
}
Use magic setter
class Foo {
private $description;
function __set($name,$value)
{
$this->$name = $value;
}
/*public function setDescription($description) {
$this->description = $description;
}*/
}
but by this way your all private properties will act as public ones if you want it for just description use this
class Foo {
private $description;
function __set($name,$value)
{
if($name == 'description')
{ $this->$name = $value;
return true;
}
else
return false
}
/*public function setDescription($description) {
$this->description = $description;
}*/
}

How do I tell if a variable is public or private from within a PHP class?

I'm sure I could find this on PHP.net if only I knew what to search for!
Basically I'm trying to loop through all public variables from within a class.
To simplify things:
<?PHP
class Person
{
public $name = 'Fred';
public $email = 'fred#example.com';
private $password = 'sexylady';
public function __construct()
{
foreach ($this as $key=>$val)
{
echo "$key is $val \n";
}
}
}
$fred = new Person;
Should just display Fred's name and email....
Use Reflection. I've modified an example from the PHP manual to get what you want:
class Person
{
public $name = 'Fred';
public $email = 'fred#example.com';
private $password = 'sexylady';
public function __construct()
{
$reflect = new ReflectionObject($this);
foreach ($reflect->getProperties(ReflectionProperty::IS_PUBLIC) as $prop)
{
$propName = $prop->getName();
echo $this->$propName . "\n";
}
}
}
http://php.net/manual/en/function.get-class-vars.php
You can use get_class_vars() function:
<?php
class Person
{
public $name = 'Fred';
public $email = 'fred#example.com';
private $password = 'sexylady';
public function __construct()
{
$params = get_class_vars(__CLASS__);
foreach ($params AS $key=>$val)
{
echo "$key is $val \n";
}
}
}
?>

Categories