Not able to access private protect member in iterator php - php

Here is the data Iterator implementation
//Data Iterator
class DataIterator implements Iterator
{
public $data ;
public function __construct(Data $obj)
{
$this->data = $obj;
}
public function rewind()
{
$this->properties = get_object_vars($this->data);
}
public function valid()
{
if (key($this->properties) === null )
{
return false;
}
return true;
}
public function key()
{
return key($this->properties);
}
public function current()
{
return current($this->properties);
}
public function next()
{
next($this->properties);
}
}
and here is data class
/*Data Class*/
class Data implements IteratorAggregate
{
public $name;
private $age;
protected $address;
public $country;
public $state;
public function __construct($name, $age, $address, $country = 'USA', $state = 'NH')
{
$this->name = $name;
$this->age = $age;
$this->address = $address;
$this->country = $country;
$this->state = $state;
}
function getIterator()
{
return new DataIterator($this);
}
}
And here is the calling part
$data = new Data('Joker', '27', 'California');
foreach($data->getIterator() as $key => $value)
{
echo $key , ' ', $value, '<br>';
}
output
name Joker
country USA
state NH
Notice that the output does not contain my private and protected properties (age, address) output.
How do I tell Iterator to output those as well?

You cannot tell the iterator to output those properties because they are simply not accessible from the outside (i.e. the point where the iterator does get_object_vars($this->data).
There are two ways you could go about doing this:
By having the data object pass the values to the iterator.
Use the reflection API to pull them out by force (verbose, slow!).
But before going ahead with #1 as the preferred option, stop for a moment and ask yourself: why does the iterator expose non-public members of the data object?
Making something private means "You people don't really need to know about this; it may go away in the future, or it may change beyond recognition". If it's something that the outside world cares about, then why is it not public (either directly, or exposed through a public getter)? A rethink of what this iterator's purpose is might be in order.
That said, here's how you would do #1:
class DataIterator implements Iterator
{
public $data;
private $properties;
public function __construct(Data $obj, array $propeties)
{
$this->data = $obj;
$this->properties = $properties;
}
public function rewind()
{
// Arguably horrible trick to refresh the property map without
// demanding that Data exposes a separate API just for this purpose
$newIterator = $this->data->getIterator();
$this->properties = $newIterator->properties;
}
}
class Data implements IteratorAggregate
{
function getIterator()
{
return new DataIterator($this, get_object_vars($this));
}
}

Public, private and protected are access modifiers. They are designed to restrict the accessibility of your class attributes.
Public means that any one can access that attribute, so if someone wants, they can change the value, without that you know it.
Private mean that the attribute is only accessible INSIDE the class,
so nobody can "mess" with those properties from OUTSIDE the class.
Protected is similar like Private, but child classes (classes that
inherit from that class) have access to it.
You are making age and address private, so you are basically saying, nobody is allowed to access these attributes. If you want to access private/protected attributes, you will have to make getters and setters and call these functions, or make the attributes public.

try get_class_vars
$this->properties = get_class_vars(get_class($this->data));
instead of
$this->properties = get_object_vars($this->data);

Related

Use of __construct or setVar() [duplicate]

I have been searching for this online, but I can't seem to find something that is clear enough for me to understand. I have seen "similiar" questions on here about this in Java.
class animal{
private $name;
// traditional setters and getters
public function setName($name){
$this->name = $name;
}
public function getName(){
return $this->name;
}
// animal constructors
function __construct(){
// some code here
}
// vs
function __construct($name){
$this->name = $name;
echo $this->name;
}
}
$dog = new animal();
$dog->setName("spot");
echo $dog->getName();
// vs
$dog = new animal("spot");
Should I declare and access my private fields through setters and getters or through the constructor?
Which one is the best practice?
I understand the purpose of a constructor(maybe not), but what is the point of having a constructor if I can declare and access my private fields through setters and getters?
Please note...this is my first time using OOP with web development and PHP, and I'm trying to learn by getting my hands "dirty" by writing some code in order for me to understand certain things in OOP. Please keep it simple.
It is more a matter of semantics than best practice per say.
In your example, your buisness logic may determine that an animal always needs a name.
So it makes sense to construct the object with a name. If you do not want to allow
an animal's name to be changed, then you don't write a setter.
i.e.
class Animal
{
private $name;
public function __construct($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
}
You may have other properties that an animal doesn't have to have, like an owner
that you only write a getter/setter for i.e.
class Animal
{
private $name;
private $owner;
public function __construct($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
public function setOwner($owner)
{
$this->owner = $owner
}
}
But if you find that you are always creating an animal with an owner at the same time
you may want to put that in the contructor signature for convenience
class Animal
{
private $name;
private $owner;
public function __construct($name, $owner = null)
{
$this->name = $name;
$this->owner = $owner;
}
public function getName()
{
return $this->name;
}
public function setOwner(Owner $owner)
{
$this->owner = $owner
}
public function getOwner()
{
return $this->owner;
}
}
If the owner is another class in your application, you can type hint that your constructor
needs an owner of a specific type (class). All of this is used to make it easier for you, or another developer to understand some of the requirements/logic behind your code - as well as potentially catching a bug here or there
class Owner
{
private $name;
public function __construct($name)
{
$this->name = $name;
}
}
class Animal
{
private $name;
private $owner;
public function __construct($name, Owner $owner = null)
{
$this->name = $name;
$this->owner = $owner;
}
public function getName()
{
return $this->name;
}
public function setOwner(Owner $owner)
{
$this->owner = $owner
}
public function getOwner()
{
return $this->owner;
}
}
// Create a new owner!
$dave = new Owner('Farmer Dave');
// a standard php empty object
$otherObj = new \stdClass();
// Create a new animal
$daisy = new Animal('Daisy');
// Farmer dave owns Daisy
$daisy->setOwner($dave);
// Throws an error, because this isn't an instance of Owner
$daisy->setOwner($otherObj);
// Set up Maude, with Dave as the owner, a bit less code than before!
$maude = new Animal('Maude', $dave);
Should I declare and access my private fields through setters and getters or through the constructor?
In situations like this, I ask myself:
Why should I create a method just to hold a one line function? (+Constructor)
How painful is it going to be to refactor two, three, four, five or more getters/setters vs one constructor?(+Constructor)
How hard is it going to be to document two, three, four, five or more getters/setters vs one constructor?(+Constructor)
Is there going to be a default value which will be documented? (+Constructor)
Do I like documentation and expect people to read? (+Constructor)
Will the initial value be undefined?(+Setter)
Is there a set of equivalent forms (shorthand, international, nicknames) which will all be acceptable as syntatically correct for required arguments? (+Setter)
Is there a set of optional arguments with default values? (+Setter)
Is there a common need to stringify and parse the initial value? (+Setter)
Do I dislike documentation and expect people to experiment? (+Setter)
Which one is the best practice?
The Date object seems to be the most complex class in most languages, so its PHP implementation would be a good reference for best practices.
What is the point of having a constructor if I can declare and access my private fields through setters and getters?
A constructor is implicitly invoked upon object instantiation in order to encapsulate the default state of the resulting data structure of its type.
References
DateTime::__construct
date_create
The DateTime class
date_default_timezone_get
date_default_timezone_set
Changes in PHP datetime support
PHP OOP: Accessor and Destructor Methods
Concurrency, part 4: Comparing promises frameworks in different languages – SLaks.Blog
CDD: Context-Driven Development
Depends. Usually one say: If it's a required dependency, use the constructor, if it's optional, use getter/setter.
There is no preference for, or against one of them.
The constructor contains code, that is executed right after the object is created and it should leave the object in a stable and useable state. Thats the idea behind the constructor and it doesn't work in any case, but it should give you an idea, what should go into it.
Note, that you can even implement both constructor arguments and setters for the same property, for example if you want to allow to replace property later.
$bingo = new Dog;
echo $bingo->getName(); // DogHasNoNameException <-- maybe better as constructor argument?
$bingo = new Dog('Bingo');
echo $bingo->getName(); // "Bingo"
$spike = new Dog; // Missing argument
$bingo->setName('Spike'); // Or maybe "rename()" ;)
echo bingo->getName(); // "Spike"
Should I declare and access my private fields through setters and
getters or through the constructor? Which one is the best practice?
Both. It depends on your needs. If need a value in certain fields you add a param to the
__construct()-Method to do so. Or you can also add an optional Param to __construct to give the user the option to set the attribute
I understand the purpose of a constructor(maybe not), but what is the
point of having a constructor if I can declare and access my private
fields through setters and getters?
The contructor should initialize your attributes which need to be initialized.
In my opinion, it is more correct to write setter's & getter's, since then, the number of properties will only grow. And the __construct can then take an array of properties of the names of the keys (property => value), and set them to properties.
1 > That's your chose : if dependency is required, good practise use the constructor, else, use getter.
2 > for the best practise is the first,
Actually, you have a name, for your animal, but if you add a type and sex? and you want to call type, sexe or name separatly, first method is more better than the second.
class animal{
private $name, $type, $sex;
// traditional setters and getters
public function setName($name){
$this->name = $name;
}
public function setSex($sex){
$this->sex = $sex;
}
public function setType($type){
$this->type = $type;
}
public function getName(){
return $this->name;
}
public function getSex(){
return $this->sex;
}
public function getType(){
return $this->type;
}
// animal constructors
function __construct(){
// some code here
}
}
$dog = new animal();
$dog->setName("spot");
$dog->setSexe("male");
$dog->setType("dog");
echo $dog->getName().' is a '.$dog->getType().'('.dog->getSex().')';
3 > that depends first question... BUt Globaly we are always one dependency required, for sample:
class animal{
private $name, $type, $sex;
// traditional setters and getters
public function setName($name){
$this->name = $name;
}
public function setSex($sex){
$this->sex = $sex;
}
private function setType($type){
// if type is string ( cat, dog, lion ) and you want
// to linked string in an id in your database (1, 2, 3...).
// you want to call your database connection ( declared in you constructor)
// and search type id here.
$this->type = $type;
}
public function getName(){
return $this->name;
}
public function getSex(){
return $this->sex;
}
public function getType(){
return $this->type;
}
// animal constructors
public function __construct($type){
// for sample you want to open your database here
this->setType($type);
}
public function __destruct(){
// and you want to close your connection here.
}
}

Detect changes to Array in PHP

I've been using __set magic method with protected properties to monitor changes so that my classes know if they have something to save. Is there any way to monitor an array type property for changes? I understand that normally you access the array via a reference and functions like array_push won't trigger the __set method, they'll use a reference to the array.
What I want is basically this:
class Skill{ public $Player, $Name, $Level;}
class Player {
protected $Name, /*Other properties*/, $Skills /*Array*/
}
I then do tracking on all of the properties in Player to tell me if the persistence needs updated. (Skill would also have this function, but this shows the basic example). Also, I want to force them to remain synchronized (it's a bidirectional relationship).
Is there any way to do this that allows it to behave like an array (don't want to go through making a class just to synchronize those if I don't have to).
You could extend ArrayObject and proxy append:
class Skills extends ArrayObject
{
public function append($value)
{
// track changes
parent::append($value);
}
}
You could look into something like runkit_function_redifine(), but is it really too cumbersome to make helper methods for what you want? e.g.
class Player
{
private $skills = array();
protected function addSkill($skill)
{
// Do something.
//
$this->skills[] = $skill;
}
}
Or even a wrapper for an array to make it cleaner:
class FancyArray
{
private $content = array();
public function add($value)
{
// Do something.
//
$this->content[] = $value;
}
public function remove($value){ /* blah */ }
public function getContent(){ return $this->content; }
}
class Player
{
protected $skills;
public function __construct()
{
$this->skills = new FancyArray();
$this->skills->add("Ninjitsu");
}
}

PHP how to use magic method with static class? [duplicate]

This question already has answers here:
Magic __get getter for static properties in PHP
(6 answers)
Closed 9 years ago.
I'm trying to convert array to object. I want to use magic methods - __get and __set with static properties.
My code:
class UserData {
private static $id, $name, $login;
public function __get($var)
{
return self::$var;
}
public function __set($var, $val)
{
self::{$var} = $val;
}
}
And setting:
foreach($userArray as $key => $val)
{
DaneBilingowe::${$key} = $val;
}
Error:
Fatal error: Cannot access private property UserData::$id
Is it possible to use magic method with static property?
In short, no.
__get() and __set() are instance methods. They are essentially the functions that make up the stdClass(), which is an instance.
If you must set static content in this manner you can give the class a stdClass parameter and a singleton structure that would allow you to magically set and get data.
For example:
class UserData {
protected static $_instance;
protected $_data = array();
public static function get_instance() {
static $initialized = FALSE;
if ( ! $initialized) {
self::$_instance = new UserData;
$initialized = TRUE;
}
return self::$_instance;
}
public function __get($var) {
$self = self::get_instance();
return isset($self->_data[$var]) ? $self->_data[$var] : NULL;
}
public function __set($var, $val) {
$self = self::get_instance();
$self->_data[$var] = $val;
}
}
Then you could go:
$UserData =& UserData::get_instance();
$UserData->var = 'val';
echo $UserData->var; // prints 'val'
I don't recommend using Singletons in PHP, however, because they are pointless. You can read some reasons why in the post Best practice on PHP singleton classes.
Either use a static class or an instance class.
Magic getters and setters are shortcuts. You can implement the same behavior with normal setters and getters. The example below provides the same functionality, but the intent is a lot more clear:
class UserData {
protected $id, $name, $login;
public static function set_name($name) {
self::$name = $name;
}
public static function set_login($login) {
self::$login = $login;
}
public static function get_id() {
return self::$id;
}
public static function get_name() {
return self::$name;
}
public static function get_login() {
return self::login;
}
}
Notice how in the above code $id is not writable. It is only readable. $name and $login are readable and writable. It is easier and less buggy to control reading and writing using normal setters and getters. Magic methods are just that, magic, and usually magic is not concrete and is less understandable in code.
The final point I want to make is, why would UserData be static? Unless you only have 1 user in the entirety of your code it doesn't make sense to have it static. Perhaps I am not getting the whole picture, but something with an id and name should be instantiated so that you can have multiple instances. Otherwise, why have the id because the class itself is unique.
If you really want to use magic methods on static properties, you can but you will need an instance. Though it does not look reasonable, being a programmer itself is not reasonable at all :)
Also user defined classes and objects are not dynamic in php.
You can not add variables to them that easily... So you can use the pattern below:
class UserData {
private static $id, $name, $login, $arr = [];
public function __get($var){
return (array_key_exists(self::$arr, $var)? self::$arr[$var]:null;
}
public function __set($var, $val){
self::$arr[$var] = $val;
}
}
And setting: Well what is DaneBilingowe? I do not now here... But:
$inst = new UserData();
foreach($userArray as $key => $val){
$inst->$key = $val;
}
will work.
But beware, It will work only on class (static) memory.
Also since there is no appropriate filtering for setting names, weird things can happen.
(That means you should add them)

Class returning object confusion

I've been asked to create a class that does some stuff, and then returns an object with read only properties.. Now I've created the class and I've got everything working 100%, however I'm confused when they say to 'return an object with read only properties'.
This is the outline of my php file which contains the class and some extra lines calling it etc:
class Book(){
protected $self = array();
function __construct{
//do processing and build the array
}
function getAttributes(){
return $this->self; //return the protected array (for reading)
}
}
$book = new Book();
print_r($book->getAttributes());
How can I return an object or something?
You are probably looking for the keyword final. Final means the object/method cannot be overridden.
Protected means that the object/method can only be accessed by the class who it belongs to.
Since self is a reserved keyword, you need to change that as well as your declarations. Rename $self an $this->self to $data and $this->data
self is a PHP reserved word. You have to renamed your variable.
What they're referring to is an object with private or protected properties which can only be accessed by setters/getters. The property will be read-only if you only define the getter method.
Something like:
Class Book {
protected $attribute;
protected $another_attribute;
public function get_attribute(){
return $this->attribute;
}
public function get_another_attribute() {
return $this->another_attribute;
}
public method get_this_book() {
return $this;
}
}
Now this is kind of s silly example because Book->get_this_book() would return itself. But this should give you an idea of how to set of getters on protected properties such that they are read only. And how to reutrn an object (in this case it returns itself).
read only property means you can access them but can not write them
class PropertyInaccessible {
//put your code here
protected $_data = array();
public function __get($name) {
if(isset ($this->_data[$name]))
return $this->_data[$name];
}
public function __set($name, $value) {
throw new Exception('Can not set property directly');
}
public function set($name, $value) {
$this->_data[$name] = $value;
}
}

PHP: Detect instances of same class

I have a PHP Class which requires a unique value in its constructor. If multiple instances of the same class are passed the same value the results are horrific.
How would I go about detecting other instances of a Class so I can check and prevent this from happening before constructing any new ones?
A simple solution would be to keep a static array of the values inside the class. Then, when a new instance is created, check the static array's contents in the constructor.
Something like..
class Foo {
private static $usedValues = array();
public function __construct($val) {
if(in_array($val, self::$usedValues)) {
throw new Exception('blah');
}
self::$usedValues[] = $val;
}
}
I think the multiton pattern is right for you.
class Foo {
static protected $_instances = array();
static public function getInstance($id) {
if(!self::exists($id)) {
self::$_instances[$id] = new Foo($id);
}
return self::$_instances[$id];
}
static public function exists($id) {
return isset(self::$_instances[$id]);
}
protected function __construct($id) {
}
}

Categories