Php: Exposing private members of a class - php

I have a class User which has private properties of a user and public interfaces. I am trying to expose those properties through OOP in order to bind their $key=>value to some sql parameters, but I can iterate over private members in order to extract the data. I have saw the var_dump() method which is usually used for debugging, so I created a public interface userInfo() that would return that object as an array. However, that just seems like a hack and not a real eloquent way of exposing or sharing data across this application. Ive read tons of articles and in class we are taught to keep members private and expose them through public interfaces. I know there is the protected member access, but is that eloquent enough? So, how would a "good", and I know that subjective, coder share this data across the application?
EDIT: Cannot use protected because nothing extends the user class
class User{
private $firstname
private $lastname
private $username
private $password
public getFirstName(){}
public getLastName(){}
public getUsername(){}
public getPassword(){}
public userInfo(){
return get_object_vars($this)
}
}

PHP has overloading / magic methods exactly for this purpose. You don't need to programmatically think of every possible value / field. Have a look at the below example:
class MyClass {
private $firstField;
private $secondField;
public function __get($property) {
if ( property_exists($this, $property) ) {
return $this->$property;
}
}
public function __set($property, $value) {
if ( property_exists($this, $property) ) {
$this->$property = $value;
}
return $this;
}
}

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.
}
}

Use functions from a class in another class without extending?

I have multiple classes, in this case Core and User. At this moment User is an extension of Core. In Core, I have my main functions that are required in multiple classes, for example a database connection through PDO. I use a __construct function to build the database connection, no problems with that.
However, in my User class, I want to pass values to multiple attributes through __construct. For example a Firstname, Lastname, Email, Password and a few other attributes.
When doing this, I get a warning from Netbeans that the parent constructor should be used, and a lot of vague errors, I don't ask you to fix these errors.
I would like to know if there is a way for me to use the database connection function from Core in User without making the extension. I hope it is more clear with a little bit of background information!
Below both classes, only showing the parts related to the question:
abstract class Core implements ICore {
private $_dbcon;
public function __construct($_database){
$this->_dbcon = $_database;
}
public function _connectDB(){
return $this->_dbcon;
}
class User extends Core implements IUser {
public $_username;
private $_password;
protected $_email;
protected $_adres;
protected $_phone;
protected $_contactperson;
protected $_company;
protected $_kvk;
public function __construct($_username, $_password, $_email, $_adres, $_phone, $_contactperson, $_company, $_kvk){
$this->_username = $_username;
$this->_password = $_password;
$this->_email = $_email;
$this->_adres = $_adres;
$this->_phone = $_phone;
$this->_contactperson = $_contactperson;
$this->_company = $_company;
$this->_kvk = $_kvk;
}
You have to call the parent constructor.
class User extends Core
{
public function __construct($db, $username, ...)
{
parent::__construct($db);
$this->_username = $_username;
...
}
}
But in your case I would think about a better overall design. Read about Dependency injection. In this way you'd only have one DB connection and use that connection in other classes.
class User
{
protected $db;
public function __construct(Db $db)
{
$this->db = $db;
}
}

Not able to access private protect member in iterator 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);

doctrine2 and codeigniter2, right approach for parent class to interact with child properties

I'm searching for this for quite some time now.
I saw few similar questions but not sure if they apply with doctrine2 and this problem.
I'm trying to get started with CodeIgniter2 and Doctrine2, and I'm having some problems, I'm not OOP guru in php.
I would like to have MainObject that will contains methods for CRUD and few others, and I want objects to extend that class and use parent's methods, but with child's properties. Since Doctrine2 uses Private Properties for objects, I cannot access these methods from parent class. For example:
Class MainObject{
public function validateFields(){
//go over each field and validate/update if needed
}
public function store(){
// do some validation, some logic, store, etc...
}
}
Class User extends MainObject{
/**
* #Column(type="string", length=32, unique=true, nullable=false)
*/
private $username;
/**
* #Column(type="string", length=64, nullable=true)
*/
private $email;
}
Now, I would like to just call
$user = new User();
//set properties, somehow
$user-__set($something);
//call validation or store or some method from the parent that will interact with child properties
$user->validate();
$user->store();
$user->uploadImage();
$user->formatPropertiesForSomethingSpecial();
I'm almost there to do this by using the ReflectionClass but I'm not sure that I'm doing this the right way?
Or is there a way to have MainObject with all this methods, and then just pass User to it so it can do what it should do with user, is perhaps that the 'righter' approach? I don't think it will allow me to do something with Private properties from the user, but I guess that User can have its own getters and setters?
I'm working with semi-oop in php for years, but this is something new for me, so thanks for any advice, tutorial, url, critique, anything.
The easiest (and correct) way is to use a setter.
Class User extends MainObject{
private $username;
private $email;
public function set_username($username) {
$this->username = $username;
}
}
If you want to make it less verbose, use a general purpose setter in the parent:
Class MainObject{
public function validateFields(){
}
public function store(){
}
public function set($data) {
foreach ($data as $key => $value) {
if (property_exists($this, $key)) {
$this->$key = $value;
}
}
}
}
// Example
$user = new User();
$data = array('username' => 'foo', 'email' => 'bar#bar.bar');
$user->set($data);
$user->validate();
$user->store();
You will need at least PHP >= 5.1 for the second method.
I just brushed up on my visibility documentation. You'll need to use a protected property instead of private, or write all of your setters in the child class.

How to override a static property of a parent object and let the parent object access the new value in PHP?

This is what I have: All objects that can be persisted on the database extend the DatabaseObject abstract class, which has all the logic code to actually watch for attribute changes and run the databas queries.
I'm using two static variables to define object-specific details. I define them generically in the base class, and then supposedly I overwrite them in the actual database objects.
The problem is: When the code in the parent class is actually executed, it uses the old parent value instead of the current object value.
Here's the code for the base class:
abstract class DatabaseObject {
public $id;
private static $databaseTable = NULL;
private static $databaseFields = array();
private $data = array();
private $changedFields = array();
public function IDatabaseObject($id) {
$this->id = $id;
$this->data = Database::GetSingle(self::$databaseTable, $id);
Utils::copyToObject($this, $this->data, self::$databaseFields);
}
public static function Load($id) {
return new self($userID);
}
public static function Create($data) {
$id = Database::Insert(self::$databaseTable, $data);
return new self($id);
}
public function Save() {
$data = Utils::copyFromObject($this, $this->changedFields);
Database::Update(self::$databaseTable, $data, $this->id);
}
public function __constructor() {
// We do this to allow __get and __set to be called on public vars
foreach(self::$databaseFields as $field) {
unset($this->$field);
}
}
public function __get($variableName) {
return $this->$variableName;
}
public function __set($variableName, $variableValue) {
// We only want to update what has been changed
if(!in_array($variableName, $this->changedFields) && in_array($variableName, self::$databaseFields)) {
array_push($this->changedFields, $variableName);
}
$this->$variableName = $variableValue;
}
}
And here's the code for one of the objects extending the base class above:
class Client extends DatabaseObject {
public static $databaseTable = "clients";
public static $databaseFields = array("name","contactName","primaryUserID","email","is_active","rg","cpf","cnpj","ie","addrType","addrName","addrNumber","addrComplement","addrPostalCode","addrNeighborhood","addrCity","addrState","addrCountry","phoneLandline","phoneFax","phoneMobile");
public $name;
public $contactName;
public $primaryUserID;
public $email;
public $is_active;
public $rg;
public $cpf;
public $cnpj;
public $ie;
public $addrType;
public $addrName;
public $addrNumber;
public $addrComplement;
public $addrPostalCode;
public $addrNeighborhood;
public $addrCity;
public $addrState;
public $addrCountry;
public $phoneLandline;
public $phoneFax;
public $phoneMobile;
public static function Load($id) {
return new Client($id);
}
}
What am I doing wrong here? Is there another way I can achieve the same result?
A brief addendum: I declare the attributes in the class body mainly to let it be seen by the NetBeans' auto-complete feature.
You are looking for Late Static Binding.
So you need to use:
static::$databaseTable
instead of
self::$databaseTable
This feature is available as of PHP 5.3. Simulating this in PHP 5.2 is very hard, because of two reasons: get_called_class is available only since PHP 5.3, too. Therefore it must be simulated, too, using debug_backtrace. The second problem is, that if you have the called class, you still may not use $calledClass::$property because this is a PHP 5.3 feature, too. Here you need to use eval or Reflection. So I do hope that you have PHP 5.3 ;)

Categories