What those $variable->$variable in OOP php do? - php

I am following a tutorial and have come across the following code in defining a user class:
class User {
public $id;
public $username;
public $password;
public $first_name;
public $last_name;
public static function instantiate($record) {
$object = new self;
foreach ($record as $attribute => $value){
if ($object->has_attribute($attribute)){
$object->$attribute = $value;
}
}
return $object;
}
private function has_attribute($attribute) {
$object_vars = get_object_vars($this);
return array_key_exists($attribute, $object_vars);
}
}
My question is: What does the "$object->$attribute = $value;" do exactly ?
I am just starting in OOP php and I am really confuse of what that bit of code is downing.
Thanks a lot.

Pretty basic question : it is assigning the value $value to the attribute $attribute of the object $object.
In other words, it is copying the value of the variable $value to the attribute of the object $object.

It's an assignment statement for an attribute of the PHP class. Let's use a less ambiguous example. We will create a small person class that holds a first name and a last name.
class Person
{
//Class attributes
public $fisrtName;
public $lastName;
}
Using the above example, if you wanted to set those attributes, you would do the following:
//Instantiate a new person
$myPerson = new Person();
//Assign values to the person object
$myPerson->firstName = "John";
$myPerson->lastName = "Smith";
Alternately, if you wanted to assign the value myPerson object's firstName field to a different variable, you could do the following:
$personsName = $myPerson->firstName;

All this is doing is internally creating a new instance of it's creating a new instance of it's self for a form of recursion or other functionality,
so calling:
$object->$attribute
is essentially, from what I can see. Will create a new instance then depending on the contents of $attribute return a value or call a method

Related

What is the difference between assigning property values using a constructor and property assignment in the class declaration?

