SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 41
  1. #1
    SitePoint Addict agentforte's Avatar
    Join Date
    May 2007
    Location
    Toronto, ON, Canada
    Posts
    213
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Question Calling methods from another class?

    Hi,
    Would the following work?
    I have two separate classes, and I want to call a method in the second class from the first.

    for example, one class deals with validation, and one deals with errors. If certain critical events happen during validation, I want to have methods in the error class executed automatically (without affecting the page that uses the validation class)

    PHP Code:
    class validate {

    function 
    one($string) {
    // retrieve something from DB, saved in $DBstuff, if error saved in $err
    if ($DBstuff == $string) {
    // GREAT!

    if (isset(
    $err)) {
    $warn = new error($);
    }
    }


    class 
    error {
    var 
    $err;
    function 
    error($err) {
     
    $this->err=$err;
     
    $this->log();
    }

    function 
    log(){
     
    // log error
     
    $this->email()
    }

    funtion email() {
    // email error
    }


  2. #2
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You don't call methods on a class - You call it on an object, and an object is an instance of a class. To call the methods of an object, you must first obtain a variable, referencing it.
    For example:
    PHP Code:
    class Foo
    {
      function 
    doStuff() {
        echo 
    "doStuff called";
        
    $bar = new Bar();
        
    $bar->cux();
      }
    }

    class 
    Bar
    {
      function 
    cux() {
        echo 
    "cux called";
      }
    }

    // test
    $foo = new Foo();
    $foo->doStuff(); 

  3. #3
    SitePoint Addict agentforte's Avatar
    Join Date
    May 2007
    Location
    Toronto, ON, Canada
    Posts
    213
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks!

  4. #4
    SitePoint Wizard Hammer65's Avatar
    Join Date
    Nov 2004
    Location
    Lincoln Nebraska
    Posts
    1,160
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Actually there is such a thing as class methods in PHP, even in 4.x. This would be called, a static call.

    For instance I have a utility class as part of a custom framework solely for the purpose of encapsulating basic utility functions that are available to the framework. I call these functions statically with the following syntax.

    PHP Code:
    utility::setNoCache(); 
    This function sends all the headers necessary to tell a browser not to cache a page.

    if you don't need a class, to act as an object but you need the functionality of a specific method, call that method statically. In PHP 5.x you have to explicitly declare a method static, in order to this.

    http://www.phpbuilder.com/manual/en/...op5.static.php

  5. #5
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Static methods are possible, but are generally a bad idea. I suggest that you ignore this feature to begin with, and get a feeling for how to use objects.

  6. #6
    SitePoint Wizard Hammer65's Avatar
    Join Date
    Nov 2004
    Location
    Lincoln Nebraska
    Posts
    1,160
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That's a new one on me, Basic OOP theory allows for class members and methods, why would you consider them bad practice when they are available in what OOP purists consider true object oriented languages.

  7. #7
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Hammer65 View Post
    That's a new one on me, Basic OOP theory allows for class members and methods, why would you consider them bad practice when they are available in what OOP purists consider true object oriented languages.
    Because they introduce hard coupling. When you call a method on an object, the actual function invoked, is determined at run time. If you call a method statically, the function is determined at compile (interpret) time. To a far extend, the power of objects are the late binding, they enable.

    There isn't really any practical difference between a floating function and a static method -- It's purely a syntactical matter. There are cases, where it is easier to use a static method, but it's always a trade off on the expense of flexibility. As a rule of thumb, they are a sign of bad design.

  8. #8
    SitePoint Wizard Hammer65's Avatar
    Join Date
    Nov 2004
    Location
    Lincoln Nebraska
    Posts
    1,160
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The use I suggested isn't much different than using System.out.println() in Java. You don't make an instance of System.out you invoke it's class methods as basic utility routines.

    Encapsulation being of a higher importance here than any interaction of multiple member values and methods.

    In other words, if I have some data, the nature of which is simple enough, that it doesn't need special code to work with and manipulate, I might store it in an associative array instead of an object, since it's simple nature doesn't require special methods and scope to be applied to it directly.

    If I have a collection of routines that as a group do not explicitly need to communicate or work as one, I would still need to encapsulate those functions in a specific scope, if I wish to avoid naming collisions and preserve the OOP nature of the framework. There would however be no real functional use in producing an instance of that class.

    By doing this you don't mix proceedural and OOP by including long function pages in the main scope, that can cause naming collisions with other code.

    If for instance a client asks that this or that third party RSS reader or Ad rotator, etc. be included on a page, I'm not as concerned about functions in that third party add on colliding with mine. Encapsulation is the single most important OOP feature for web applications over all others for that reason.

    In OOP desktop software development the issues are much different.

  9. #9
    SitePoint Addict agentforte's Avatar
    Join Date
    May 2007
    Location
    Toronto, ON, Canada
    Posts
    213
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Question OOP for custom application

    Quote Originally Posted by kyberfabrikken View Post
    ...There are cases, where it is easier to use a static method, but it's always a trade off on the expense of flexibility ...they are a sign of bad design.
    Aww man! and I was hoping that my design was good. heh heh.

    On a serious note, I have a simple function that takes an error message, and the type of error message as arguments. It simply logs errors in a database, and if either a) it is a specific type of error, or b) there is an error saving to the database, it will send me an email with details.

    Forgive me for being a bit numb. I have only been learning php for the past 3 months. Can you give any examples where a floating function provides a benefit over a static method?

    The only other thing that I would add to this class is a return value that gives a message to the user if all error reporting methods fail, asking them to send me an email and report the problem, but I believe this can be done statically too.

    Coming from an engineering background, I am really interested in understanding the nuances. Now that I am programming more complex functionality in my website, how do I determine the best approach for the same result?

    Keep in mind, I am building a single website for a business idea I have been developing, I am not a web developer. I want it to be very maintainable, not necessarily reusable. It is a custom application.

    Your feedback is great!

    -Frank

  10. #10
    SitePoint Addict agentforte's Avatar
    Join Date
    May 2007
    Location
    Toronto, ON, Canada
    Posts
    213
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Wow,

    That is exactly what I was looking for. Thanks Hammer65.
    I was thinking something along those lines, and for a small while I thought of just having a list of functions as an include. I opted for OOP since it allowed me to generate webpages, perform validation, and do some more complex work efficiently.

    The other reason was to keep the code separate and organized (also preventing conflicts with other code that might be specific to one of the pages or a third party program)
    Last edited by agentforte; Aug 2, 2007 at 08:59. Reason: one more point added

  11. #11
    SitePoint Wizard Hammer65's Avatar
    Join Date
    Nov 2004
    Location
    Lincoln Nebraska
    Posts
    1,160
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    In your case it might not make a difference, but with a function sitting out in the main scope, you have the possibility of colliding with the name of another function.

    Say for instance you have a function called print_err to print out errors. Then you decide to include some third party PHP based software that does something you want on your site. If that code also has a function called print_err within it, you will have a naming collision and PHP will throw errors.

    This can happen more than you might think. PHP doesn't support a package scope, but it does support the class scope. If you encapsulate that function along with others in a class, they will be shielded from any naming collisions with other code.

    In my work, I do a lot of integrating of different software with my own code to get the functionality a client is looking for. That encapsulation is important in situations like that.

  12. #12
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Hammer65 View Post
    The use I suggested isn't much different than using System.out.println() in Java. You don't make an instance of System.out you invoke it's class methods as basic utility routines.
    If a method calls directly to System.out.println(), then you have a problem reusing the function in a different context. If for example, you used wanted to reuse the code in a GUI application instead, and have the output routed to a textfield, you'd have to change the calls to System.out. If you had instead passed an instance, you could just pass a different one.

    Quote Originally Posted by Hammer65 View Post
    In other words, if I have some data, the nature of which is simple enough, that it doesn't need special code to work with and manipulate, I might store it in an associative array instead of an object, since it's simple nature doesn't require special methods and scope to be applied to it directly.
    PHP is a multi-paradigm language. It makes it natural to mix procedural code with object oriented code. My advice implied that you aim to write object oriented code, but of course, if you mix the two with each other, a static method is an option. Personally, I prefer floating functions in those cases, but I rarely use a procedural style anyway.

    Quote Originally Posted by Hammer65 View Post
    By doing this you don't mix proceedural and OOP by including long function pages in the main scope, that can cause naming collisions with other code.
    The risk of naming collision is the same in these two cases:
    PHP Code:
    Foobar::DoStuff(); 
    PHP Code:
    foobar_dostuff(); 
    Quote Originally Posted by agentforte View Post
    Forgive me for being a bit numb. I have only been learning php for the past 3 months. Can you give any examples where a floating function provides a benefit over a static method?
    I'm using "floating function" for describing a regular function, not declared in a class. A function, declared on a class, which is called on an object (an instance of that class), is a method. From your question, I assume, that you're asking about what benefit there qould be of replacing a static method or floating function with a dynamic method.

    Basically, the benefit is, that the code, which logs the error, doesn't get to decide what happens with the error. Take this example:
    PHP Code:
    class Person
    {
      public 
    $name;
     
      function 
    validate($logger) {
        if (
    preg_match('/^[a-zA-Z]+$/'$this->name)) {
          
    $logger->setError("The name is invalid");
        }
      }
    }

    class 
    DebugErrorLogger
    {
      function 
    setError($message) {
        echo 
    $message "\n";
      }
    }

    $logger = new DebugErrorLogger();
    $test = new Person();
    $test->validate($logger); 
    We the Person class has no knowledge about the DebugErrorLogger class. The only thing it knows is, that it gets an object, which has a setError() method. During development, it may be convenient to use this simple logger, which just echoes the errors out to the console. Later, in the production environment, you could then replace the DebugErrorLogger with something else, such as:
    PHP Code:
    class ProductionErrorLogger
    {
      function 
    setError($message) {
        
    mail("foo@example.com""An Error has occurred""There was an error" $message);
      }
    }
    $logger = new ProductionErrorLogger();
    $test = new Person();
    $test->validate($logger); 
    Without changing a single line of code in Person, you have changed the behaviour. This is a rather na´ve example, but I hope you get the general idea.

    Quote Originally Posted by agentforte View Post
    Keep in mind, I am building a single website for a business idea I have been developing, I am not a web developer. I want it to be very maintainable, not necessarily reusable. It is a custom application.
    Maintainability and reusability are more or less the same thing. OOP has often been sold as a tool for giving better code reuse, which isn't really fair. The strength of OOP is that it makes code maintainable, rather than magically make parts of the code reusable.

  13. #13
    SitePoint Addict agentforte's Avatar
    Join Date
    May 2007
    Location
    Toronto, ON, Canada
    Posts
    213
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Question Another way for static methods

    You did interpret my question correctly, thanks for the clarification.

    I see the logic, but in this case there is a key difference. The message sent to the user has nothing to do with the message sent to the error logger.


    You said that:
    Quote Originally Posted by kyberfabrikken View Post
    ...Later, in the production environment, you could then replace the DebugErrorLogger with something else ... Without changing a single line of code in Person...
    If I call a static method or floating function, I believe I can do the exact same thing without touching the code that the person uses.

    for example with the following code,
    PHP Code:
    class Person {
       public 
    $name;
        function 
    validate() {
           
    // connect to database and check if name taken
           
    if (error connecting to database) {
           
    $err=setError("database error");
           return(
    $err);
           } else {
         if (
    name taken  || preg_match('/^[a-zA-Z]+$/'$this->name)) {
           return (
    'Error with name');
           } else {
           return();
         }
       }
     }

    class 
    DebugErrorLogger {
       function static 
    setError($message) {
          
    // log error
          
    if (// problem logging error  ) {
         
    return ('please contact us to report error')
         } else {
         return(
    'There was an error. Site admin have been notified. Please try again or come back soon');
         }
    }

    $test = new Person();
    $errmsg[] = $test->validate($name); 
    if (isset(
    $errmsg)) {
    foreach (
    $errmsg as $err) {
    echo 
    $err;
    }
    else {
    echo 
    'success!;

    The static method setError can still be altered to do whatever without affecting the user.

    The only case that the dynamic method would be better is if I want to add a lot of functionality to the error logger class.

    Still, I could add other static methods and do what I need without altering the validator class.

  14. #14
    SitePoint Addict agentforte's Avatar
    Join Date
    May 2007
    Location
    Toronto, ON, Canada
    Posts
    213
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    In fact, in the code I wrote above, you do not need to worry about even mentioning the error logger in the page code. It is completely hidden. Only when I want to change the way my website handles errors do I need to look at that class.

    For some reason I think I am missing something, and this is possible with both static and dynamic methods.

  15. #15
    SitePoint Wizard Hammer65's Avatar
    Join Date
    Nov 2004
    Location
    Lincoln Nebraska
    Posts
    1,160
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The risk of naming collision is the same in these two cases:
    How do you figure that? If you have a class named foobar and a function named foobar_doSomething, they are two different things to PHP. You would have to instead have a function named foobar and a class named foobar, but then you could get that kind of name collision even with Java packages. The likelyhood of the collision is considerably reduced because you may have 12 classes but 50 methods.

    DoStuff inside of Foobar, is inside a different scope and would not conflict with any floating function called dostuff. Try it.

    System.out is part of the standard Java install and is just one example, in one language. You have to at some point, if you want to echo anything to the commandline, statically call System.out.println.

    I don't care how you obscure it in layers of sub classes, you still end up calling that method statically. That's how the System package was designed.

  16. #16
    SitePoint Addict agentforte's Avatar
    Join Date
    May 2007
    Location
    Toronto, ON, Canada
    Posts
    213
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Question

    Ok, here is what I have been trying to get an answer for this whole time:

    Can I have the line $db = new dbConn(); is inside a dynamic method, or must it be in the global scope (beside the code calling the validator class)

    Can I do option (1) below, or do I have to use option (2) for this to work?


    Option (1) (What I want to do):
    PHP Code:
    class Validator{
      function 
    userName($username) {

          
    $db = new &dbConn();
          
          if (
    $db->check4match($username)) {
          return (
    'Sorry name taken');
          } else {
          return(
    'That is a valid username!')
          }
      }
    }

    class 
    dbConn{

       
    // connect to database

       
    function check4match($username){
          
    // if username in database
          
    return TRUE;
          } else {
          return 
    FALSE;
          }
       }
    }

    $validate = new Validator();
    $result $validate->userName($username);
    echo 
    $result
    Option (2) (the way you showed me):
    PHP Code:
    class Validator{
      function 
    userName($username$db) {
          if (
    $db->check4match($username)) {
          return (
    'Sorry name taken');
          } else {
          return(
    'That is a valid username!')
          }
      }
    }


    class 
    dbConn{

       
    // connect to database

       
    function check4match($username){
          
    // if username in database
          
    return TRUE;
          } else {
          return 
    FALSE;
          }
       }
    }

    $db = new &dbConn();
    $validate = new Validator();
    $result $validate->userName($username$db);
    echo 
    $result
    My way would allow the page to have
    $validate = new Validator();
    $result = $validate->userName($username);
    echo $result;

    instead of
    $db = new &dbConn();
    $validate = new Validator();
    $result = $validate->userName($username, $db);
    echo $result;

  17. #17
    SitePoint Wizard Hammer65's Avatar
    Join Date
    Nov 2004
    Location
    Lincoln Nebraska
    Posts
    1,160
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If you include a file with your class in it, so that it has been declared, then it is accessable in any scope, including inside other classes. You can set a class member to be an instance of any declared class or use it in a temporary fashion inside a method (not sure how the garbage collection works in that case).

  18. #18
    SitePoint Addict agentforte's Avatar
    Join Date
    May 2007
    Location
    Toronto, ON, Canada
    Posts
    213
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I see. What do you mean by garbage collection? Is there some kind of problem I might run into?

  19. #19
    SitePoint Wizard Hammer65's Avatar
    Join Date
    Nov 2004
    Location
    Lincoln Nebraska
    Posts
    1,160
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    No. When you are coding for a very large high volume site, and want to optimize your code as much as possible, it can be instructive to know some of the deeper inner workings of PHP. This helps you avoid taking up to much RAM or other server resources.

    In many compiled languages, when you use some memory space to store a value, you have to manually release that memory space when you are done with it, so that your application doesn't keep eating up more and more memory.

    In PHP this is done for you based on a complex set of rules. The PHP interpreter may release a value stored in memory, when it knows that it has gotten to a point in your code where that value will no longer be used. This is called garbage collection.

    What I was wondering out loud about was exactly what PHP does if you use a variable in the method scope to store an instance of an object. I imagine that it throws it away once the method is done executing. I'm just not certain of that.

  20. #20
    SitePoint Addict agentforte's Avatar
    Join Date
    May 2007
    Location
    Toronto, ON, Canada
    Posts
    213
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I remember learning that a few years ago in a C programming course I had. Thanks for reminding me.

    This has really been helpful. Before I wasn't too sure how to use classes to do what I want. Now I'll be able to use them a lot more effectively.

    Also, I decided to use the class dbConn (database connection) in global scope to prevent a number of connections being made when a single connection will work for a number of things the page needs to do.

  21. #21
    SitePoint Wizard Hammer65's Avatar
    Join Date
    Nov 2004
    Location
    Lincoln Nebraska
    Posts
    1,160
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I would pass that connection identifier to each class that needs it by reference through an argument to the constructor or other method. coding access to global variables by name inside a class, isn't ideal.

    Passing by reference allows you to name the connection whatever you want in the global scope without having to change the class code to match.

  22. #22
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by agentforte View Post
    The static method setError can still be altered to do whatever without affecting the user.
    The difference is, that I didn't change the setError method. I defined a new one, and then I made the connection at run time. If you need one implementation of setError for development, and another in live operation, you could of course rewrite the code each time you go from one environment to the other, but that would be rather tedious. By deferring the "wiring", you can have both implementations, and simply swap them, depending on the environment. You can even do it several times within the same thread of execution, perhaps depending on user input or some program logic.

    Quote Originally Posted by Hammer65 View Post
    How do you figure that? If you have a class named foobar and a function named foobar_doSomething, they are two different things to PHP. You would have to instead have a function named foobar and a class named foobar ...
    We were comparing static methods with floating functions. You have to stick with that -- You can't compare floating functions to classes. Except for the fact, that you use two colons to separate namespace (class) from function in a static method, and an underscore (or whatever) in a floating function, the difference is purely syntactical.

    Quote Originally Posted by Hammer65 View Post
    ... but then you could get that kind of name collision even with Java packages.
    Yeah, but I'm not saying that static methods are a good idea in Java either.

    Quote Originally Posted by Hammer65 View Post
    System.out is part of the standard Java install and is just one example, in one language. You have to at some point, if you want to echo anything to the commandline, statically call System.out.println.

    I don't care how you obscure it in layers of sub classes, you still end up calling that method statically. That's how the System package was designed.
    Of course, but the point is not which object gets the call, but rather which variable is used to access the value (the object). There is a (subtle) difference. By using an object, you make the dispatch deferred till run time. This adds flexibility, and reduces dependencies.


    Quote Originally Posted by Hammer65 View Post
    What I was wondering out loud about was exactly what PHP does if you use a variable in the method scope to store an instance of an object. I imagine that it throws it away once the method is done executing. I'm just not certain of that.
    PHP doesn't have real garbage collection. It uses reference counting, which is quite simple: When a value is no longer referenced by any variable, it's reclaimed. This is a very simple scheme, which can be implemented efficiently. Unfortunately it is very prone to cyclical references. For most web applications, it doesn't make much difference, but when writing complex, and especially object oriented applications, it can be something of a headache.

  23. #23
    SitePoint Wizard Hammer65's Avatar
    Join Date
    Nov 2004
    Location
    Lincoln Nebraska
    Posts
    1,160
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The underscore is just another character in the name of the function.

    PHP Code:
    class test
    {
       function 
    shout()
       {
           echo(
    'test::shout()');
       }
    }

    function 
    shout()
    {
       echo(
    'the function shout');
    }

    shout();
    // will output 'the function shout'
    echo('<br />');
    test::shout();
    // will output 'test::shout()' 
    You can easily run this and see that the method "shout" does not conflict with the function called shout. No naming collisions.

    In fact in Java and any other OOP language I know of main() is called statically.

  24. #24
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Hammer65 View Post
    The underscore is just another character in the name of the function.
    And so are the two colons.

    PHP Code:
    function test_shout() {
      echo 
    'test_shout()';
    }

    function 
    shout() {
      echo 
    'the function shout';
    }

    shout();
    // will output 'the function shout'
    echo '<br />';
    test_shout();
    // will output 'test_shout()' 
    Same thing.

  25. #25
    SitePoint Wizard Hammer65's Avatar
    Join Date
    Nov 2004
    Location
    Lincoln Nebraska
    Posts
    1,160
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That isn't what your example is showing. You cannot use the double colon in a function name, it's an operator.

    When you write
    PHP Code:
    test::shout(); 
    The left operand is the name of the class and the right operand is the name of the method. The page that I linked to earlier on the subject from the manual is also quite plain on this, and the code I posted demonstrates it.


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
  •