Consider following example:
<?php
class p{
public $name = 'jimmy';
public $sex = 'male';
private $age = 31;
// there should be more unknow properties here ..
function test(){
echo $this->name;
}
function get_p_as_json(){
// how can i get json of this class which contains only public properties ?
// {"name":"jimmy","sex":"male"}
}
}
$p = new p();
$json = $p->get_p_as_json();
echo $json;
Question: How to get all public properties of a class as JSON?
You just create another class q extends from p. And then the code looks like following:
class p {
public $name = 'jimmy';
public $sex = 'male';
private $age = 31;
// there should be more unknown properties here ..
function test(){
echo $this->name;
}
}
class q extends p {
function get_p_as_json($p) {
return json_encode(get_object_vars($p));
}
}
$q = new q();
$p = new p();
$json = $q->get_p_as_json($p);
echo $json;
$a = array();
$reflect = new ReflectionClass($this /* $foo */);
$props = $reflect->getProperties(ReflectionProperty::IS_PUBLIC);
foreach ($props as $prop) {
/* here you can filter for spec properties or you can do some recursion */
$a[ $prop->getName() ] = $a[ $prop->getValue()];
}
return json_encode($a);
Since the public members can also be accessed outside of the class..
Accessing members outside of the class
$p = new p();
foreach($p as $key => $value) {
$arr[$key]=$value;
}
Demo
Accessing the public members within the class by making use of ReflectionClass
<?php
class p{
public $name = 'jimmy';
public $sex = 'male';
private $age = 31;
// there should be more unknow properties here ..
function test(){
echo $this->name;
}
function get_p_as_json(){
static $arr;
$reflect = new ReflectionClass(p);
$props = $reflect->getProperties(ReflectionProperty::IS_PUBLIC);
foreach ($props as $prop) {
$arr[$prop->getName()]=$prop->getValue($this); //<--- Pass $this here
}
return json_encode($arr);
}
}
$p = new p();
echo $json=$p->get_p_as_json();
Demo
The best way to do this would not be to call a method of the class, per se.
However, you could initiate the following:
$myPublicMethodsInJson = json_encode(get_class_methods($p));
However, you would not be able to call get_class_methods from within the class because it will return ALL of your methods, private and public. When you call it from outside of the class it will only return the public methods.
Related
This is my example code :
class Dad {
protected $name = 'Alex';
public function setName($string)
{
$this->name = $string;
}
}
class Son extends Dad{
public function showName()
{
return $this->name;
}
}
and i use that classes like this:
$dad = new Dad();
$dad->setName('John');
$son = new Son();
echo $son->showName();//it echo Alex but i need to echo John
I use many protected variable in parent and child class and this is just example.
How i can use new value from protected variables in child class ?
You have 2 objects. The default name in the object is 'Alex'. Therefore, when you create a new object and don't explicitly give it a name, it will use 'Alex' because that is the default.
$p = new Dad;
// name is Alex.
$q = new Son;
// name is Alex
$p->setName('John'); // Now the name of $p is John
$q->setName('Beto'); // Now the name of $q is Beto. $p remains unchanged.
This is the point of objects, that they are separate.
If you wanted a way to change the default name, then you could do this.
class Dad
{
protected $name;
static protected $defaultName = 'Alex';
public function __construct()
{
$this->name = self::$defaultName;
}
public function showName()
{
return $this->name;
}
public static function setDefault($name)
{
self::$defaultName = $name;
}
}
Now:
$p = new Dad; // $p->name is 'Alex'
Dad::setDefault('Bernie');
$q = new Dad; // $q->name is 'Bernie', $p is not changed
$r = new Dad; // $r->name is 'Bernie'
Dad::setDefault('Walt');
$t = new Dad; // $t->name is Walt
Hope this helps.
Why I am able to use properties in constructor function without being defined in the class, Please read my code below.
<?php
class TV
{
public function __construct($m, $v)
{
$this->model = $m;
$this->volume = $v;
}
}
$tv_one = new TV("Samsung", 6);
echo $tv_one->model."<br><br>";
echo $tv_one->volume;
?>
Have a look at this code also. I am able to share private property outside the class. Just go throuh this code-
<?php
class TV
{
private $model = "Samsung";
private $volume = 2;
public function volumeUp()
{
return $this->volume++;
}
public function volumeDown()
{
return $this->volume--;
}
public function __construct($m, $v)
{
$this->model = $m;
$this->volume = $v;
}
}
class PlasmaTv extends TV
{
public $plasma = true;
public function hello()
{
return "I am new " . $this->model . " and my default volume is " . $this->volume . ".";
}
public function __construct($m, $v, $p)
{
$this->model = $m;
$this->volume = $v;
$this->plasma = $p;
}
}
$plasma = new PlasmaTv("Soni", 6, true);
echo $plasma->model."<br><br>";
echo $plasma->volume."<br><br>";
echo $plasma->plasma;
echo $plasma->hello();
?>
PHP doesn't require you to declare properties. Just assigning to a property will create it as a public property. So when the first constructor does:
$this->model = $m;
that creates a model property in the object.
In your PlasmaTv class, the model and volume properties are not the same as the ones in the parent class TV, because the properties in the parent are private and can't be accessed in the child. If you do:
$plasma->volumeUp();
echo $plasma->volume;
it will print 6, not 7, because volumeUp() incremented a different property than the public property in PlasmaTv.
If you want to share the properties between the child and parent, declare them protected. But then you won't be able to use $plasma->volume from outside the classes.
I have the following piece of code.
class SomeClass
{
public static $one = 1;
private static $two = 2;
public $three = 3;
private $four = 4;
}
header("Content-Type: application/json");
echo json_encode(new SomeClass());
What I want to achieve is encode the public class property and member as a JSON object. My problem is that json_encode() ignores public static $one = 1; and the result will be:
{
"three": 3
}
Although I expect it to print the public static member as well, such as:
{
"one": 1,
"three": 3
}
Can JSON encoding be done with static members in PHP?
According to PHP manual:
Static properties cannot be accessed through the object using the arrow operator ->.
That means no
Nevertheless, I came up with the solution utilizing Reflections:
class SomeClass
{
public static $one = 1;
private static $two = 2;
public $three = 3;
private $four = 4;
}
$reflection = new ReflectionClass('SomeClass');
$instance = $reflection->newInstance();
$properties = $reflection->getProperties(ReflectionProperty::IS_PUBLIC);
$jsonArray = array();
foreach($properties as $property) {
$jsonArray[$property->getName()] = $property->getValue($instance);
}
echo json_encode($jsonArray);
The result is
{"one":1,"three":3}
In native implementation: NO.
In case you use Php v >= 5.4.0, you can use JsonSerializable
Here is example:
class myClass implements JsonSerializable
{
private $_name = 'test_name';
public $email = 'test#mail.com';
public static $staticVar = 5;
public function jsonSerialize()
{
return get_class_vars(get_class($this));
}
}
echo json_encode(new myClass());
I have three php classes. I can instantiate them this way:
$piza = new Mashrooms(new SeaFood(new PlainPiza()));
However when I try to instantiate them dynamically in this way:
$temp = Mashrooms(new SeaFood(new PlainPiza()));
$piza = new $temp;
it fails and shows this error:
Fatal error: Class 'SeaFood(new Mashrooms' not found.
Your help will be appreciated.
$temp is an Object, not a Class, and you cannot use the new keyword on an existing Object.
$plain = 'PlainPiza';
$seafood = 'SeaFood';
$mashrooms = 'Mashrooms';
$piza = new $mashrooms(new $seafood(new $plain)));
Given the new information
The problem is I don't know how many classes I will instantiate
I think your approach my be wrong. Have you thought about having a Pizza class and adding your topping objects to the pizza object? For instance:
<?php
class Pizza
{
private $_toppings;
private $_placements = array('left', 'right', 'whole');
public function _construct()
{
foreach($this->_placements as $placement)
{
$this->_toppings[$placement] = array();
}
}
public function add_topping(Base_Topping $topping, $placement)
{
if(in_array($placement, $this->_placements))
{
array_push($this->_toppings[$placement], $topping);
}
}
}
abstract class Base_Topping
{
protected $_price = 0.00;
protected $_name = 'No Name';
public function get_name()
{
return $this->_name;
}
public function get_price()
{
return $this->_price;
}
}
class Mushrooms extends Base_Topping
{
protected $_price = '1.00';
protected $_name = 'Mushrooms';
}
// assuming $_POST['toppings'] = array('Mushrooms' => 'whole', 'Pepperoni' => 0, 'Sausage' => 0, etc...)
$pizza = new Pizza();
$toppings = array_filter($_POST); // will return anything with a non-false value
foreach($toppings as $name => $coverage)
{
$topping = new $name();
$pizza->add_topping($topping, $coverage);
}
?>
This will work:
$temp = "Mashrooms";
$pizza = new $temp(new SeaFood(new PlainPiza()));
See here: http://3v4l.org/RXDLX
Can we dynamically create and initialize an object in PHP?
This is the normal code:
class MyClass{
var $var1 = null;
var $var2 = null;
.
.
public function __construct($args){
foreach($args as $key => $value)
$this->$key = $value;
}
}
---------------------
$args = ($_SERVER['REQUEST_METHOD'] == "POST") ? $_POST : $_REQUEST;
$obj = new MyClass($args);
The above code works fine. Please note that the names of REQUEST parameters are accurately mapped with the members of class MyClass.
But can we do something like this:
$class = "MyClass";
$obj = new $class;
If we can do like this, then can we initialize $obj by using $args.
According to this post, $obj = $class should work. But it does not work for me. I tried get_class_vars($obj). It threw an exception.
Thanks
It's more a comment, but I leave it here more prominently:
$class = "MyClass";
$obj = new $class($args);
This does work. See newDocs.
You have to overload some other magic methods:
__get (a method that gets called when you call object member)
__set (a method that gets called when you want to set object member)
__isset
__unset
Please see this codepad to see your code rewritten to work with what you want:
<?php
class MyClass{
var $properties = array();
public function __construct($args){
$this->properties = $args;
}
public function __get($name) {
echo "Getting '$name'\n";
if (array_key_exists($name, $this->properties)) {
return $this->properties[$name];
}
return null;
}
}
$args = array("key1" => "value1", "key2" => "value2");
$class = "MyClass";
$obj = new $class($args);
echo "key1:". $obj->key1;
?>
You can use Reflection to instanciate an object with parameters.
<?php
class Foo {
protected $_foo;
protected $_bar;
public function __construct($foo, $bar)
{
$this->_foo = $foo;
$this->_bar = $bar;
}
public function run()
{
echo $this->_foo . ' ' . $this->_bar . PHP_EOL;
}
}
$objectClass = 'Foo';
$args = array('Hello', 'World');
$objectReflection = new ReflectionClass($objectClass);
$object = $objectReflection->newInstanceArgs($args);
$object->run();
See Reflection on php manual.