What is the difference between assigning property values using a constructor and direct property assignment within the class declaration? In other words, what is the difference between the following two pieces of code making default values for the new object?
Code with direct assignment:
<?php
class A {
public $name="aName";
public $weight = 80;
public $age = 25;
public $units = 0.02 ;
}
?>
Code with constructor:
<?php
class A {
public $name;
public $weight;
public $age;
public $units;
public function __construct() {
$this->name = "aName";
$this->weight = 80;
$this->age = 25;
$this->units= 0.02 ;
}
}
?>
You may answer that i can't change the hard coded properties, but i could in the following code( In Local Sever ):
<?php
class A{
public $name="aName";
public $weight = 80;
public $age = 25;
public $units = 0.02 ;
}
class B extends A{
public function A_eat(){
echo $this->name.' '."is".' '.$this->age.' '."years old<br>";
echo $this->name.' '."is eating".' '.$this->units.' '."units of food<br>";
$this->weight +=$this->units;
echo $this->name.' '."weighs".' '.$this->weight."kg";
}
}
$b = new B();
echo "<p>If no changes to the object's Properties it inherits the main class's</p>";
$b->A_eat();
echo '<br><br>';
echo "<p>If changes made to the object's Properties it uses it's new properties</p>";
$b->name ="bName";
$b->weight = 90;
$b->units = 0.05;
$b->A_eat();
?>
When a property declaration contains initialization, the initialization is evaluated at compile time, i.e. in the step when the PHP source is compiled into PHP opcodes.
The code within constructor is evaluated at run time, i.e. at the time when one creates an object with new operator.
There is practically no difference, if you don't use opcode caching (OPcache, APC, and similar extensions). However, if the opcodes are cached, the performance will be better with the compile-time initialization, obviously.
Nothing really however,...
in the construct() you could pass in optional variables... for instance..
public function __construct($name = 'aName', $weight = 80, $age = 25, $units = 0.02) {
$this->name = $name;
$this->weight = $weight;
$this->age = $age;
$this->units = $units;
}
In the first example you posted, you are defining HARD values to your properties, where as in the 2nd one, the construct will let you "build" those...
Take the first example:
$x = new Class();
// You can't change it, those properties are what you coded in...
Now look at my example...
$x = new Class('My New Name', 120, 30, 0.10);
// Now $name = 'My New Name' etc...
The construct lets you build the object on initialization rather than hard coding the default values like you had...
You could use the default values and create setters, but I like the __construct()
Because the constructor can receive parameters to have the object start with values other than some default values. Without a constructor with parameters, you would have to create a default object, then modify it's fields.
Also note there's always a constructor; it's just a question of whether or not you've created one yourself, or a default one is created for you that doesn't require any arguments.
A constructor in this case simply puts an object into an active state, allocating proper memory.
One may create a Person object with just a name provided as argument, but another constructor may be needed when both a name and age are given as arguments.
In PHP you are limited to 1 unfortunatly, _contruct
You can have multiple constructors built however in a work around way shown here.
There's nothing major difference between both of these.
Both the approaches are fine, and it basically depends upon your use cases.
According to the first approach you are unable to assign values to class members while creating the Class's object whereas in the 2nd approach you have that power, Let me demonstrate this:
class A
{
protected $name = 'John';
protected $age = 20;
}
$obj = new A();
/* Here you get an object with
** $obj->name = 'John'
** $obj->age = 20;
*/
Whereas in approach 2nd you have the power of defining the variables on the go(while defining its Object). Everytime you create an object for Class B you can have different object everytime based on your passed arguments to the class constructor:
class B
{
protected $name;
protected $age;
public function __construct($name = 'John', $age = 20)
{
$this->name = $name;
$this->age = $age;
}
}
$obj = new B("John Doe", 40);
/* Here you get an object with
** $obj->name = 'John Doe'
** $obj->age = 40;
*/
$obj = new B("John Doe");
/* Here you get an object with
** $obj->name = 'John Doe'
** $obj->age = 20;
*/
Classes which have a constructor method call this method on each
newly-created object, so it is suitable for any initialization that
the object may need before it is used
Hope this helps!
What is the difference between a construct method and object properties and when should I use them?
First and foremost, construct() returns an instance of the class you're using, hence why if you ever try return something different inside this method:
public function __construct() { return 'hello, world!'; }
It will not actually work. You're probably asking what this means and why its so important to the question. Well, there are more than just two ways to access data in a property, there are things we call getters and setters.
private $_name;
public function setName($name) { $this->_name = $name; return $this; }
public function getName() { return $this->_name; }
In your use-case, I assume that your data is not constant, it isn't always going to be an age of 25 so you could use multiple ways to approach this. If the data comes from a database, a constructor method would be useful to load the configuration like so:
public $name;
public function __construct($id) {
$user = SomeDriver::GetInstance()->on('Users', '*')->where('user_id = ?', [$id]);
$this->name = $user['username'];
}
Which you can then just access through the instance like $obj->name. However, if you're just setting data through input, you could just use setter/getter or access the properties directly outside the scope;
class User {
public $name = 'Frank';
public function setName($name) { $this->name = $name; return $this; }
public function getName() { return $this->name; }
}
$u = new User;
echo $u->name;
$u->name = 'John';
// or change the property to private and:
$u = new User;
echo $u->getName();
$u->setName('John');

Appropriate use case of __get in daily life programming

