Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Page 1 of 2 12 LastLast
Results 1 to 15 of 19
  1. #1
    Regular Coder
    Join Date
    Oct 2008
    Posts
    255
    Thanks
    113
    Thanked 0 Times in 0 Posts

    Classes Accessing Outside Info?

    If you set up a class, what all can you access in the class that was created outside the class?

  • #2
    Super Moderator Inigoesdr's Avatar
    Join Date
    Mar 2007
    Location
    Florida, USA
    Posts
    3,642
    Thanks
    2
    Thanked 405 Times in 397 Posts
    Global variables and constants, but if your class is well-designed any dynamic data would usually be passed in via the constructor or setters.

  • #3
    Regular Coder
    Join Date
    Oct 2008
    Posts
    255
    Thanks
    113
    Thanked 0 Times in 0 Posts
    So if I wanted to make a class that processes an email form, I could do:

    PHP Code:
    class goForm
    {

       public function 
    varProcess()
       {

          
    // do something with $_POST array
       
    }

    }

    if (
    $_POST)
    {

       
    $email = new goForm;
       
    $email->varProcess();


    ?

  • #4
    Senior Coder
    Join Date
    Jul 2009
    Location
    South Yorkshire, England
    Posts
    2,318
    Thanks
    6
    Thanked 304 Times in 303 Posts
    $_POST is global, so yes, that would work fine. You'd be better doing:

    Code:
    class goForm
    {
    
       public function varProcess($post)
       {
          // do something with $post array
       }
    
    }
    
    if ($_POST)
    {
    
       $email = new goForm;
       $email->varProcess($_POST);
    
    }
    however, and then you aren't limited to just processing $_POST vars.

  • #5
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,987
    Thanks
    4
    Thanked 2,660 Times in 2,629 Posts
    Quote Originally Posted by MattF View Post
    $_POST is global, so yes, that would work fine. You'd be better doing:

    Code:
    class goForm
    {
    
       public function varProcess($post)
       {
          // do something with $post array
       }
    
    }
    
    if ($_POST)
    {
    
       $email = new goForm;
       $email->varProcess($_POST);
    
    }
    however, and then you aren't limited to just processing $_POST vars.
    Classes are independant of environment, they should be designed to handle any type of data, whether its posted, read from a file, scanned from a database, etc.
    This is where polymorphism really shines, lets do a quick and dirty example:
    PHP Code:
    interface IRequest
    {
        public function 
    getRequest($var);
        public function 
    setRequest($var$val);
    }

    interface 
    IResponse
    {
        public function 
    getResponse($var);
        public function 
    setResponse($var$val);
    }

    // Now we have a class that does stuff:
    class MyClass
    {
        public function 
    doSomething(IRequest $reqIResponse $res)
        {
            
    $res->setResponse('result''Request was: ' $req->getRequest('request'));
        }
    }

    // And a wrapper of some sorts:
    class POSTWrapper implements IRequestIResponse
    {
        private 
    $req;
        private 
    $res;

        public function 
    __construct()
        {
            
    // We'll just go without a pass here
            
    $this->req $_POST;
            
    $this->res = array();
        }

        public function 
    getRequest($var)
        {
            return 
    $this->req[$var];
        }
        public function 
    setRequest($var$val)
        {
            
    $this->req[$var] = $val;
        }
        public function 
    getResponse($var)
        {
            return 
    $this->res[$var];
        }
        public function 
    setResponse($var$val)
        {
            
    $this->res[$var] = $val;
        }

    Usage:
    PHP Code:
    $wrapper = new POSTWrapper(); // Or factory this up, which would look something like:
    // $wrapper = WrapperFactory::createWrapper('POST'); for example
    $class = new MyClass();
    $class->doSomething($wrapper);

    print_r($wrapper); 
    (BTW, I have no idea if the above actually works; I'll be needing to buy a new home PC soon :'()

    Combine the wrapper into a factory and you'll see some real power. Swap out a POSTWrapper for a FILEWrapper instead and you can read/write from files instead of request/response styles through post. Only thing that changes is the $wrapper call, everything else would be good to go (assuming its been programmed of course hah).
    Notice I did use the _POST superglobal in the POSTWrapper class, but with this example it suits it; there is no reason for me to pass a superglobal into a class who's sole purpose is to manage that type of data (_POST in this example). Although there is absolutely nothing wrong with it either, the reason why I use this approach is this way the wrapper itself doesn't need to accept a parameter to it, which will reduce the complication of expanding the system to cover things like file handling and whatnots.
    PHP Code:
    header('HTTP/1.1 420 Enhance Your Calm'); 

  • #6
    Regular Coder
    Join Date
    Oct 2008
    Posts
    255
    Thanks
    113
    Thanked 0 Times in 0 Posts
    This probably sounds silly, but what is an interface used for? I've just begun learning about classes. I had no idea there was such a thing as Interfaces.

  • #7
    Senior Coder Dormilich's Avatar
    Join Date
    Jan 2010
    Location
    Behind the Wall
    Posts
    3,248
    Thanks
    12
    Thanked 340 Times in 336 Posts
    Quote Originally Posted by Fou-Lu View Post
    (BTW, I have no idea if the above actually works; I'll be needing to buy a new home PC soon :'()
    I’d say, second argument missing in MyClass::doSomething()

    Interfaces (simplified): they allow you to specify, that a certain class or object has the methods you want to use later.
    PHP Code:
    class MyClass
    {
    # if $req has no (public) getRequest() and setRequest() method, an error will be thrown
    # if $res has no (public) getResponse() and setResponse() method, an error will be thrown
        
    public function doSomething(IRequest $reqIResponse $res)
        {
            
    $res->setResponse('result''Request was: ' $req->getRequest('request'));
        }

    PHP Code:
    # this class must at least have/define the methods specified in the Interfaces
    class POSTWrapper implements IRequestIResponse 
    The computer is always right. The computer is always right. The computer is always right. Take it from someone who has programmed for over ten years: not once has the computational mechanism of the machine malfunctioned.
    André Behrens, NY Times Software Developer

  • Users who have thanked Dormilich for this post:

    Joseph Witchard (03-04-2010)

  • #8
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,987
    Thanks
    4
    Thanked 2,660 Times in 2,629 Posts
    Quote Originally Posted by Dormilich View Post
    I’d say, second argument missing in MyClass::doSomething()
    Hah, yes indeed, the above example of mine should have been:
    PHP Code:
    $class->doSomething($wrapper$wrapper); 
    I'm a strong believer that the two values should exist, one for the request and one for the response. The post wrapper itself does handle both, but should be considered independant for expansion purposes.

    Interfaces are a contract, they are supposed to guarentee that methods exist within a class. So with this signature on a class method:
    PHP Code:
    public function doSomething(IRequest $reqIResponse $res
    I'm supposed to be guarenteed that $req has an publically accessable method called getRequest.

    However, PHP fails when it comes to interface handling, you can actually get around an interface as outlined in the bug report I filed here: http://bugs.php.net/bug.php?id=48376
    This unfortunately exists up to 5.3.0 for certain (though I'm not 100% certain if its been corrected with the 5.3.1), and 6.0.0 Dev beta. Since it allows you to decay the scope of you're interface, this results in intermittent runtime errors instead of compilation errors. It is indicated by the php team that this is not a bug, which is total bs I'm afraid.
    Too bad too, interfaces are probably the single most powerful tool when it comes to OOP since it is the only way in PHP (and most other OO languages I've used, except for C++) to control multiple inheritance.
    PHP Code:
    header('HTTP/1.1 420 Enhance Your Calm'); 

  • #9
    Senior Coder Dormilich's Avatar
    Join Date
    Jan 2010
    Location
    Behind the Wall
    Posts
    3,248
    Thanks
    12
    Thanked 340 Times in 336 Posts
    Quote Originally Posted by Fou-Lu View Post
    However, PHP fails when it comes to interface handling, you can actually get around an interface as outlined in the bug report I filed here: http://bugs.php.net/bug.php?id=48376
    I didn’t understand that bug. I always thought that calling __construct() happens, whenever the object is created through new*, regardless of public/protected/private. that only matters, if you explicitly access it as ClassName::__construct() or parent::__construct(). And I can’t spot the relation to Interfaces …

    * that’s why the Singleton Pattern explicitly declares empty constructors.
    Last edited by Dormilich; 03-03-2010 at 02:41 PM.
    The computer is always right. The computer is always right. The computer is always right. Take it from someone who has programmed for over ten years: not once has the computational mechanism of the machine malfunctioned.
    André Behrens, NY Times Software Developer

  • #10
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,987
    Thanks
    4
    Thanked 2,660 Times in 2,629 Posts
    Yes, __construct or a method with the same name as the class will always be called when using new if available. Otherwise, it will always look for its parent. Using a non-public construct will always throw an error on a new call. In PHP, I'm fairly certain that even constructors cannot be decayed from inherited methods, though they are intending us to be able to do this in the future. I'm pretty certain offhand that inherited classes can however redeclare the __construct signature. Singletons should use private / protected constructors since you cannot reassign $this (you could get around this issue if you could assign $this = self::$instance; for example). Otherwise, the singleton pattern will not allow you to act on a single instance of an object since each new will create a new instance of that class.

    The first example was showing scope decay, the second shows the decay of interfaced methods as well - look lower to see the interfaced example (I'll include it here):

    PHP Code:
    interface IInterface
    {
        public function 
    test();
    }

    class 
    Grandfather
    {
        private function 
    __construct()
        {
        }

        private function 
    test() //<-- This allows us to decay
        
    {
            
    printf("%s\n"__METHOD__);
        }
    }

    class 
    Father extends Grandfather implements IInterface
    {
        public function 
    __construct()
        {
            
    printf("%s\n"__METHOD__);
        }

        public function 
    test() // <-- Required by IInterface
        
    {
            
    printf("%s\n"__METHOD__);
        }
    }

    class 
    Son extends Father
    {
        protected function 
    __construct()
        {
            
    parent::__construct();
            
    printf("%s\n"__METHOD__);
        }

        public static function 
    createInstance()
        {
            return new 
    self;
        }

        protected function 
    test() // <-- This is not right, you cannot decay a parent scope
        
    {
            
    parent::test();
            
    printf("%s\n"__METHOD__);
        }
    }


    class 
    CorrectScope implements IInterface
    {
        public function 
    __construct()
        {
            
    printf("%s\n"__METHOD__);
        }
        
        public function 
    test()
        {
            
    printf("%s\n"__METHOD__);
        }
    }

    $t Son::createInstance();
    var_dump($t);
    if (
    $t instanceof IInterface)
    {
        print(
    "\$t is an IInterface, check test:\n");
        
    // Fatal error on an interface call
        
    printf("Results of \$t->test() = %s\n"$t->test());

    When run, $t indicates that it is an interface of type IInterface which should guarentee that a method called test exists within it. However, attempting to call this method on this interfaced class will throw an uncatchable fatal error.

    I have a much better version of this with a runner and stuff if you want to see, but you'll need to wait until I at least get a new monitor at home :P
    PHP Code:
    header('HTTP/1.1 420 Enhance Your Calm'); 

  • #11
    Senior Coder Dormilich's Avatar
    Join Date
    Jan 2010
    Location
    Behind the Wall
    Posts
    3,248
    Thanks
    12
    Thanked 340 Times in 336 Posts
    Quote Originally Posted by Fou-Lu View Post
    Otherwise, it will always look for its parent.
    that’s news to me.

    Quote Originally Posted by Fou-Lu View Post
    When run, $t indicates that it is an interface of type IInterface which should guarentee that a method called test exists within it. However, attempting to call this method on this interfaced class will throw an uncatchable fatal error.
    what I find strange here is that the error is not a parse error (overwriting public with proteced), although you could argue, that the parent’s method still conforms to the interface, but due to overwriting it’s not publicly accessible.
    The computer is always right. The computer is always right. The computer is always right. Take it from someone who has programmed for over ten years: not once has the computational mechanism of the machine malfunctioned.
    André Behrens, NY Times Software Developer

  • #12
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,987
    Thanks
    4
    Thanked 2,660 Times in 2,629 Posts
    Yes exactly!
    The error should be a parse error at compile time, not runtime. Extending a base class cannot decay the scope of a parent method, otherwise its not really an extension on it since it then defeats the purpose of conforming to the dynamic binding model (Son is typeof Father, so must include all methods expected of Father). The error should be occuring at linking and not at runtime, but as shown it will trigger at runtime instead which of course results in intermittent uncatachable fatal errors.
    You'll also notice if you take the grandfather class out of the equation completely, that the code would run as expected. This only exists in a Grandfather > Father > Son relationship.

    As for the constructor:
    Note: Parent constructors are not called implicitly if the child class defines a constructor. In order to run a parent constructor, a call to parent::__construct() within the child constructor is required.
    parent::__construct will be called implicitly if extending a parent class and no constructor is defined for the child. Otherwise, unlike languages like Java, PHP requires us to explicitly call the parent (java implicilty calls the parent constructor, and if overriden to use an overloaded constructor it must be the first line). I actually really like this feature of PHP. Eventually we'll be able to control the scope on this too; that I am looking forward to.
    PHP Code:
    header('HTTP/1.1 420 Enhance Your Calm'); 

  • #13
    Senior Coder Dormilich's Avatar
    Join Date
    Jan 2010
    Location
    Behind the Wall
    Posts
    3,248
    Thanks
    12
    Thanked 340 Times in 336 Posts
    Quote Originally Posted by Fou-Lu View Post
    parent::__construct will be called implicitly if extending a parent class and no constructor is defined for the child.
    „Man kann alt werden, wie ’ne Kuh und lernt immernoch dazu.“ (german proverb, directly translated as "you can get as old as a sphinx, but you can still learn new things")
    Last edited by Dormilich; 03-04-2010 at 02:10 PM. Reason: making the translation rhyme
    The computer is always right. The computer is always right. The computer is always right. Take it from someone who has programmed for over ten years: not once has the computational mechanism of the machine malfunctioned.
    André Behrens, NY Times Software Developer

  • #14
    Regular Coder
    Join Date
    Oct 2008
    Posts
    255
    Thanks
    113
    Thanked 0 Times in 0 Posts
    So should I or should I not use interfaces (provided I come to a place where they would be useful)?

  • #15
    Senior Coder Dormilich's Avatar
    Join Date
    Jan 2010
    Location
    Behind the Wall
    Posts
    3,248
    Thanks
    12
    Thanked 340 Times in 336 Posts
    you should.

    but you should also be aware, where there could be problems, but that’s rather rare.
    The computer is always right. The computer is always right. The computer is always right. Take it from someone who has programmed for over ten years: not once has the computational mechanism of the machine malfunctioned.
    André Behrens, NY Times Software Developer


  •  
    Page 1 of 2 12 LastLast

    Posting Permissions

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