php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #52626 New magic method for procedural calls on object.
Submitted: 2010-08-17 18:00 UTC Modified: 2020-03-01 23:10 UTC
From: jay at jay dot cz Assigned:
Status: Suspended Package: Class/Object related
PHP Version: Irrelevant OS: *
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: jay at jay dot cz
New email:
PHP Version: OS:

 

 [2010-08-17 18:00 UTC] jay at jay dot cz
Description:
------------
<?php
$a = Array();
$a['a'] = 'text';
$a['b'] = 15;
$a['c'] = 155.12;
?>

Classic style:
<?php
ksort( $a );
is_array( $a );
?>

Object style:
<?php
$oa = new ObjArray($a); // extends ArrayIterator or ArrayObject
$oa->ksort();
$oa->is_array(); //implemented in ObjArray
?>

But what if :
<?php
$oa = new ObjArray($a); // extends ArrayIterator or ArrayObject
ksort( $oa );
is_array( $oa );
?>

(SplTypes project is dead and I need object types.)
Now it is not possible to control, what functions are executed on object.


If a language function is used on a object, php would 
Variant 1) try to call object function of the same name,
Variant 2) call magic method __callOnObject if exists 

Both variants can be implemented together.


Possible problem in variant 1)
Programmer would need to take care, to really implement exact same structure of parameters, with all optional parameters, elze it would throw errors on different arguments.
There could by a variant 1a) where, called function doesn't list all arguments, but passes an array of arguments. But that would make object calls too different from procedural.




Test script:
---------------
Variant 1)

class ObjArray extends ArrayIterator{
  public function is_array( $var ){
    return is_array( $this->storage );
  }
  public function is_object( $var ){
    return is_object( $this->storage );
  }
}

$obj = new ObjArray( Array( 1, 2 ) );
var_dump( is_array( $obj ) );
var_dump( is_object( $obj ) );



Variant 2)

class ObjArray extends ArrayIterator{
  public function __callOnObject( $calledFunction, $params ){
    switch $calledFunction {
      case "is_array":
        return $this->is_array( $params[0] );
        break;
      case "is_object":
        return $this->is_object( $params[0] );
        break;
      default:
        return $calledFunction( insert_params_irrelevant_how( $params ) );
    }
  }
  public function is_array( $var ){
    return is_array( $this->storage );
  }
  public function is_object( $var ){
    return is_object( $this->storage );
  }
}

$obj = new ObjArray( Array( 1, 2 ) );
var_dump( is_array( $obj ) );
var_dump( is_object( $obj ) );




Expected result:
----------------
Variant 1)

//$obj = new ObjArray( Array( 1, 2 ) );
//var_dump( is_array( $obj ) );
//should translate to var_dump( $obj->is_array( $obj ) );
bool(true)
//var_dump( is_object( $obj ) );
//should translate to var_dump( $obj->is_object( $obj ) );
bool(false)


Variant 2)
//$obj = new ObjArray( Array( 1, 2 ) );
//var_dump( is_array( $obj ) );
//should translate to var_dump( $obj->__callOnObject( "is_array", Array( $obj ) ) );
//swith/case finds function is_array and calls $obj->is_array( $obj );
bool(true)
//var_dump( is_object( $obj ) );
//should translate to var_dump( $obj->__callOnObject( "is_object", Array( $obj ) ) );
//swith/case finds function is_object and calls $obj->is_object( $obj );
bool(false)





Actual result:
--------------
//$obj = new ObjArray( Array( 1, 2 ) );
//var_dump( is_array( $obj ) );
bool(false)
//var_dump( is_object( $obj ) );
bool(true)






Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-08-18 15:49 UTC] email at robertdewilde dot nl
This comes close to the dynamic proxy class problem. It would really make sense to fix this, as people want to use more OOP-style code. Transparent implementing wrapperclasses would be a way to do this, if it would be possible.
 [2010-10-03 18:47 UTC] + at ni-po dot com
This problem would be fixed if PHP allowed casting to other scalar types then strings and casting to arrays.

How it would work internally:
ksort($obj);
// =>
ksort((array) $obj);
// =>
ksort($obj->__cast('array'));

Bug #52807 deals with __toArray / cast to array.
 [2020-03-01 23:10 UTC] cmb@php.net
-Status: Open +Status: Suspended
 [2020-03-01 23:10 UTC] cmb@php.net
This feature certainly needs more discussion about the details,
for which this bug tracker is not appropriate.  Please bring that
forward on the internals mailing list[1].  Thanks!

[1] <https://www.php.net/mailing-lists.php#internals>
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Oct 12 10:01:28 2024 UTC