I am in learning phase of OOP and PHP. Below is how i implemented __get method. It is working fine but i don't understand why to use it. Since in my example i set the property to protected deliberately so that i can't be accessed via outside class. Then what is the purpose of __get then ?
class Magic {
protected $name = 'John';
public $age = 26;
public $new_name;
public function __get($key){
$this->new_name = $key;
}
public function get_new_name(){
return $this->new_name. " is my friend";
}
}
$person = new Magic();
$person->Alan;
echo $person->get_new_name();
There is no valid reason I would have thought of that you would use __get() with a protected string, protected arrays would be useful, but not strings. The example you provided works, but it isn't going to be the best code for others to understand or for use with IDEs (code editors).
Since you don't seem to understand what I was saying, here is an example of a quick database script.
Let's say you want to insert a row in the database using an ORM-like class. You would do something like:
Class Person {
protected $fields = array();
public function setField($name, $value) {
$this->fields[$name] = $value;
}
public function getField($name) {
return $this->fields[$name];
}
public function save() {
Database::insert($table, $fields); // Generic function to insert the row, don't worry about this.
}
}
Now in this instance you could do:
$person = new Person();
$person->setField('name', 'Bob');
$person->setField('age', '30');
$person->save();
echo $person->getField('name'); // Echoes Bob
Overloading
Now to change this, we could use overloading with __set() instead of setField() and __get() instead of getField():
Class Person {
protected $fields = array();
public function __set($name, $value) {
$this->fields[$name] = $value;
}
public function __get($name) {
return $this->fields[$name];
}
public function save() {
Database::insert($table, $fields);
}
}
Now in this instance you could do:
$person = new Person();
$person->name = 'Bob';
$person->age = '30';
$person->save();
echo $person->name; // Echoes Bob
Hopefully this gives you an easy example of how overloading can work. We don't want to declare the properties $name and $age because we want to use those properties to build the $fields array which is later used in the insert.
For example you can use the __get method for obtain the value of an array. In this case you can have a dynamic number of class variable.
public function __get($key){
return $this->property[$key];
}

Why is my PHP class acting static?

New to PHP.
I have created a simple class:
class User
{
private $name;
private $password;
private $email;
public function getName()
{
return $this->name;
}
public function setName($value)
{
$this->name = $value;
}
public function setPassword($value)
{
$this->password = $value;
}
public function setEmail($value)
{
$this->email = $value;
}
public function getEmail()
{
return $this->email;
}
}
I created 2 instances of this class and stored the first instance into an array. I am then checking to see if the second instance exists in the array (the one I did not add to the array). For some reason in_array() always returns '1' or true.
It turns out that the array now somehow contains the second user object that I did not explicitly add to the array. As if the properties of User are behaving like static class members. What am I missing?
$user = new User();
$user::setName('Nick');
$user::setEmail('bbbb#gmail.com');
$user::setPassword('bbbbb');
$somethingelse = new User();
$somethingelse::setName('Mindy');
$somethingelse::setEmail('a#gmail.com');
$somethingelse::setPassword('aaaa');
$arr = array('users'=>$user); //add first object to array
echo in_array($somethingelse,$arr); //check if second object is in array
echo $arr['users']::getName(); //Prints mindy
}
Because you're using the namespace resolution operator ::, rather than the instance dereferencing operator ->. The first invokes the method on the class, the second on an instance. If you turn on E_STRICT error reporting (which you should!), you'll see a bunch of warnings about calling instance methods statically.
To fix this, use $user->setName('Nick'); (with similar changes elsewhere).
use
->
instead of
::
In short, it’s used to access Static or Constant members of a class.
it would result in
$user = new User();
$user->setName('Nick');
$user->setEmail('bbbb#gmail.com');
$user->setPassword('bbbbb');
$somethingelse = new User();
$somethingelse->setName('Mindy');
$somethingelse->setEmail('a#gmail.com');
$somethingelse->setPassword('aaaa');
$arr = array('users'=>$user); //add first object to array
echo in_array($somethingelse,$arr); //check if second object is in array
echo $arr['users']->getName(); //Prints mindy

get the name of the object calling one of its methods

is it possible to get the name of the object which calls one of its methods.
scenario:
I have class A. I instantiate 2 objects of that class. If one object calls a method, is it possible to retrieve the name of the object which called it?
EDIT:
class Property() {
public function __call($name, $atts) {
if ($name === 'foo') {
//I want to differ Between Color and Position
}
}
}
$Color = new Property();
$Position = new Property();
$Color->foo();
$Position->foo();
Add a name element to your object:
class ObJA {
$this->name;
function __construct($name){
$this->name = $name;
}
function getName(){ return $this->name; }
}
On object create:
$a = new ObJA('a');
$b = new ObJA('is b');
echo $a->getName(); //`a`
echo $b->getName(); //`is b`
You can always use get_class(), but the name is not going to change simply by creating two or more instances of the object. Neal's solution will work but it doesn't actually change the name of the class, and begs the question: Why do you need it?

PHP Class Property Name

I have a class called contact:
class contacts
{
public $ID;
public $Name;
public $Email;
public $PhoneNumber;
public $CellPhone;
public $IsDealer;
public $DealerID;
}
At some point in my code I would like to point to a property within that class and return the name of the property.
<input type="text"
id="<?php key($objContact->Name)" ?>"
name="<?php key($objContact->Name)" ?>"
value="<?php $_POST['contact'.key($objContact->Name)]" />
My issue being that the key() function only deals with arrays or objects. $objContact->Name itself does not meet these requirements. I know it would be just as simple to type the name itself out into the ID and NAME fields but this is for other code verification uses. Imagine the processor page:
$objContact = new contact();
$objContact->Email = $_POST[$objContact->Email->**GetSinglePropertyName()**];
$objContact->PhoneNumber = $_POST[$objContact->PhoneNumber->**GetSinglePropertyName()**];
This allows me to turn on STRICT and ensure that as I'm writing I'm not creating any fat finger errors along the way that are going to have me denting my head anymore than it presently exist.
UPDATE WITH ANSWER
Answer provided by: linepogl
Now I've taken linepogl's idea and extended is some so it can work very easily with my existing code base. Here's what I've come up with:
class baseData {
public $meta;
public function __construct() {
$this->meta = new Meta($this);
}
}
class Meta {
public function __construct($obj) {
$a = get_object_vars($obj);
foreach ($a as $key => $value){
$this->$key = $key;
}
}
}
class contacts extends baseData
{
public $ID;
public $Name;
public $Email;
public $PhoneNumber;
public $CellPhone;
public $IsDealer;
public $DealerID;
}
Which means I can now call the following code with the desired results:
$objContact = new contacts();
echo($objContact->meta->Email);
So, you want when you type $objContact->Name to take as an answer not the evaluation of this expression but its meta data, which in this case is a ReflectionProperty object.
What you want is a feature that is called metaprogramming ( http://en.wikipedia.org/wiki/Metaprogramming ). Of course php does not support that but there are other languages that do, such as Lisp etc. Rumors say that C# 5.0 will introduce such features.
You can achieve a similar effect by using Reflection ( http://php.net/manual/en/book.reflection.php ). You can get the meta-object of $objContact (ReflectionClass) and iterate over the properties.
So, there is no way to identify a specific property with an identifier. The only way to do is is with a string of its name.
EDIT:
Yet, there a way to simulate it! Write a class like this:
class Meta {
public function __construct($obj) {
$a = get_object_vars($obj);
foreach ($a as $key => $value){
$this->$key = $key; // <-- this can be enhanced to store an
// object with a whole bunch of meta-data,
// but you get the idea.
}
}
}
So now you will be able to do this:
$meta = new Meta($objContact);
echo $meta->Name; // <-- with will return 'Name'!
You can use get_object_vars() like this:
$properties = get_object_vars($objContact);
foreach($properties as $name => $value)
{
if($value == $objContact->Name)
{
//here's youre name
}
}
but with this you will have to assume that $objContact->Name has unique value over all properties...
The key() function works very well with objects. It just doesn't accomplish what you are seemingly trying to do.
$c = new contacts;
end($c);
print key($c); // "DealerID"
You can foreach over object attributes, and PHP remembers the last accessed key(). But I'm not sure if this is what you want.
As alluded to by konforce, is this what you are looking for?
$var = 'Name';
$Obj->$var;//Obj's Name property
...
id="<?php $var ?>" //id="Name"
...
$_POST['contact'.$var];//$_POST['contactName']

Categories