what calls the magic __get method, how does this differ from the magic __set method

from lynda.com
php object oriented tutorial

demo.php
<?php

require 'class.Address.inc';

echo '<h2>Instantiating Address</h2>';
$address = new Address;

echo '<h2>Empty Address</h2>';
echo '<tt><pre>' . var_export($address, TRUE) . '</pre></tt>';

echo '<h2>Setting properties...</h2>';
$address->street_address_1 = '555 Fake Street';
$address->city_name = 'Townsville';
$address->subdivision_name = 'State';
$address->postal_code = '12345';
$address->country_name = 'United States of America';
echo '<tt><pre>' . var_export($address, TRUE) . '</pre></tt>';

echo '<h2>Displaying address...</h2>';
echo $address->display();

echo '<h2>Testing magic __get and __set</h2>';
unset($address->postal_code);
echo $address->display();

echo '<h2>testing address __construct with an array</h2>';
$address_2 = new Address(array(
  'street_address_1' =>'123 Phony Ave',
  'city_name' => 'Villageland',
  'subdivision_name' => 'region',
  'postal_code' => '67890',
  'country_name' => 'Canada',
));
echo $address_2->display();

Open in new window


class.address.inc
<?php

/**
 * Physical address. 
 */
class Address {
  // Street address.
  public $street_address_1;
  public $street_address_2;
  
  // Name of the City.
  public $city_name;
  
  // Name of the subdivison.
  public $subdivision_name;
  
  // Postal code.
  protected $_postal_code;
  
  // Name of the Country.
  public $country_name;
  
  // Primary key of an Address.
  protected $_address_id;
  
  // When the record was created and last updated.
  protected $_time_created;
  protected $_time_updated;
  
  function __construct($data=array()){
    $this->_time_created=time();
    
    //ensure that the address can be populated
    if (!is_array($data)){
      trigger_error('Unable to construct address with a ' . $get_class($name));
    }
    // if there is a least one value, populate the address with it
    if(count($data)>0){
      foreach($data as $name=>$value){
        //special case for protected properties
        if(in_array($name,array(
        'time_created',
        'time_updated',
        ))){
          $name='_'.$name;
        }
        $this->$name=$value;
      }
    }
    
  }
  
  /**
   * Magic __get.
   * @param string $name 
   * @return mixed
   */
  function __get($name) {
    // Postal code lookup if unset.
    if (!$this->_postal_code) {
      $this->_postal_code = $this->_postal_code_guess();
    }
    
    // Attempt to return a protected property by name.
    $protected_property_name = '_' . $name;
    if (property_exists($this, $protected_property_name)) {
      return $this->$protected_property_name;
    }
    
    // Unable to access property; trigger error.
    trigger_error('Undefined property via __get: ' . $name);
    return NULL;
  }
  
  /**
   * Magic __set.
   * @param string $name
   * @param mixed $value 
   */
  function __set($name, $value) {
    // Allow anything to set the postal code.
    if ('postal_code' == $name) {
      $this->$name = $value;
      return;
    }
    
    // Unable to access property; trigger error.
    trigger_error('Undefined or unallowed property via __set(): ' . $name);
  }
  
  /**
   * Guess the postal code given the subdivision and city name.
   * @todo Replace with a database lookup.
   * @return string 
   */
  protected function _postal_code_guess() {
    return 'LOOKUP';
  }
  
  /**
   * Display an address in HTML.
   * @return string 
   */
  function display() {
    $output = '';
    
    // Street address.
    $output .= $this->street_address_1;
    if ($this->street_address_2) {
      $output .= '<br/>' . $this->street_address_2;
    }
    
    // City, Subdivision Postal.
    $output .= '<br/>';
    $output .= $this->city_name . ', ' . $this->subdivision_name;
    $output .= ' ' . $this->postal_code;
    
    // Country.
    $output .= '<br/>';
    $output .= $this->country_name;
    
    return $output;
  }
}

Open in new window



because
$this->postal_code is unset, then the __get method is called

if I echo
$this->dasfdafafasfasf;
then will the get method be called


I do not understand how this relates/differs from the set method
LVL 1
rgb192Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Beverley PortlockCommented:
The __get and __set methods are called when you attempt to access a protected or a private class property. If a property has no access modifier or is declared as public then you can access it directly from outside the class

So if you attempted to assign a value to a private or protected property then the __set method is called.

If you attempt to fetch a value from a protected property then the __get method is called.

If you use statements that do not assign a value then neither __set nor __get will be called. An example would be unset()


In the example you gave of $this->dasfdafafasfasf; results in a call to the __get method because  "dasfdafafasfasf" is not a public property
0
Ray PaseurCommented:
Here's my two Euros: Any method or property that is defined as private or protected is defined that way for a reason, and when you decide you need to use a magic method to access the property from outside its intended scope, it's a very strong indication that you're not using the original class as it was intended.  Or that the original class needs to be refactored.  If the class author expected these variables to be accessed or mutated by non-class elements, they would be defined public or there would be setter() and getter() methods.  Encapsulation is good.
0
Slick812Commented:
I will add some of MY view about the __get and __set magic methods, , these can be useful if you have set up your class definition to be "flexible" and use a class property as an array (or object) to store some specially used properties,that are added (or not added) at runtime where you call
$addres->table_name = "table1";
$addres->sql_opp = "INSERT";

where the properties table_name and sql_opp are not directly assigned in the Class, so the  __set( ) method is used  and it is IMPORTANT that you have a way to FILTER what is allows to be set and what is NOT allowed, usually with a list (array of values) property names that are are allowed. AND most important, there is some special PHP processing that is required INSIDE the Class when setting or getting these properties.
Your code example for teaching seems like a terrible teaching or learning example for the __set( ) thing, as it does NOT emphasize the need for special added processing when ever the postal-code this is added.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
rgb192Author Commented:
The __get and __set methods are called when you attempt to access a protected or a private class property. If a property has no access modifier or is declared as public then you can access it directly from outside the class

Thanks
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.