SitePoint Sponsor

User Tag List

Results 1 to 13 of 13
  1. #1
    SitePoint Addict bronze trophy
    Join Date
    Apr 2013
    Location
    Ithaca
    Posts
    338
    Mentioned
    6 Post(s)
    Tagged
    1 Thread(s)

    cloning objects results in 500 internal server error...

    Anyone else experiencing the same problem? I got it whenever I try to clone objects, and never understood why this keeps happening.

    Could this be the cause of error? All my classes extend from the root Object class, which has this __clone() method:
    PHP Code:
        /**
         * Magic method __clone() for Object Class, returns a copy of Object with additional operations.
         * @access public
         * @return Object
         */
        
    public function __clone(){
            return clone 
    $this;
        } 
    Maybe this is redundant, but still it does not explain why a 500 Internal Server Error is triggered. I thought it might throw a fatal error if the syntax is incorrect or that the operation is invalid. *sigh*

  2. #2
    Hosting Team Leader silver trophybronze trophy
    cpradio's Avatar
    Join Date
    Jun 2002
    Location
    Ohio
    Posts
    4,808
    Mentioned
    141 Post(s)
    Tagged
    0 Thread(s)
    Do you have a real basic example of a class that inherits this Object class that performs the 500 internal server error? I'd be willing to try it out on one of my servers if you have reproducible code (otherwise, I'd just be guessing at what the problem may be...).
    Be sure to congratulate xMog on earning April's Member of the Month
    Go ahead and blame me, I still won't lose any sleep over it
    My Blog | My Technical Notes

  3. #3
    SitePoint Mentor bronze trophy
    fretburner's Avatar
    Join Date
    Apr 2013
    Location
    Brazil
    Posts
    1,256
    Mentioned
    32 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by Hall of Famer View Post
    Anyone else experiencing the same problem? I got it whenever I try to clone objects, and never understood why this keeps happening.

    Could this be the cause of error? All my classes extend from the root Object class, which has this __clone() method:
    PHP Code:
        /**
         * Magic method __clone() for Object Class, returns a copy of Object with additional operations.
         * @access public
         * @return Object
         */
        
    public function __clone(){
            return clone 
    $this;
        } 
    Maybe this is redundant, but still it does not explain why a 500 Internal Server Error is triggered. I thought it might throw a fatal error if the syntax is incorrect or that the operation is invalid. *sigh*
    According to the manual:
    Once the cloning is complete, if a __clone() method is defined, then the newly created object's __clone() method will be called, to allow any necessary properties that need to be changed.
    This being the case, if you call clone $this; in your __clone method, isn't it going to end up in some kind of infinite loop?

  4. #4
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    988
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    fretburner is spot on. __clone() is called AFTER the object has been cloned, not before. __clone will be called on the newly created object, not the object you're cloning before it gets cloned so every time you clone an object, it gets cloned again (And then that gets cloned, and that, ad infinitum)

  5. #5
    SitePoint Addict bronze trophy
    Join Date
    Apr 2013
    Location
    Ithaca
    Posts
    338
    Mentioned
    6 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by TomB View Post
    fretburner is spot on. __clone() is called AFTER the object has been cloned, not before. __clone will be called on the newly created object, not the object you're cloning before it gets cloned so every time you clone an object, it gets cloned again (And then that gets cloned, and that, ad infinitum)
    So you are saying that what I am doing is actually creating an infinite loop? Oh my...

  6. #6
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    988
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    Exactly. And I'm fairly sure the return vale of __clone is never used at all.

  7. #7
    SitePoint Addict bronze trophy
    Join Date
    Apr 2013
    Location
    Ithaca
    Posts
    338
    Mentioned
    6 Post(s)
    Tagged
    1 Thread(s)
    I see, I thought __clone() works like Java's clone() method on the object you operate. Thanks for letting me know, I will run another test again and hopefully wont run into another 500 Internal Server Error.

    Update:
    It wont work even if I remove 'return clone $this;' from the script, still 500 Internal Server error, and the speed is rather fast so I dont think it has anything to do with infinite loop this time. Weird, maybe I should try removing the magic method __clone() for good? Even an empty __clone() doesnt fix the issue.

    Update 2:
    It works if I completely get rid of the __clone() method from the interface that specifes a clonable contract. Weird though, is the presence of method __clone() in the interface causing all the trouble?

  8. #8
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    988
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    Hmm, strange. Can you post a minimalist example, one interface, one class that implements it and the code you're using to clone the object?

    edit: this works for me:

    PHP Code:
    <?php 

    interface {
        public function 
    __clone();
    }

    class 
    implements {
        public function 
    __clone() {
            
        }
    }

    $b = new B;
    $b2 = clone $b;

    var_dump($b2);

    ?>

  9. #9
    SitePoint Addict bronze trophy
    Join Date
    Apr 2013
    Location
    Ithaca
    Posts
    338
    Mentioned
    6 Post(s)
    Tagged
    1 Thread(s)
    I have no idea tbh, removing __clone() method completely from both the abstract root class and the interface will work, but leaving a marker __clone() method always result in 500 internal server error. Perhaps the method __clone() is not working properly on my server?

  10. #10
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    988
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    No, it's almost certainly something else. Can you post a cut down version of your code? Just the class chain, and __clone methods (Whereever they are)

  11. #11
    SitePoint Addict bronze trophy
    Join Date
    Apr 2013
    Location
    Ithaca
    Posts
    338
    Mentioned
    6 Post(s)
    Tagged
    1 Thread(s)
    Well the class hierachy is a bit complex, but anyway I will give a try:

    Interface: Objective
    PHP Code:
    <?php

    namespace Resource\Native;

    /**
     * The Objective Interface, it is the interface that all Mysidia classes should implement minus a few special cases.
     * It defines a standard interface for Mysidia Objects, the root class Object also implements this interface.
     * This interface is very useful for classes that extend from PHP's built-in classes, as they cannot extend from root Object Class.
     * By Implementing Objective interface, objects of the specific class can be used in Collections Framework.
     * @category Resource
     * @package Native
     * @author Hall of Famer 
     * @copyright Mysidia Adoptables Script
     * @link http://www.mysidiaadoptables.com
     * @since 1.3.3
     * @todo Not much at this point.
     *
     */
     
    interface Objective{

        
    /**
         * The equals method, checks whether target object is equivalent to this one.
         * @param Objective  $object     
         * @access public
         * @return Boolean
         */
        
    public function equals(Objective $object);
        
        
    /**
         * The getClassName method, returns class name of an instance. 
         * The return value may differ depending on child classes. 
         * @access public
         * @return String
         */    
        
    public function getClassName();
        
        
    /**
         * Magic method __clone() for Object Class, returns a copy of Object with additional operations.
         * @access public
         * @return Object
         */
        
    public function __clone();
        
        
    /**
         * Magic method to_String() for Object class, returns object information.
         * @access public
         * @return String
         */    
        
    public function __toString(); 
    }
    ?>
    Abstract Class: Object
    PHP Code:
    <?php

    namespace Resource\Native;

    /**
     * The Abstract Object Class, root of all Mysidia library files.
     * Contrary to Java's Object root class, this one is abstract.
     * For this reason, one cannot instantiate an object of this class.
     * @category Resource
     * @package Native
     * @author Hall of Famer 
     * @copyright Mysidia Adoptables Script
     * @link http://www.mysidiaadoptables.com
     * @since 1.3.2
     * @todo Not much at this point.
     * @abstract
     *
     */

    abstract class Object implements Objective{
      
        
    /**
         * Constructor of Object Class, which simply serves as a marker for child classes.
         * @access public
         * @return Void
         */
        
    public function __construct(){

        }

        
    /**
         * Destructor of Object Class, which simply serves as a marker for child classes.
         * @access public
         * @return Void
         */
        
    public function __destruct(){

        }

        
    /**
         * Magic method __clone() for Object Class, returns a copy of Object with additional operations.
         * @access public
         * @return Object
         */
        
    public function __clone(){

        }
     
        
    /**
         * The getClassName method, returns class name of an instance. 
         * It is alias to getClass method, its existence is for backward compatibility.
         * @access public
         * @return String
         */
        
    public function getClassName(){
            return 
    $this->getClass();
        }
     
        
    /**
         * The equals method, checks whether target object is equivalent to this one.
         * @param Objective  $object     
         * @access public
         * @return Boolean
         */
        
    public function equals(Objective $object){
            return (
    $this == $object);
        } 

        
    /**
         * The hashCode method, returns the hash code for the very Object.
         * @access public
         * @return Int
         */            
        
    public function hashCode(){
            return 
    hexdec(spl_object_hash($this));
        }

        
    /**
         * The hasMethod method, examines if the object has a certain method.
         * @param String  $method
         * @access public
         * @return Boolean
         */    
        
    public function hasMethod($method){
            return 
    method_exists($this$method);
        }

        
    /**
         * The hasProperty method, finds if the object contains a certain property.
         * @param String  $property
         * @access public
         * @return Boolean
         */
        
    public function hasProperty($property){
            return 
    property_exists($this$property);
        }
        
        
    /**
         * The serialize method, serializes an object into string format.
         * A serialized string can be stored in Constants, Database and Sessions.
         * @access public
         * @return String
         */
        
    public function serialize(){
            return 
    serialize($this);
        }
       
        
    /**
         * The unserialize method, decode a string to its object representation.
         * This method can be used to retrieve object info from Constants, Database and Sessions.
         * @param String  $string
         * @access public
         * @return String
         */
        
    public function unserialize($string){
            return 
    unserialize($string);
        }    
       
        
    /**
         * Magic method __toString() for Object class, returns object information.
         * @access public
         * @return String
         */
        
    public function __toString(){
            return 
    get_class($this);
        }    
    }
    ?>
    Concrete Class: Boolean(just an example, the real subclasses are way too long for posting here)
    PHP Code:
    <?php

    namespace Resource\Native;
    use 
    Exception;

    /**
     * The Boolean Class, extending the root Object class.
     * This class serves as a wrapper class for primitive data type boolean.
     * It is a final class, no child class shall derive from Boolean.
     * @category Resource
     * @package Native
     * @author Hall of Famer 
     * @copyright Mysidia Adoptables Script
     * @link http://www.mysidiaadoptables.com
     * @since 1.3.2
     * @todo Not much at this point.
     * @final
     *
     */

    final class Boolean extends Object{
          
        
    /**
         * Size constant, specifies the size a boolean value occupies.
        */
        
    const Size 8;
        
        
    /**
         * BooleanTrue constant, defines the True value for Boolean.
        */
        
    const BooleanTRUE TRUE;
        
        
    /**
         * BooleanFALSE constant, defines the False value for Boolean.
        */
        
    const BooleanFALSE FALSE;
        
        
    /**
         * The value property, which stores the primitive value for this Boolean object. 
         * @access private
         * @var Boolean
        */
        
    private $value;
          
        
    /**
         * Constructor of Boolean Class, initializes the Boolean wrapper class.
         * If supplied argument is not of boolean type, type casting will be converted.
         * @param Any  $param
         * @access public
         * @return Void
         */
        
    public function __construct($param){
            if(!
    is_bool($param)) $param = (boolean)$param;
            
    $this->value $param;
        }

        
    /**
         * The getValue method, returns the primitive boolean value.
         * @access public
         * @return Boolean
         */
        
    public function getValue(){
            return 
    $this->value;
        }
        
        
    /**
         * The compareTo method, compares a boolean object to another.
         * @param Objective  $target     
         * @access public
         * @return Int
         */
        
    public function compareTo(Objective $target){
            if(!(
    $target instanceof Boolean)) throw new Exception("Supplied argument must be a boolean value!");
            return (
    $this->equals($target))?0:($this->value : -1);
        }

        
    /**
         * Magic method to_String() for Boolean class, casts boolean value into string.
         * @access public
         * @return String
         */
        
    public function __toString(){
            return (string)
    $this->value;
        }
        
        
    /**
         * Magic method __invoke() for Boolean class, it returns the primitive data value for manipulation.
         * @access public
         * @return Number
         */
        
    public function __invoke(){
            return 
    $this->value;  
        }
    }
    ?>

  12. #12
    SitePoint Guru bronze trophy TomB's Avatar
    Join Date
    Oct 2005
    Location
    Milton Keynes, UK
    Posts
    988
    Mentioned
    9 Post(s)
    Tagged
    2 Thread(s)
    PHP Code:
    <?php  
    interface Objective{

        
    /**
         * The equals method, checks whether target object is equivalent to this one.
         * @param Objective  $object     
         * @access public
         * @return Boolean
         */
        
    public function equals(Objective $object);
        
        
    /**
         * The getClassName method, returns class name of an instance. 
         * The return value may differ depending on child classes. 
         * @access public
         * @return String
         */    
        
    public function getClassName();
        
        
    /**
         * Magic method __clone() for Object Class, returns a copy of Object with additional operations.
         * @access public
         * @return Object
         */
        
    public function __clone();
        
        
    /**
         * Magic method to_String() for Object class, returns object information.
         * @access public
         * @return String
         */    
        
    public function __toString(); 
    }



    abstract class 
    Object implements Objective{

        
    /**
         * Constructor of Object Class, which simply serves as a marker for child classes.
         * @access public
         * @return Void
         */
        
    public function __construct(){

        }

        
    /**
         * Destructor of Object Class, which simply serves as a marker for child classes.
         * @access public
         * @return Void
         */
        
    public function __destruct(){

        }

        
    /**
         * Magic method __clone() for Object Class, returns a copy of Object with additional operations.
         * @access public
         * @return Object
         */
        
    public function __clone(){

        }

        
    /**
         * The getClass method, returns class name of an instance.
         * The return value may differ depending on child classes.
         * @access public
         * @return String
         */
        
    public function getClass(){
            return 
    get_class($this);
        }

        
    /**
         * The getClassName method, returns class name of an instance.
         * It is alias to getClass method, its existence is for backward compatibility.
         * @access public
         * @return String
         */
        
    public function getClassName(){
            return 
    $this->getClass();
        }

        
    /**
         * The equals method, checks whether target object is equivalent to this one.
         * @param Objective  $object
         * @access public
         * @return Boolean
         */
        
    public function equals(Objective $object){
            return (
    $this == $object);
        }

        
    /**
         * The hashCode method, returns the hash code for the very Object.
         * @access public
         * @return Int
         */
        
    public function hashCode(){
            return 
    hexdec(spl_object_hash($this));
        }

        
    /**
         * The hasMethod method, examines if the object has a certain method.
         * @param String  $method
         * @access public
         * @return Boolean
         */
        
    public function hasMethod($method){
            return 
    method_exists($this$method);
        }

        
    /**
         * The hasProperty method, finds if the object contains a certain property.
         * @param String  $property
         * @access public
         * @return Boolean
         */
        
    public function hasProperty($property){
            return 
    property_exists($this$property);
        }

        
    /**
         * The serialize method, serializes an object into string format.
         * A serialized string can be stored in Constants, Database and Sessions.
         * @access public
         * @return String
         */
        
    public function serialize(){
            return 
    serialize($this);
        }
         
        
    /**
         * The unserialize method, decode a string to its object representation.
         * This method can be used to retrieve object info from Constants, Database and Sessions.
         * @param String  $string
         * @access public
         * @return String
         */
        
    public function unserialize($string){
            return 
    unserialize($string);
        }
         
        
    /**
         * Magic method __toString() for Object class, returns object information.
         * @access public
         * @return String
         */
        
    public function __toString(){
            return 
    get_class($this);
        }
    }


    final class 
    Boolean extends Object{

        
    /**
         * Size constant, specifies the size a boolean value occupies.
         */
        
    const Size 8;

        
    /**
         * BooleanTrue constant, defines the True value for Boolean.
         */
        
    const BooleanTRUE TRUE;

        
    /**
         * BooleanFALSE constant, defines the False value for Boolean.
         */
        
    const BooleanFALSE FALSE;

        
    /**
         * The value property, which stores the primitive value for this Boolean object.
         * @access private
         * @var Boolean
         */
        
    private $value;

        
    /**
         * Constructor of Boolean Class, initializes the Boolean wrapper class.
         * If supplied argument is not of boolean type, type casting will be converted.
         * @param Any  $param
         * @access public
         * @return Void
         */
        
    public function __construct($param){
            if(!
    is_bool($param)) $param = (boolean)$param;
            
    $this->value $param;
        }

        
    /**
         * The getValue method, returns the primitive boolean value.
         * @access public
         * @return Boolean
         */
        
    public function getValue(){
            return 
    $this->value;
        }

        
    /**
         * The compareTo method, compares a boolean object to another.
         * @param Objective  $target
         * @access public
         * @return Int
         */
        
    public function compareTo(Objective $target){
            if(!(
    $target instanceof Boolean)) throw new Exception("Supplied argument must be a boolean value!");
            return (
    $this->equals($target))?0:($this->value : -1);
        }

        
    /**
         * Magic method to_String() for Boolean class, casts boolean value into string.
         * @access public
         * @return String
         */
        
    public function __toString(){
            return (string)
    $this->value;
        }

        
    /**
         * Magic method __invoke() for Boolean class, it returns the primitive data value for manipulation.
         * @access public
         * @return Number
         */
        
    public function __invoke(){
            return 
    $this->value;
        }
    }



    $bool = new Boolean(true);

    $bool2 = clone $bool;

    var_dump($bool2);

    This is a slightly slimmed down version of what you posted. It works fine for me, can you run that script and see if you have a problem?



    However, I will say this despite it being off topic: Trying to use scalars as objects in PHP is a very bad idea until the PHP developers give us a way to manage it better.

  13. #13
    SitePoint Addict bronze trophy
    Join Date
    Apr 2013
    Location
    Ithaca
    Posts
    338
    Mentioned
    6 Post(s)
    Tagged
    1 Thread(s)
    Yeah you are right, it is working. Guess it only happens to certain classes though, its getting more complex than I thought. Due to the complexity of the code that generates 500 Internal Server Error, tracking down this problem is quite difficult. *sigh* Thank you for being this patient with me.

    And yeah, I agree that the way PHP is currently handing primitive/scalar types makes them really hard to work as objects. These are wrapper class/object used only in collections, since I've designed a PHP Collection Framework(PCF) myself a few months ago, and these collections only accept objects. For this reason, scalars must be wrapped/boxed before they can be sent to collection objects.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •