On Fri, May 27, 2016 at 6:34 AM, Lester Caine <les...@lsces.co.uk> wrote:

> On 27/05/16 11:25, Fleshgrinder wrote:
> > On 5/27/2016 11:41 AM, Lester Caine wrote:
> >> Now I am confused, but it's probably because I'm looking at a simple
> >>
> >> $f->d = new DateTime( $initial );
> >>
> >> While you are looking at
> >>
> >> If ( isset($initial) )
> >> then $f->d = new DateTime( $initial );
> >> else $f->d = null;
> >>
> >> While the original code would have simply been
> >>
> >> $f->d = $initial;
> >>
> >> And in an ideal world, because $d has been typed as DateTime this would
> >> magically run 'new DateTime($initial)' which is where I am stumbling
> >> because *I* simply look at '?DateTime $d' as creating a DateTime object
> >> where in fact $d is a different type of object which will then hold the
> >> link to the real one. I am still looking for $d to be an object I can do
> >> all of the checks on that are provided by int or DateTime as appropriate
> >> ... the object needs to exist before the 'new' in order to know if you
> >> need the first or second type of $initial code ... or we make typed
> >> properties only work one way or the other?
> >
> > PHP does not automagically instantiate the DateTime object for you, this
> > is still your responsibility. The type hint on the property only
> > restricts what you are allowed to assign to the property, nothing else.
>
> If you want something to magically happen when setting a property, PHP has
a way to do this called magic methods. Think about this:

class Person {
   protected ?DateTime $death;

   public function setDeath($date) {
      if (!empty($date) && is_string($date)) {
         $this->death = new DateTime($date);
      }
      elseif ($date instanceof DateTime) {
          $this->death = $date;
      }
      // else $date is empty, person has not died
   }

   public function __set($prop, $val) {
      if (method_exists($this, "set_$prop")) {
         $this->{"set_$prop"}($val);
      }
   }

   public function __get($prop) {
       if (property_exists($this, $prop)) {
          return $this->$prop;
       }
   }
}

$p = new Person();
$p->death = "2015-06-01";
var_dump($p->death); // class DateTime#1 (3) { ...

$p2 = new Person();
$p2->death = new DateTime("2016-01-02");
var_dump($p2->death); // class DateTime#1 (3) { ...

$p3 = new Person();
var_dump($p3->death); // NULL, $p3 is not dead

Note, all of this is possible currently except the typing of the property,
you could enforce this right now in exactly this way.

If however, you want an object that will provide a format function (as in
your example) whether or not it was initiated with a value, then you would
need to define your own class for that:

class MyDateTime {
    protected $dt;

    public function __construct($date) {
        if (!empty($date)) {
           $this->dt = new DateTime($date);
        }
    }

   public function format($format) {
      if (!empty($this->dt)) {
          return $this->dt->format($format);
      }
      return '';
   }
}

Now you can blindly initialize it, and call format on it, whether or not
the date is provided. This is all controllable in userland, there is no
reason to make the language do it for you, as its purely a design decision.

Reply via email to