OOP PHP Is it possible to call on a function from other classes

I am a bit new to OOP although I have been coding procedural PHP for years.

Here is what I am trying to figure out.

Say I have several classes and I want to call on a function from one of those classes inside a function in the other classes. What is the best way to do this? Do I have to extend them all from the first one, that seems like it would get really confusing if I have 8-10 different classes.

Below is a scenario of something similar to what I would like to do.


class History
{
          public function setHistory()
          {
               $sql = "insert into history (some columns here) values (some values here)";
               $result = mysql_query($sql);
          }
}


class Tasks
{
          public function updateTask()
          {
               $result = mysql_query("update task set subject = "testing" where task_id = $this->task_id ");
               $setHistory();   //TRYING TO CALL FUNCTION FROM OTHER CLASS
          }
}


class Contact
{
          public function updateContact()
          {
              $result = mysql_query("update contact set first_name = "John" where contact_id = $this->contact_id ");
              $setHistory();   //AGAIN IM TRYING TO CALL FUNCTION FROM OTHER CLASS
          }
}

So I might want to put data into the history table from all the other classes but I don’t really want to have to build a function inside each and every class that does the same thing.

Any help would be very much appreciated.

The simplest option (I’ll show a better way in just a bit) is to create a global history object.

$history = new History();

class Tasks
{
          public function updateTask()
          {
               global $history;

               $history->setHistory();
          }
} 

The downside, though, is that by relying on a global variable, the Tasks class is tightly coupled to this particular application environment, and it’s also harder to create different task objects that might have different histories. A better way is to inject a history object into your instantiated tasks object.

class Tasks
{
          private $history;

          public function __construct(History $history)
          {
               // Tasks doesn't need to know where this history object came from or how it was created
               // It only needs to know that this is the object it should use
               $this->history = $history;
          }

          public function updateTask()
          {
               $this->history->setHistory();
          }
}

$history = new History();

$tasks = new Tasks($history);

use call_user_func or call_user_func_array

i.e.


$instance = new History();
$output = user_call_func(array($instance, 'setHistory'));

If your setHistory accepted parameters, then you’d use:


$instance = new History();
$output = user_call_func(array($instance, 'setHistory'), $param1, $param2);

http://php.net/manual/en/function.call-user-func.php

Here is a question for you. Would you ever want to call setHistory() by itself? Or will it only be called from other classes such as Tasks and Contacts?

If you answer is No, you will never call it by itself and it will only be called by other classes such as Tasks and Contacts, then I recommend the following approach

class History 
{            
          protected function setHistory() // Note I made this protected
          { 
               $sql = "insert into history (some columns here) values (some values here)"; 
               $result = mysql_query($sql); 
          } 
} 


class Tasks  extends History // Extend History
{ 
          public function updateTask() 
          { 
               $result = mysql_query("update task set subject = "testing" where task_id = $this->task_id "); 
               // use $this to indicate you want to call a function that exists within the class or extended class
               $this->setHistory();   
          } 
} 


class Contact extends History
{ 
          public function updateContact() 
          { 
              $result = mysql_query("update contact set first_name = "John" where contact_id = $this->contact_id "); 
               // use $this to indicate you want to call a function that exists within the class or extended class
              $this->setHistory();
          } 
}  

You can technically accomplish this as well if you DO plan to call History by itself and not through another class (such as Tasks/Contacts) by using the above code, but keeping setHistory as public instead of protected.

I’m not sure this would pass the “is-a” test. Is it correct to say that a task “is-a” history? Or that a contact “is-a” history? Then I don’t think inheritance is the right choice in this situation. I think it’s more correct to say that a task “has-a” history, and that a contact “has-a” history.

That is true, but I also don’t see the History class as being a “true” history, it is more of a Log/Entry. A Task/Contact could be considered as an “Entry”.

Another aspect would to have Tasks and Contacts implement History, so they can self define how the history log is written, which may be even a better approach.

Thanks cpradio. This implement option you spoke of, can you elaborate on this a bit please? I haven’t used it and I am not sure how to use it or what it does. Could you please show me how that would work, how it differs from “extends”, and maybe provide an example?

I really appreciate everyone’s help on this.

Thanks groberts, I’ll try to look into this and see if that will work for me.

I’d be glad to

interface IHistory  
{             
          public function setHistory();  
}  


class Tasks implements IHistory // Implements History 
{  
          public function updateTask()  
          {  
               $result = mysql_query("update task set subject = "testing" where task_id = $this->task_id ");  
          }  

          // History Implementation
          public function setHistory()  
          {  
               $sql = "insert into history (some columns here) values (some values here)";  
               $result = mysql_query($sql);    
          }  
}  


class Contact implements IHistory 
{  
          public function updateContact()  
          {  
              $result = mysql_query("update contact set first_name = "John" where contact_id = $this->contact_id ");  
          }  

          // History Implementation
          public function setHistory()  
          {  
               $sql = "insert into history (some columns here) values (some values here)";  
               $result = mysql_query($sql);    
          }  
}  

$task = new Task();
$task->updateTask();
$task->setHistory(); // granted you can run this within updateTask() using $this->setHistory();

$contact = new Contact();
$contact->updateContact();
$contact->setHistory(); // granted you can run this within updateTask() using $this->setHistory();

// The best part about interfaces is setHistory can be called without knowing you are using a Task or a Contact
// Example: assume someone defined $mightBeATaskMightBeAContactWhoKnows as either a Task or Contact
if ($mightBeATaskMightBeAContactWhoKnows instanceOf IHistory)
{
    $implementsHistory->setHistory();
}

The interface simply allows you to define functions that need to be written in a class that implements that interface. It is a design contract for your objects. If you have a set of objects that all need to react in a similar fashion, your interface can define what functions those objects need to implement.

You can even make update() part of an implementation, but I’d argue that wouldn’t fit as the parameters for both Tasks and Contacts would likely differ.

this is the best answer in the thread. This is actual oop methodology in practice.

Wait now… Interfaces and inheritance are both accepted uses in OOP. The compisitional approach that Jeff Mott showed in his example is one way and it is true that it is the simplest to understand. Interfaces are properly demonstrated by cpradio where a contract for every class that implements the interface must adhere to and implement in their own way. Earlier Jeff and cpradio discussed if inheritance is warranted by a ‘is a’ test versus not using inheritance if the ‘has a’ test proves true; if it had worked in a ‘is a’ test then inheritance would have been a fine OOP method to use.

But if the history object is more of a log/entry class in reality, then it should be renamed.

It simply doesn’t makes sense for a task to be an instance of a history.

Also, one of the primary reasons for using an interface is to take advantage of polymorphism, but this was never mentioned. I think Mott’s original answer was tidier and makes more sense.

My only argument to the implementation Mott proposed (and this isn’t stated anywhere, just my opinion), is that the implementation of the $history -> setHistory can’t change by the type of object implementing it. With an interface it can, as your object can define how the setHistory is executed (so long as it matches the function declaration).

Maybe a Contact and a Task would execute the history entry the same way, I highly doubt it, but I guess it is possible. If it were up to me, I’d want to implement the two differently and that is where an interface would shine. Just my two cents.

I must also agree, that Mott’s implementation is very simple and tidy as well and if the execution would be the same between the two, I’d go with his method (so long as it matches any other objects execution as well).

Doh… He did show polymorphism… That’ll teach me to read the forum on my iPad. Didn’t see his example until just now…

He used dependency injection, so you could just pass a different history object to the Task constructor to change the implementation.

I’m not sure I’d ever approve having multiple History objects without some sort of IHistory interface that defined how those objects should be utilized. Then once you do that, you can pass in IHistory and let each object run the appropriate functions.

Or you could have the objects themselves implement IHistory and take one less class out of the mix.

:tup:++

Yeah, we’ll I was thinking the History objects would have a setHistory method enforced by an interface or abstract base class. I tend to use abstract classes personally, but it’s used for the same effect. Polymorphism really tidies things up and helps make things easier to maintain.