Pass functions to a class












2














PHP
mysql database
I have created a follow on question to this one here that is specifically about pagination



I need to call a method from one class in another, and be able to change the method that is called. Like so



class db{

function a(){ echo 'I run a query';}
function b(){ echo 'im the other query';}

}


class YourClass {

var $fcn;
$db = new db()

function invoke(){
call_user_func($this->fcn);
}

}



$instance = new YourClass;
$instance->fcn = 'db->a';
$instance->invoke();


I want to use a method 'a' from the db class in the 'yourClass' method 'invoke'
Thanks



Ok this is what i have put together from the answers provided and it works.



    class A {

function a(){
$x = 'Method a is used';
return $x;
}
function b(){
$x = 'Method b is used';
return $x;
}
}

class B {

function invoke($obj, $method){

echo call_user_func( array( $obj, $method) );

}

}

$instance = new B();
$instance->invoke(new A(),"a");


Which writes, 'Method a is used' to the screen



But i really want to be able to pass arguments to method "a" so i tried the code below.



class A {

function a($var1,$var2,$var3){
$x = 'the three passed values are ' . $var1 . ' and ' . $var2 . ' and ' . $var3;
return $x;
}
function b(){
$x = 'im method b';
return $x;
}
}

class B {

function invoke($obj,$arguments){

echo call_user_func_array($obj,$arguments);

}

}

$arguments = array('apple','banana','pineapple');
$use_function = array(new A(),"a");

$instance = new B();
$instance->invoke($use_function,$arguments);


It almost works but i get these errors above the correct answer



Missing argument 1 for A::a(),.....for argument 2 and 3 as well but then the answer prints to the screen
"the three passed values are apple and banana and pineapple"



I'm probably making a rookie mistake I've been coding all day. If someone could fix the script above and submit the working code, I would be eternally grateful. I have to put this issue to bed so i can go to bed.
Thanks










share|improve this question




















  • 2




    You probably want to reformat the code and tag this with the language you're using.
    – dlamblin
    Nov 14 '09 at 7:26






  • 1




    Why would you want to wrap db in YourClass and then provide a generic interface to call methods on $db, when you could just as well call the methods directly on $db. Since $db is a composite here, there is no gain in using this approach. This is kind of reinventing method calling.
    – Gordon
    Nov 14 '09 at 10:33
















2














PHP
mysql database
I have created a follow on question to this one here that is specifically about pagination



I need to call a method from one class in another, and be able to change the method that is called. Like so



class db{

function a(){ echo 'I run a query';}
function b(){ echo 'im the other query';}

}


class YourClass {

var $fcn;
$db = new db()

function invoke(){
call_user_func($this->fcn);
}

}



$instance = new YourClass;
$instance->fcn = 'db->a';
$instance->invoke();


I want to use a method 'a' from the db class in the 'yourClass' method 'invoke'
Thanks



Ok this is what i have put together from the answers provided and it works.



    class A {

function a(){
$x = 'Method a is used';
return $x;
}
function b(){
$x = 'Method b is used';
return $x;
}
}

class B {

function invoke($obj, $method){

echo call_user_func( array( $obj, $method) );

}

}

$instance = new B();
$instance->invoke(new A(),"a");


Which writes, 'Method a is used' to the screen



But i really want to be able to pass arguments to method "a" so i tried the code below.



class A {

function a($var1,$var2,$var3){
$x = 'the three passed values are ' . $var1 . ' and ' . $var2 . ' and ' . $var3;
return $x;
}
function b(){
$x = 'im method b';
return $x;
}
}

class B {

function invoke($obj,$arguments){

echo call_user_func_array($obj,$arguments);

}

}

$arguments = array('apple','banana','pineapple');
$use_function = array(new A(),"a");

$instance = new B();
$instance->invoke($use_function,$arguments);


It almost works but i get these errors above the correct answer



Missing argument 1 for A::a(),.....for argument 2 and 3 as well but then the answer prints to the screen
"the three passed values are apple and banana and pineapple"



I'm probably making a rookie mistake I've been coding all day. If someone could fix the script above and submit the working code, I would be eternally grateful. I have to put this issue to bed so i can go to bed.
Thanks










share|improve this question




















  • 2




    You probably want to reformat the code and tag this with the language you're using.
    – dlamblin
    Nov 14 '09 at 7:26






  • 1




    Why would you want to wrap db in YourClass and then provide a generic interface to call methods on $db, when you could just as well call the methods directly on $db. Since $db is a composite here, there is no gain in using this approach. This is kind of reinventing method calling.
    – Gordon
    Nov 14 '09 at 10:33














2












2








2


1





PHP
mysql database
I have created a follow on question to this one here that is specifically about pagination



I need to call a method from one class in another, and be able to change the method that is called. Like so



class db{

function a(){ echo 'I run a query';}
function b(){ echo 'im the other query';}

}


class YourClass {

var $fcn;
$db = new db()

function invoke(){
call_user_func($this->fcn);
}

}



$instance = new YourClass;
$instance->fcn = 'db->a';
$instance->invoke();


I want to use a method 'a' from the db class in the 'yourClass' method 'invoke'
Thanks



Ok this is what i have put together from the answers provided and it works.



    class A {

function a(){
$x = 'Method a is used';
return $x;
}
function b(){
$x = 'Method b is used';
return $x;
}
}

class B {

function invoke($obj, $method){

echo call_user_func( array( $obj, $method) );

}

}

$instance = new B();
$instance->invoke(new A(),"a");


Which writes, 'Method a is used' to the screen



But i really want to be able to pass arguments to method "a" so i tried the code below.



class A {

function a($var1,$var2,$var3){
$x = 'the three passed values are ' . $var1 . ' and ' . $var2 . ' and ' . $var3;
return $x;
}
function b(){
$x = 'im method b';
return $x;
}
}

class B {

function invoke($obj,$arguments){

echo call_user_func_array($obj,$arguments);

}

}

$arguments = array('apple','banana','pineapple');
$use_function = array(new A(),"a");

$instance = new B();
$instance->invoke($use_function,$arguments);


It almost works but i get these errors above the correct answer



Missing argument 1 for A::a(),.....for argument 2 and 3 as well but then the answer prints to the screen
"the three passed values are apple and banana and pineapple"



I'm probably making a rookie mistake I've been coding all day. If someone could fix the script above and submit the working code, I would be eternally grateful. I have to put this issue to bed so i can go to bed.
Thanks










share|improve this question















PHP
mysql database
I have created a follow on question to this one here that is specifically about pagination



I need to call a method from one class in another, and be able to change the method that is called. Like so



class db{

function a(){ echo 'I run a query';}
function b(){ echo 'im the other query';}

}


class YourClass {

var $fcn;
$db = new db()

function invoke(){
call_user_func($this->fcn);
}

}



$instance = new YourClass;
$instance->fcn = 'db->a';
$instance->invoke();


I want to use a method 'a' from the db class in the 'yourClass' method 'invoke'
Thanks



Ok this is what i have put together from the answers provided and it works.



    class A {

function a(){
$x = 'Method a is used';
return $x;
}
function b(){
$x = 'Method b is used';
return $x;
}
}

class B {

function invoke($obj, $method){

echo call_user_func( array( $obj, $method) );

}

}

$instance = new B();
$instance->invoke(new A(),"a");


Which writes, 'Method a is used' to the screen



But i really want to be able to pass arguments to method "a" so i tried the code below.



class A {

function a($var1,$var2,$var3){
$x = 'the three passed values are ' . $var1 . ' and ' . $var2 . ' and ' . $var3;
return $x;
}
function b(){
$x = 'im method b';
return $x;
}
}

class B {

function invoke($obj,$arguments){

echo call_user_func_array($obj,$arguments);

}

}

$arguments = array('apple','banana','pineapple');
$use_function = array(new A(),"a");

$instance = new B();
$instance->invoke($use_function,$arguments);


It almost works but i get these errors above the correct answer



Missing argument 1 for A::a(),.....for argument 2 and 3 as well but then the answer prints to the screen
"the three passed values are apple and banana and pineapple"



I'm probably making a rookie mistake I've been coding all day. If someone could fix the script above and submit the working code, I would be eternally grateful. I have to put this issue to bed so i can go to bed.
Thanks







php class






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited May 23 '17 at 11:48









Community

11




11










asked Nov 14 '09 at 7:21









andrew

2,26773653




2,26773653








  • 2




    You probably want to reformat the code and tag this with the language you're using.
    – dlamblin
    Nov 14 '09 at 7:26






  • 1




    Why would you want to wrap db in YourClass and then provide a generic interface to call methods on $db, when you could just as well call the methods directly on $db. Since $db is a composite here, there is no gain in using this approach. This is kind of reinventing method calling.
    – Gordon
    Nov 14 '09 at 10:33














  • 2




    You probably want to reformat the code and tag this with the language you're using.
    – dlamblin
    Nov 14 '09 at 7:26






  • 1




    Why would you want to wrap db in YourClass and then provide a generic interface to call methods on $db, when you could just as well call the methods directly on $db. Since $db is a composite here, there is no gain in using this approach. This is kind of reinventing method calling.
    – Gordon
    Nov 14 '09 at 10:33








2




2




You probably want to reformat the code and tag this with the language you're using.
– dlamblin
Nov 14 '09 at 7:26




You probably want to reformat the code and tag this with the language you're using.
– dlamblin
Nov 14 '09 at 7:26




1




1




Why would you want to wrap db in YourClass and then provide a generic interface to call methods on $db, when you could just as well call the methods directly on $db. Since $db is a composite here, there is no gain in using this approach. This is kind of reinventing method calling.
– Gordon
Nov 14 '09 at 10:33




Why would you want to wrap db in YourClass and then provide a generic interface to call methods on $db, when you could just as well call the methods directly on $db. Since $db is a composite here, there is no gain in using this approach. This is kind of reinventing method calling.
– Gordon
Nov 14 '09 at 10:33












9 Answers
9






active

oldest

votes


















8














As of PHP5.3 you could use closures or functors to pass methods around. Prior to that, you could write an anonymous function with create_function(), but that is rather awkward.



Basically, what you are trying to do could be done with the Strategy Pattern.



removed example code, as it wasnt helpful anymore after the OP changed the question (see wiki)



Apart from that, you might want to look into Fowlers's Data Source Architectural Patterns. The Zend Framework (and pretty much all other PHP frameworks) offers database access classes you could use for these patterns and there is also a paginator class, so why not check them out to learn how they did it.



removed EDIT 1 as it wasnt helpful anymore after the OP changed the question (see wiki)



EDIT 2
Ok, let's take a step by step approach to this (not using a Strategy Pattern though)



What you are asking for in the question can easily be solved with this code:



class Foo
{
public function bar()
{
echo 'bar method in Foo';
}
}

class MyInvoker
{
protected $myObject;

public function __construct()
{
$this->myObject = new Foo();
}

public function __call($method, $args)
{
$invocation = array($this->myObject, $method);
return call_user_func_array($invocation, $args);
}
}


With this code you'd just call the appropriate methods. No setting of methods names. No clumsy extra invoke method. No reinventing of how methods are called. You dont need it, because PHP has the __call function that you just taught to send all methods not existing in MyInvoker to $myObject, e.g. Foo.:



$invoker = new MyInvoker;
$invoker->bar(); // outputs 'bar method in Foo called'


You might just as well have extended MyInvoker to be a subclass of Foo, e.g.



class MyInvoker extends Foo {}


and then you could do the same. This not what you need though and it illustrates how pointless it is, to do such a thing. MyInvoker now does nothing by itself. It is an empty class and effectively the same as Foo. Even with the previous approach using the __call method it is not doing anything. This is why I have asked you to be more specific about the desired outcome, which is a Paginator.



First try:



class Paginator()
{
// A class holding all possible queries of our application
protected $queries;

// A class providing access to the database, like PDO_MySql
protected $dbConn;

public function __construct()
{
$this->db = new MyPdo();
$this->queries = new DbQueries();
}

public function __call($method, $args)
{
$invocation = array($this->queries, $method);
$query = call_user_func_array($invocation, $args);
return $this->dbConn->query($query);
}
}


With that code, our Paginator creates everything it needs inside itself, tightly coupling the db connection class and all queries and it allows you to call upon these, like so



$paginator = new Paginator;
// assuming we have something like getImageCount() in DbQueries
echo $paginator->getImageCount();


What is happening then is, Paginator will recognize it doesnt know getImageCount() and will invoke the __call method. The __call method will try to invoke the getImageCount() method on the DbQueries. Since it exists, it will return the query, which in turn is passed to the db connection to execute it. Great you'd say, but it's not. In fact, this is horrible. Your paginator's responsibility is to count items in a table and fetch items from this table in a certain range and amount. But right now, it is not doing anything like this. It is completely oblivious to whats going on, so lets try a new class:



class Paginator
{
protected $dbConn;
protected $itemCount;

public function __construct($dbConn)
{
$this->dbConn = $dbConn;
}

public function countItems($query)
{
$this->itemCount = $this->dbConn->query('select count(*) from (?)', $query);
return $this->itemCount;
}

public function fetchItems($query, $offset = 0, $limit = 20)
{
$sql = sprintf('select * from (?) LIMIT %d, %d', $offset, $limit);
return $this->dbConn->query($sql, $query);
}
}


Much better. Now our Paginator is an aggregate instead of a composite, meaning it does not instantiate objects inside itself, but requires them to be passed to it in the constructor. This is called dependency injection (and also provides a loose coupling, when dbConn uses an interface) which will make your app much more maintainable, as it is easy to exchange components now. This will also come in handy when Unit Testing your code.



In addition, your Paginator now concentrates on what it is supposed to do: counting and fetching items of an arbitrary query. No need to pass methods around. No need for obscure method invocation. You'd use it like this:



$paginator = new Paginator($dbConn);
$query = $dbQueries->findImagesUploadedLastWeek(); // returns SQL query string
$images = $paginator->countItems($query);
if($images > 0) {
$images = $paginator->fetchItems($query);
}


And that's it. Well, almost. You'd have to render the pagination of course. But this should be rather trivial, if you extend what you already have above. The $imageCount property is a hint at where to go next.



Anyway, hope that I could shed some light.



P.S. The $this->dbConn->query($sql, $query) calls are of course dummy code. Dont expect to be able to copy and paste it and get it working. In addition, you should make sure the queries added to the Paginator SQL is safe to use. You wouldnt want someone to insert a query that deletes all your db rows. Never trust user input.



P.P.S. $query should be an SQL query string. Check the PHP manual for PDO::prepare. In general, it yields better performance and security to prepare a statement before executing it. The page in the manual will give you the clues about the ? in the query calls. If you dont want to use PDO, just use sprintf() or str_replace() to replace ? with $query, e.g. $this->dbConn->query(sprintf('SELECT count(*) from (%s)', $query) but keep in mind that this has none of the benefits of a prepared statement and potentially opens the door for SQL Injection vulnerabilities.



P.P.P.S Yes, Dependency Injection is generally a preferred strategy. This is an advanved topic though and might be too much to fully grasp right now, but it's well worth looking into it. For now, it should be enough if you try to favor favor aggregation over composition. Your classes should only do what they are responsible for and get any dependencies through the constructor.






share|improve this answer























  • sorry about that but i wasn't getting the answers i wanted.
    – andrew
    Nov 14 '09 at 10:14










  • Well, and now you didnt get the answers you needed ;) Really, it is pointless to do $instance->invoke('method') when you just call_user_func the method to an object inside $instance. You could just as well use __call() then and put the invoke() code in there. Then you could do $instance->a(). This is typical for decorators and adapters. The big question is, what is the purpose of YourClass.
    – Gordon
    Nov 14 '09 at 11:01










  • Check Edit2 for some more code.
    – Gordon
    Nov 14 '09 at 12:53










  • Thanks that looks like what i need, now i just have to try and implement it.
    – andrew
    Nov 14 '09 at 23:09










  • Im learning a lot here. Is dependency injection in general a preferred strategy. For example, I have an Authentication class which requires a database connection. Is it better to instatiate my database class $db = new db(localhost,...) and then pass the authentication class my database object $auth = new Authentication($db) instead of creating an instance of $db inside the authentication class? What if i created a db class in auth but only made a connection if one had not already been made? Thanks
    – andrew
    Nov 14 '09 at 23:26



















2














Here are two ways of doing it:



class YourClass {
var $fcn;
function invoke($arguments){
//one way:
$this->{$this->fcn}($arguments);
//another way:
call_user_func_array(array($this, $this->fcn), $arguments);
}
function a(){
echo 'I am a()';
}
}

$instance = new YourClass;
$instance->fcn = 'a';
$instance->invoke();


This'll print out "I am a()" from inside the class.






share|improve this answer























  • Ahha, I see... fixed :)
    – brianreavis
    Nov 14 '09 at 9:33










  • yes, but the method 'a' needs to be in an entirely different class
    – andrew
    Nov 14 '09 at 9:49



















1














you are almost there



    class db {
function a(){ echo 'I run a query';}
function b(){ echo 'im the other query';}
}


class YourClass {
var $fcn;
function __construct() {
$this->db = new db();
}
function invoke() {
call_user_func(array(
$this->{$this->fcn[0]},
$this->fcn[1]
));
}

}

$instance = new YourClass;

$instance->fcn = array('db', 'a');
$instance->invoke();
$instance->fcn = array('db', 'b');
$instance->invoke();


the syntax is quite fancy, but it works



// edit: from your comment it looks like the simplest option is to pass method name as string, like this



 class Paginator {
function __consturct($db, $counter_func) ...

function get_count() {
$args = func_get_args();
return call_user_func_array(
array($this->db, $this->counter_func),
$args);
}
}

new Paginator($db, 'get_num_products');





share|improve this answer























  • Is there a cleaner way to do it? Colour Blend's answer is fairly simple.
    – andrew
    Nov 14 '09 at 9:52










  • I have a database class (db) which contains functions such as get_num_images(). I want to use functions from my db class in my paginator class AND i want to be able to change the function that the paginator class uses. So in some situations i will ask paginator class to use db->get_num_images() and other times tell it to use db->get_num_products.
    – andrew
    Nov 14 '09 at 11:07










  • Have a look at the original question, i have updated it with more detail
    – andrew
    Nov 14 '09 at 11:08



















0














I am guessing that you are using php here. Php supports variable functions which might solve you problem but as far as I am aware does not support delegates/function pointers.



What database are you using? I would be against putting queries within the code and using stored procedures as an alternative, if this is supported in the database you are using. This may solve the underlying problem you have.






share|improve this answer





















  • Hi, i am using php and mysql
    – andrew
    Nov 14 '09 at 8:14










  • MySql supports stored procedure from 5.0 onwards: dev.mysql.com/tech-resources/articles/… Here is an example calling a stored procedure from php which needs you to build php with mysqli: java2s.com/Tutorial/MySQL/0201__Procedure-Function/…
    – bobwah
    Nov 14 '09 at 8:56



















0














Are you asking if PHP has functional references? It doesn't. But it does let you call functions by putting their name in a string, or an array of a class name and method name.
See call_user_func() for a description, and variable functions.






share|improve this answer































    0














    class DB {
    function a(){ echo 'I run a query';}
    function b(){ echo 'im the other query';}
    }

    class B {

    protected $db;
    private $method;

    function __constructor($db) { $this->db; }

    function invoke($m){
    $this->method = $m;
    // Non static call
    call_user_func( array( $this->db, $this->method ) );
    }
    }

    $db = new DB();

    $b = new B($db);
    $b->invoke('a');


    I have made little modifications to my initial answer. You could also check out this post, it may help:



    Database and OOP Practices in PHP






    share|improve this answer































      0














      The Observer Design Pattern may be useful for this sort of thing, or it might be a misuse of the pattern; I don't know yet. Anyway, for your consideration:



      class DbObserver implements SplObserver
      {
      public function update(SplSubject $subject) // Required
      {
      $method = $subject->getObserverMethod();
      $args = $subject->getObserverArgs();
      $this->$method($args);
      }

      private function a($args)
      {
      echo 'I run query ' . $args[0] . '<br />';
      }

      private function b($args)
      {
      echo 'I run query ' . $args[0] . ' because ' . $args[1] . '<br />';
      }

      private function c()
      {
      echo 'I have no argument' . '<br />';
      }
      }

      class ObserverObserver implements SplObserver
      {
      public function update(SplSubject $subject) // Required
      {
      if (count($subject->getAttached()) > 1) {
      echo 'I saw that<br />';
      } else {
      echo 'Nothing happened<br />';
      }
      }
      }

      class DbSubject implements SplSubject
      {
      private $observerMethod;
      private $observerArgs = array();
      private $attached = array();

      public function notify() // Required
      {
      foreach ($this->attached as $each) {
      $each->update($this);
      }
      }

      public function attach(SplObserver $observer) // Required
      {
      $this->attached = $observer;
      }

      public function detach(SplObserver $observer) // Required
      {
      $key = array_keys($this->attached, $observer);
      unset($this->attached[$key[0]]);
      }

      public function setObserverMethod($method, $args = array())
      {
      $this->observerMethod = $method;
      $this->observerArgs = $args;
      return $this;
      }

      public function getObserverMethod()
      {
      return $this->observerMethod;
      }

      public function getObserverArgs()
      {
      return $this->observerArgs;
      }

      public function getAttached()
      {
      return $this->attached;
      }
      }

      $db_subj = new DbSubject;
      $db_obs = new DbObserver;
      $db_subj->attach($db_obs);
      $args = array('A');
      $db_subj->setObserverMethod('a', $args)->notify();
      $args = array('B', 'I can');
      $db_subj->setObserverMethod('b', $args)->notify();
      $obsvr = new ObserverObserver;
      $db_subj->attach($obsvr);
      $db_subj->setObserverMethod('c')->notify();
      $db_subj->detach($db_obs);
      $db_subj->notify();

      /**
      I run query A
      I run query B because I can
      I have no argument
      I saw that
      Nothing happened
      **/





      share|improve this answer





























        0














        You need to make this change:



        $arguments = array('apple','banana','pineapple');
        $a = new A();
        $use_function = array(&$a,"a"); // Make this changes to your code

        $instance = new B();
        $instance->invoke($use_function,$arguments);





        share|improve this answer































          0














          class A {
          function a(){ echo 'I run a query';}
          function b(){ echo 'im the other query';}
          }

          class B {

          function Test() {
          invoke(new $A(), "a");
          }

          function invoke($obj, $method){
          // Non static call
          call_user_func( array( $obj, $method ) );

          // Static call
          //call_user_func( array( 'ClassName', 'method' ) );
          }
          }


          I hope this helps.






          share|improve this answer























          • could you make this a complete example this is nearly the best example, sorry I'm just learning php i need is spelled out for me
            – andrew
            Nov 14 '09 at 10:15










          • I made another post. Let me know if that's what you want.
            – Tebo
            Nov 14 '09 at 10:26











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f1733582%2fpass-functions-to-a-class%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          9 Answers
          9






          active

          oldest

          votes








          9 Answers
          9






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          8














          As of PHP5.3 you could use closures or functors to pass methods around. Prior to that, you could write an anonymous function with create_function(), but that is rather awkward.



          Basically, what you are trying to do could be done with the Strategy Pattern.



          removed example code, as it wasnt helpful anymore after the OP changed the question (see wiki)



          Apart from that, you might want to look into Fowlers's Data Source Architectural Patterns. The Zend Framework (and pretty much all other PHP frameworks) offers database access classes you could use for these patterns and there is also a paginator class, so why not check them out to learn how they did it.



          removed EDIT 1 as it wasnt helpful anymore after the OP changed the question (see wiki)



          EDIT 2
          Ok, let's take a step by step approach to this (not using a Strategy Pattern though)



          What you are asking for in the question can easily be solved with this code:



          class Foo
          {
          public function bar()
          {
          echo 'bar method in Foo';
          }
          }

          class MyInvoker
          {
          protected $myObject;

          public function __construct()
          {
          $this->myObject = new Foo();
          }

          public function __call($method, $args)
          {
          $invocation = array($this->myObject, $method);
          return call_user_func_array($invocation, $args);
          }
          }


          With this code you'd just call the appropriate methods. No setting of methods names. No clumsy extra invoke method. No reinventing of how methods are called. You dont need it, because PHP has the __call function that you just taught to send all methods not existing in MyInvoker to $myObject, e.g. Foo.:



          $invoker = new MyInvoker;
          $invoker->bar(); // outputs 'bar method in Foo called'


          You might just as well have extended MyInvoker to be a subclass of Foo, e.g.



          class MyInvoker extends Foo {}


          and then you could do the same. This not what you need though and it illustrates how pointless it is, to do such a thing. MyInvoker now does nothing by itself. It is an empty class and effectively the same as Foo. Even with the previous approach using the __call method it is not doing anything. This is why I have asked you to be more specific about the desired outcome, which is a Paginator.



          First try:



          class Paginator()
          {
          // A class holding all possible queries of our application
          protected $queries;

          // A class providing access to the database, like PDO_MySql
          protected $dbConn;

          public function __construct()
          {
          $this->db = new MyPdo();
          $this->queries = new DbQueries();
          }

          public function __call($method, $args)
          {
          $invocation = array($this->queries, $method);
          $query = call_user_func_array($invocation, $args);
          return $this->dbConn->query($query);
          }
          }


          With that code, our Paginator creates everything it needs inside itself, tightly coupling the db connection class and all queries and it allows you to call upon these, like so



          $paginator = new Paginator;
          // assuming we have something like getImageCount() in DbQueries
          echo $paginator->getImageCount();


          What is happening then is, Paginator will recognize it doesnt know getImageCount() and will invoke the __call method. The __call method will try to invoke the getImageCount() method on the DbQueries. Since it exists, it will return the query, which in turn is passed to the db connection to execute it. Great you'd say, but it's not. In fact, this is horrible. Your paginator's responsibility is to count items in a table and fetch items from this table in a certain range and amount. But right now, it is not doing anything like this. It is completely oblivious to whats going on, so lets try a new class:



          class Paginator
          {
          protected $dbConn;
          protected $itemCount;

          public function __construct($dbConn)
          {
          $this->dbConn = $dbConn;
          }

          public function countItems($query)
          {
          $this->itemCount = $this->dbConn->query('select count(*) from (?)', $query);
          return $this->itemCount;
          }

          public function fetchItems($query, $offset = 0, $limit = 20)
          {
          $sql = sprintf('select * from (?) LIMIT %d, %d', $offset, $limit);
          return $this->dbConn->query($sql, $query);
          }
          }


          Much better. Now our Paginator is an aggregate instead of a composite, meaning it does not instantiate objects inside itself, but requires them to be passed to it in the constructor. This is called dependency injection (and also provides a loose coupling, when dbConn uses an interface) which will make your app much more maintainable, as it is easy to exchange components now. This will also come in handy when Unit Testing your code.



          In addition, your Paginator now concentrates on what it is supposed to do: counting and fetching items of an arbitrary query. No need to pass methods around. No need for obscure method invocation. You'd use it like this:



          $paginator = new Paginator($dbConn);
          $query = $dbQueries->findImagesUploadedLastWeek(); // returns SQL query string
          $images = $paginator->countItems($query);
          if($images > 0) {
          $images = $paginator->fetchItems($query);
          }


          And that's it. Well, almost. You'd have to render the pagination of course. But this should be rather trivial, if you extend what you already have above. The $imageCount property is a hint at where to go next.



          Anyway, hope that I could shed some light.



          P.S. The $this->dbConn->query($sql, $query) calls are of course dummy code. Dont expect to be able to copy and paste it and get it working. In addition, you should make sure the queries added to the Paginator SQL is safe to use. You wouldnt want someone to insert a query that deletes all your db rows. Never trust user input.



          P.P.S. $query should be an SQL query string. Check the PHP manual for PDO::prepare. In general, it yields better performance and security to prepare a statement before executing it. The page in the manual will give you the clues about the ? in the query calls. If you dont want to use PDO, just use sprintf() or str_replace() to replace ? with $query, e.g. $this->dbConn->query(sprintf('SELECT count(*) from (%s)', $query) but keep in mind that this has none of the benefits of a prepared statement and potentially opens the door for SQL Injection vulnerabilities.



          P.P.P.S Yes, Dependency Injection is generally a preferred strategy. This is an advanved topic though and might be too much to fully grasp right now, but it's well worth looking into it. For now, it should be enough if you try to favor favor aggregation over composition. Your classes should only do what they are responsible for and get any dependencies through the constructor.






          share|improve this answer























          • sorry about that but i wasn't getting the answers i wanted.
            – andrew
            Nov 14 '09 at 10:14










          • Well, and now you didnt get the answers you needed ;) Really, it is pointless to do $instance->invoke('method') when you just call_user_func the method to an object inside $instance. You could just as well use __call() then and put the invoke() code in there. Then you could do $instance->a(). This is typical for decorators and adapters. The big question is, what is the purpose of YourClass.
            – Gordon
            Nov 14 '09 at 11:01










          • Check Edit2 for some more code.
            – Gordon
            Nov 14 '09 at 12:53










          • Thanks that looks like what i need, now i just have to try and implement it.
            – andrew
            Nov 14 '09 at 23:09










          • Im learning a lot here. Is dependency injection in general a preferred strategy. For example, I have an Authentication class which requires a database connection. Is it better to instatiate my database class $db = new db(localhost,...) and then pass the authentication class my database object $auth = new Authentication($db) instead of creating an instance of $db inside the authentication class? What if i created a db class in auth but only made a connection if one had not already been made? Thanks
            – andrew
            Nov 14 '09 at 23:26
















          8














          As of PHP5.3 you could use closures or functors to pass methods around. Prior to that, you could write an anonymous function with create_function(), but that is rather awkward.



          Basically, what you are trying to do could be done with the Strategy Pattern.



          removed example code, as it wasnt helpful anymore after the OP changed the question (see wiki)



          Apart from that, you might want to look into Fowlers's Data Source Architectural Patterns. The Zend Framework (and pretty much all other PHP frameworks) offers database access classes you could use for these patterns and there is also a paginator class, so why not check them out to learn how they did it.



          removed EDIT 1 as it wasnt helpful anymore after the OP changed the question (see wiki)



          EDIT 2
          Ok, let's take a step by step approach to this (not using a Strategy Pattern though)



          What you are asking for in the question can easily be solved with this code:



          class Foo
          {
          public function bar()
          {
          echo 'bar method in Foo';
          }
          }

          class MyInvoker
          {
          protected $myObject;

          public function __construct()
          {
          $this->myObject = new Foo();
          }

          public function __call($method, $args)
          {
          $invocation = array($this->myObject, $method);
          return call_user_func_array($invocation, $args);
          }
          }


          With this code you'd just call the appropriate methods. No setting of methods names. No clumsy extra invoke method. No reinventing of how methods are called. You dont need it, because PHP has the __call function that you just taught to send all methods not existing in MyInvoker to $myObject, e.g. Foo.:



          $invoker = new MyInvoker;
          $invoker->bar(); // outputs 'bar method in Foo called'


          You might just as well have extended MyInvoker to be a subclass of Foo, e.g.



          class MyInvoker extends Foo {}


          and then you could do the same. This not what you need though and it illustrates how pointless it is, to do such a thing. MyInvoker now does nothing by itself. It is an empty class and effectively the same as Foo. Even with the previous approach using the __call method it is not doing anything. This is why I have asked you to be more specific about the desired outcome, which is a Paginator.



          First try:



          class Paginator()
          {
          // A class holding all possible queries of our application
          protected $queries;

          // A class providing access to the database, like PDO_MySql
          protected $dbConn;

          public function __construct()
          {
          $this->db = new MyPdo();
          $this->queries = new DbQueries();
          }

          public function __call($method, $args)
          {
          $invocation = array($this->queries, $method);
          $query = call_user_func_array($invocation, $args);
          return $this->dbConn->query($query);
          }
          }


          With that code, our Paginator creates everything it needs inside itself, tightly coupling the db connection class and all queries and it allows you to call upon these, like so



          $paginator = new Paginator;
          // assuming we have something like getImageCount() in DbQueries
          echo $paginator->getImageCount();


          What is happening then is, Paginator will recognize it doesnt know getImageCount() and will invoke the __call method. The __call method will try to invoke the getImageCount() method on the DbQueries. Since it exists, it will return the query, which in turn is passed to the db connection to execute it. Great you'd say, but it's not. In fact, this is horrible. Your paginator's responsibility is to count items in a table and fetch items from this table in a certain range and amount. But right now, it is not doing anything like this. It is completely oblivious to whats going on, so lets try a new class:



          class Paginator
          {
          protected $dbConn;
          protected $itemCount;

          public function __construct($dbConn)
          {
          $this->dbConn = $dbConn;
          }

          public function countItems($query)
          {
          $this->itemCount = $this->dbConn->query('select count(*) from (?)', $query);
          return $this->itemCount;
          }

          public function fetchItems($query, $offset = 0, $limit = 20)
          {
          $sql = sprintf('select * from (?) LIMIT %d, %d', $offset, $limit);
          return $this->dbConn->query($sql, $query);
          }
          }


          Much better. Now our Paginator is an aggregate instead of a composite, meaning it does not instantiate objects inside itself, but requires them to be passed to it in the constructor. This is called dependency injection (and also provides a loose coupling, when dbConn uses an interface) which will make your app much more maintainable, as it is easy to exchange components now. This will also come in handy when Unit Testing your code.



          In addition, your Paginator now concentrates on what it is supposed to do: counting and fetching items of an arbitrary query. No need to pass methods around. No need for obscure method invocation. You'd use it like this:



          $paginator = new Paginator($dbConn);
          $query = $dbQueries->findImagesUploadedLastWeek(); // returns SQL query string
          $images = $paginator->countItems($query);
          if($images > 0) {
          $images = $paginator->fetchItems($query);
          }


          And that's it. Well, almost. You'd have to render the pagination of course. But this should be rather trivial, if you extend what you already have above. The $imageCount property is a hint at where to go next.



          Anyway, hope that I could shed some light.



          P.S. The $this->dbConn->query($sql, $query) calls are of course dummy code. Dont expect to be able to copy and paste it and get it working. In addition, you should make sure the queries added to the Paginator SQL is safe to use. You wouldnt want someone to insert a query that deletes all your db rows. Never trust user input.



          P.P.S. $query should be an SQL query string. Check the PHP manual for PDO::prepare. In general, it yields better performance and security to prepare a statement before executing it. The page in the manual will give you the clues about the ? in the query calls. If you dont want to use PDO, just use sprintf() or str_replace() to replace ? with $query, e.g. $this->dbConn->query(sprintf('SELECT count(*) from (%s)', $query) but keep in mind that this has none of the benefits of a prepared statement and potentially opens the door for SQL Injection vulnerabilities.



          P.P.P.S Yes, Dependency Injection is generally a preferred strategy. This is an advanved topic though and might be too much to fully grasp right now, but it's well worth looking into it. For now, it should be enough if you try to favor favor aggregation over composition. Your classes should only do what they are responsible for and get any dependencies through the constructor.






          share|improve this answer























          • sorry about that but i wasn't getting the answers i wanted.
            – andrew
            Nov 14 '09 at 10:14










          • Well, and now you didnt get the answers you needed ;) Really, it is pointless to do $instance->invoke('method') when you just call_user_func the method to an object inside $instance. You could just as well use __call() then and put the invoke() code in there. Then you could do $instance->a(). This is typical for decorators and adapters. The big question is, what is the purpose of YourClass.
            – Gordon
            Nov 14 '09 at 11:01










          • Check Edit2 for some more code.
            – Gordon
            Nov 14 '09 at 12:53










          • Thanks that looks like what i need, now i just have to try and implement it.
            – andrew
            Nov 14 '09 at 23:09










          • Im learning a lot here. Is dependency injection in general a preferred strategy. For example, I have an Authentication class which requires a database connection. Is it better to instatiate my database class $db = new db(localhost,...) and then pass the authentication class my database object $auth = new Authentication($db) instead of creating an instance of $db inside the authentication class? What if i created a db class in auth but only made a connection if one had not already been made? Thanks
            – andrew
            Nov 14 '09 at 23:26














          8












          8








          8






          As of PHP5.3 you could use closures or functors to pass methods around. Prior to that, you could write an anonymous function with create_function(), but that is rather awkward.



          Basically, what you are trying to do could be done with the Strategy Pattern.



          removed example code, as it wasnt helpful anymore after the OP changed the question (see wiki)



          Apart from that, you might want to look into Fowlers's Data Source Architectural Patterns. The Zend Framework (and pretty much all other PHP frameworks) offers database access classes you could use for these patterns and there is also a paginator class, so why not check them out to learn how they did it.



          removed EDIT 1 as it wasnt helpful anymore after the OP changed the question (see wiki)



          EDIT 2
          Ok, let's take a step by step approach to this (not using a Strategy Pattern though)



          What you are asking for in the question can easily be solved with this code:



          class Foo
          {
          public function bar()
          {
          echo 'bar method in Foo';
          }
          }

          class MyInvoker
          {
          protected $myObject;

          public function __construct()
          {
          $this->myObject = new Foo();
          }

          public function __call($method, $args)
          {
          $invocation = array($this->myObject, $method);
          return call_user_func_array($invocation, $args);
          }
          }


          With this code you'd just call the appropriate methods. No setting of methods names. No clumsy extra invoke method. No reinventing of how methods are called. You dont need it, because PHP has the __call function that you just taught to send all methods not existing in MyInvoker to $myObject, e.g. Foo.:



          $invoker = new MyInvoker;
          $invoker->bar(); // outputs 'bar method in Foo called'


          You might just as well have extended MyInvoker to be a subclass of Foo, e.g.



          class MyInvoker extends Foo {}


          and then you could do the same. This not what you need though and it illustrates how pointless it is, to do such a thing. MyInvoker now does nothing by itself. It is an empty class and effectively the same as Foo. Even with the previous approach using the __call method it is not doing anything. This is why I have asked you to be more specific about the desired outcome, which is a Paginator.



          First try:



          class Paginator()
          {
          // A class holding all possible queries of our application
          protected $queries;

          // A class providing access to the database, like PDO_MySql
          protected $dbConn;

          public function __construct()
          {
          $this->db = new MyPdo();
          $this->queries = new DbQueries();
          }

          public function __call($method, $args)
          {
          $invocation = array($this->queries, $method);
          $query = call_user_func_array($invocation, $args);
          return $this->dbConn->query($query);
          }
          }


          With that code, our Paginator creates everything it needs inside itself, tightly coupling the db connection class and all queries and it allows you to call upon these, like so



          $paginator = new Paginator;
          // assuming we have something like getImageCount() in DbQueries
          echo $paginator->getImageCount();


          What is happening then is, Paginator will recognize it doesnt know getImageCount() and will invoke the __call method. The __call method will try to invoke the getImageCount() method on the DbQueries. Since it exists, it will return the query, which in turn is passed to the db connection to execute it. Great you'd say, but it's not. In fact, this is horrible. Your paginator's responsibility is to count items in a table and fetch items from this table in a certain range and amount. But right now, it is not doing anything like this. It is completely oblivious to whats going on, so lets try a new class:



          class Paginator
          {
          protected $dbConn;
          protected $itemCount;

          public function __construct($dbConn)
          {
          $this->dbConn = $dbConn;
          }

          public function countItems($query)
          {
          $this->itemCount = $this->dbConn->query('select count(*) from (?)', $query);
          return $this->itemCount;
          }

          public function fetchItems($query, $offset = 0, $limit = 20)
          {
          $sql = sprintf('select * from (?) LIMIT %d, %d', $offset, $limit);
          return $this->dbConn->query($sql, $query);
          }
          }


          Much better. Now our Paginator is an aggregate instead of a composite, meaning it does not instantiate objects inside itself, but requires them to be passed to it in the constructor. This is called dependency injection (and also provides a loose coupling, when dbConn uses an interface) which will make your app much more maintainable, as it is easy to exchange components now. This will also come in handy when Unit Testing your code.



          In addition, your Paginator now concentrates on what it is supposed to do: counting and fetching items of an arbitrary query. No need to pass methods around. No need for obscure method invocation. You'd use it like this:



          $paginator = new Paginator($dbConn);
          $query = $dbQueries->findImagesUploadedLastWeek(); // returns SQL query string
          $images = $paginator->countItems($query);
          if($images > 0) {
          $images = $paginator->fetchItems($query);
          }


          And that's it. Well, almost. You'd have to render the pagination of course. But this should be rather trivial, if you extend what you already have above. The $imageCount property is a hint at where to go next.



          Anyway, hope that I could shed some light.



          P.S. The $this->dbConn->query($sql, $query) calls are of course dummy code. Dont expect to be able to copy and paste it and get it working. In addition, you should make sure the queries added to the Paginator SQL is safe to use. You wouldnt want someone to insert a query that deletes all your db rows. Never trust user input.



          P.P.S. $query should be an SQL query string. Check the PHP manual for PDO::prepare. In general, it yields better performance and security to prepare a statement before executing it. The page in the manual will give you the clues about the ? in the query calls. If you dont want to use PDO, just use sprintf() or str_replace() to replace ? with $query, e.g. $this->dbConn->query(sprintf('SELECT count(*) from (%s)', $query) but keep in mind that this has none of the benefits of a prepared statement and potentially opens the door for SQL Injection vulnerabilities.



          P.P.P.S Yes, Dependency Injection is generally a preferred strategy. This is an advanved topic though and might be too much to fully grasp right now, but it's well worth looking into it. For now, it should be enough if you try to favor favor aggregation over composition. Your classes should only do what they are responsible for and get any dependencies through the constructor.






          share|improve this answer














          As of PHP5.3 you could use closures or functors to pass methods around. Prior to that, you could write an anonymous function with create_function(), but that is rather awkward.



          Basically, what you are trying to do could be done with the Strategy Pattern.



          removed example code, as it wasnt helpful anymore after the OP changed the question (see wiki)



          Apart from that, you might want to look into Fowlers's Data Source Architectural Patterns. The Zend Framework (and pretty much all other PHP frameworks) offers database access classes you could use for these patterns and there is also a paginator class, so why not check them out to learn how they did it.



          removed EDIT 1 as it wasnt helpful anymore after the OP changed the question (see wiki)



          EDIT 2
          Ok, let's take a step by step approach to this (not using a Strategy Pattern though)



          What you are asking for in the question can easily be solved with this code:



          class Foo
          {
          public function bar()
          {
          echo 'bar method in Foo';
          }
          }

          class MyInvoker
          {
          protected $myObject;

          public function __construct()
          {
          $this->myObject = new Foo();
          }

          public function __call($method, $args)
          {
          $invocation = array($this->myObject, $method);
          return call_user_func_array($invocation, $args);
          }
          }


          With this code you'd just call the appropriate methods. No setting of methods names. No clumsy extra invoke method. No reinventing of how methods are called. You dont need it, because PHP has the __call function that you just taught to send all methods not existing in MyInvoker to $myObject, e.g. Foo.:



          $invoker = new MyInvoker;
          $invoker->bar(); // outputs 'bar method in Foo called'


          You might just as well have extended MyInvoker to be a subclass of Foo, e.g.



          class MyInvoker extends Foo {}


          and then you could do the same. This not what you need though and it illustrates how pointless it is, to do such a thing. MyInvoker now does nothing by itself. It is an empty class and effectively the same as Foo. Even with the previous approach using the __call method it is not doing anything. This is why I have asked you to be more specific about the desired outcome, which is a Paginator.



          First try:



          class Paginator()
          {
          // A class holding all possible queries of our application
          protected $queries;

          // A class providing access to the database, like PDO_MySql
          protected $dbConn;

          public function __construct()
          {
          $this->db = new MyPdo();
          $this->queries = new DbQueries();
          }

          public function __call($method, $args)
          {
          $invocation = array($this->queries, $method);
          $query = call_user_func_array($invocation, $args);
          return $this->dbConn->query($query);
          }
          }


          With that code, our Paginator creates everything it needs inside itself, tightly coupling the db connection class and all queries and it allows you to call upon these, like so



          $paginator = new Paginator;
          // assuming we have something like getImageCount() in DbQueries
          echo $paginator->getImageCount();


          What is happening then is, Paginator will recognize it doesnt know getImageCount() and will invoke the __call method. The __call method will try to invoke the getImageCount() method on the DbQueries. Since it exists, it will return the query, which in turn is passed to the db connection to execute it. Great you'd say, but it's not. In fact, this is horrible. Your paginator's responsibility is to count items in a table and fetch items from this table in a certain range and amount. But right now, it is not doing anything like this. It is completely oblivious to whats going on, so lets try a new class:



          class Paginator
          {
          protected $dbConn;
          protected $itemCount;

          public function __construct($dbConn)
          {
          $this->dbConn = $dbConn;
          }

          public function countItems($query)
          {
          $this->itemCount = $this->dbConn->query('select count(*) from (?)', $query);
          return $this->itemCount;
          }

          public function fetchItems($query, $offset = 0, $limit = 20)
          {
          $sql = sprintf('select * from (?) LIMIT %d, %d', $offset, $limit);
          return $this->dbConn->query($sql, $query);
          }
          }


          Much better. Now our Paginator is an aggregate instead of a composite, meaning it does not instantiate objects inside itself, but requires them to be passed to it in the constructor. This is called dependency injection (and also provides a loose coupling, when dbConn uses an interface) which will make your app much more maintainable, as it is easy to exchange components now. This will also come in handy when Unit Testing your code.



          In addition, your Paginator now concentrates on what it is supposed to do: counting and fetching items of an arbitrary query. No need to pass methods around. No need for obscure method invocation. You'd use it like this:



          $paginator = new Paginator($dbConn);
          $query = $dbQueries->findImagesUploadedLastWeek(); // returns SQL query string
          $images = $paginator->countItems($query);
          if($images > 0) {
          $images = $paginator->fetchItems($query);
          }


          And that's it. Well, almost. You'd have to render the pagination of course. But this should be rather trivial, if you extend what you already have above. The $imageCount property is a hint at where to go next.



          Anyway, hope that I could shed some light.



          P.S. The $this->dbConn->query($sql, $query) calls are of course dummy code. Dont expect to be able to copy and paste it and get it working. In addition, you should make sure the queries added to the Paginator SQL is safe to use. You wouldnt want someone to insert a query that deletes all your db rows. Never trust user input.



          P.P.S. $query should be an SQL query string. Check the PHP manual for PDO::prepare. In general, it yields better performance and security to prepare a statement before executing it. The page in the manual will give you the clues about the ? in the query calls. If you dont want to use PDO, just use sprintf() or str_replace() to replace ? with $query, e.g. $this->dbConn->query(sprintf('SELECT count(*) from (%s)', $query) but keep in mind that this has none of the benefits of a prepared statement and potentially opens the door for SQL Injection vulnerabilities.



          P.P.P.S Yes, Dependency Injection is generally a preferred strategy. This is an advanved topic though and might be too much to fully grasp right now, but it's well worth looking into it. For now, it should be enough if you try to favor favor aggregation over composition. Your classes should only do what they are responsible for and get any dependencies through the constructor.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 26 '09 at 15:25


























          community wiki





          17 revs
          Gordon













          • sorry about that but i wasn't getting the answers i wanted.
            – andrew
            Nov 14 '09 at 10:14










          • Well, and now you didnt get the answers you needed ;) Really, it is pointless to do $instance->invoke('method') when you just call_user_func the method to an object inside $instance. You could just as well use __call() then and put the invoke() code in there. Then you could do $instance->a(). This is typical for decorators and adapters. The big question is, what is the purpose of YourClass.
            – Gordon
            Nov 14 '09 at 11:01










          • Check Edit2 for some more code.
            – Gordon
            Nov 14 '09 at 12:53










          • Thanks that looks like what i need, now i just have to try and implement it.
            – andrew
            Nov 14 '09 at 23:09










          • Im learning a lot here. Is dependency injection in general a preferred strategy. For example, I have an Authentication class which requires a database connection. Is it better to instatiate my database class $db = new db(localhost,...) and then pass the authentication class my database object $auth = new Authentication($db) instead of creating an instance of $db inside the authentication class? What if i created a db class in auth but only made a connection if one had not already been made? Thanks
            – andrew
            Nov 14 '09 at 23:26


















          • sorry about that but i wasn't getting the answers i wanted.
            – andrew
            Nov 14 '09 at 10:14










          • Well, and now you didnt get the answers you needed ;) Really, it is pointless to do $instance->invoke('method') when you just call_user_func the method to an object inside $instance. You could just as well use __call() then and put the invoke() code in there. Then you could do $instance->a(). This is typical for decorators and adapters. The big question is, what is the purpose of YourClass.
            – Gordon
            Nov 14 '09 at 11:01










          • Check Edit2 for some more code.
            – Gordon
            Nov 14 '09 at 12:53










          • Thanks that looks like what i need, now i just have to try and implement it.
            – andrew
            Nov 14 '09 at 23:09










          • Im learning a lot here. Is dependency injection in general a preferred strategy. For example, I have an Authentication class which requires a database connection. Is it better to instatiate my database class $db = new db(localhost,...) and then pass the authentication class my database object $auth = new Authentication($db) instead of creating an instance of $db inside the authentication class? What if i created a db class in auth but only made a connection if one had not already been made? Thanks
            – andrew
            Nov 14 '09 at 23:26
















          sorry about that but i wasn't getting the answers i wanted.
          – andrew
          Nov 14 '09 at 10:14




          sorry about that but i wasn't getting the answers i wanted.
          – andrew
          Nov 14 '09 at 10:14












          Well, and now you didnt get the answers you needed ;) Really, it is pointless to do $instance->invoke('method') when you just call_user_func the method to an object inside $instance. You could just as well use __call() then and put the invoke() code in there. Then you could do $instance->a(). This is typical for decorators and adapters. The big question is, what is the purpose of YourClass.
          – Gordon
          Nov 14 '09 at 11:01




          Well, and now you didnt get the answers you needed ;) Really, it is pointless to do $instance->invoke('method') when you just call_user_func the method to an object inside $instance. You could just as well use __call() then and put the invoke() code in there. Then you could do $instance->a(). This is typical for decorators and adapters. The big question is, what is the purpose of YourClass.
          – Gordon
          Nov 14 '09 at 11:01












          Check Edit2 for some more code.
          – Gordon
          Nov 14 '09 at 12:53




          Check Edit2 for some more code.
          – Gordon
          Nov 14 '09 at 12:53












          Thanks that looks like what i need, now i just have to try and implement it.
          – andrew
          Nov 14 '09 at 23:09




          Thanks that looks like what i need, now i just have to try and implement it.
          – andrew
          Nov 14 '09 at 23:09












          Im learning a lot here. Is dependency injection in general a preferred strategy. For example, I have an Authentication class which requires a database connection. Is it better to instatiate my database class $db = new db(localhost,...) and then pass the authentication class my database object $auth = new Authentication($db) instead of creating an instance of $db inside the authentication class? What if i created a db class in auth but only made a connection if one had not already been made? Thanks
          – andrew
          Nov 14 '09 at 23:26




          Im learning a lot here. Is dependency injection in general a preferred strategy. For example, I have an Authentication class which requires a database connection. Is it better to instatiate my database class $db = new db(localhost,...) and then pass the authentication class my database object $auth = new Authentication($db) instead of creating an instance of $db inside the authentication class? What if i created a db class in auth but only made a connection if one had not already been made? Thanks
          – andrew
          Nov 14 '09 at 23:26













          2














          Here are two ways of doing it:



          class YourClass {
          var $fcn;
          function invoke($arguments){
          //one way:
          $this->{$this->fcn}($arguments);
          //another way:
          call_user_func_array(array($this, $this->fcn), $arguments);
          }
          function a(){
          echo 'I am a()';
          }
          }

          $instance = new YourClass;
          $instance->fcn = 'a';
          $instance->invoke();


          This'll print out "I am a()" from inside the class.






          share|improve this answer























          • Ahha, I see... fixed :)
            – brianreavis
            Nov 14 '09 at 9:33










          • yes, but the method 'a' needs to be in an entirely different class
            – andrew
            Nov 14 '09 at 9:49
















          2














          Here are two ways of doing it:



          class YourClass {
          var $fcn;
          function invoke($arguments){
          //one way:
          $this->{$this->fcn}($arguments);
          //another way:
          call_user_func_array(array($this, $this->fcn), $arguments);
          }
          function a(){
          echo 'I am a()';
          }
          }

          $instance = new YourClass;
          $instance->fcn = 'a';
          $instance->invoke();


          This'll print out "I am a()" from inside the class.






          share|improve this answer























          • Ahha, I see... fixed :)
            – brianreavis
            Nov 14 '09 at 9:33










          • yes, but the method 'a' needs to be in an entirely different class
            – andrew
            Nov 14 '09 at 9:49














          2












          2








          2






          Here are two ways of doing it:



          class YourClass {
          var $fcn;
          function invoke($arguments){
          //one way:
          $this->{$this->fcn}($arguments);
          //another way:
          call_user_func_array(array($this, $this->fcn), $arguments);
          }
          function a(){
          echo 'I am a()';
          }
          }

          $instance = new YourClass;
          $instance->fcn = 'a';
          $instance->invoke();


          This'll print out "I am a()" from inside the class.






          share|improve this answer














          Here are two ways of doing it:



          class YourClass {
          var $fcn;
          function invoke($arguments){
          //one way:
          $this->{$this->fcn}($arguments);
          //another way:
          call_user_func_array(array($this, $this->fcn), $arguments);
          }
          function a(){
          echo 'I am a()';
          }
          }

          $instance = new YourClass;
          $instance->fcn = 'a';
          $instance->invoke();


          This'll print out "I am a()" from inside the class.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 14 '09 at 9:33

























          answered Nov 14 '09 at 7:39









          brianreavis

          9,66533346




          9,66533346












          • Ahha, I see... fixed :)
            – brianreavis
            Nov 14 '09 at 9:33










          • yes, but the method 'a' needs to be in an entirely different class
            – andrew
            Nov 14 '09 at 9:49


















          • Ahha, I see... fixed :)
            – brianreavis
            Nov 14 '09 at 9:33










          • yes, but the method 'a' needs to be in an entirely different class
            – andrew
            Nov 14 '09 at 9:49
















          Ahha, I see... fixed :)
          – brianreavis
          Nov 14 '09 at 9:33




          Ahha, I see... fixed :)
          – brianreavis
          Nov 14 '09 at 9:33












          yes, but the method 'a' needs to be in an entirely different class
          – andrew
          Nov 14 '09 at 9:49




          yes, but the method 'a' needs to be in an entirely different class
          – andrew
          Nov 14 '09 at 9:49











          1














          you are almost there



              class db {
          function a(){ echo 'I run a query';}
          function b(){ echo 'im the other query';}
          }


          class YourClass {
          var $fcn;
          function __construct() {
          $this->db = new db();
          }
          function invoke() {
          call_user_func(array(
          $this->{$this->fcn[0]},
          $this->fcn[1]
          ));
          }

          }

          $instance = new YourClass;

          $instance->fcn = array('db', 'a');
          $instance->invoke();
          $instance->fcn = array('db', 'b');
          $instance->invoke();


          the syntax is quite fancy, but it works



          // edit: from your comment it looks like the simplest option is to pass method name as string, like this



           class Paginator {
          function __consturct($db, $counter_func) ...

          function get_count() {
          $args = func_get_args();
          return call_user_func_array(
          array($this->db, $this->counter_func),
          $args);
          }
          }

          new Paginator($db, 'get_num_products');





          share|improve this answer























          • Is there a cleaner way to do it? Colour Blend's answer is fairly simple.
            – andrew
            Nov 14 '09 at 9:52










          • I have a database class (db) which contains functions such as get_num_images(). I want to use functions from my db class in my paginator class AND i want to be able to change the function that the paginator class uses. So in some situations i will ask paginator class to use db->get_num_images() and other times tell it to use db->get_num_products.
            – andrew
            Nov 14 '09 at 11:07










          • Have a look at the original question, i have updated it with more detail
            – andrew
            Nov 14 '09 at 11:08
















          1














          you are almost there



              class db {
          function a(){ echo 'I run a query';}
          function b(){ echo 'im the other query';}
          }


          class YourClass {
          var $fcn;
          function __construct() {
          $this->db = new db();
          }
          function invoke() {
          call_user_func(array(
          $this->{$this->fcn[0]},
          $this->fcn[1]
          ));
          }

          }

          $instance = new YourClass;

          $instance->fcn = array('db', 'a');
          $instance->invoke();
          $instance->fcn = array('db', 'b');
          $instance->invoke();


          the syntax is quite fancy, but it works



          // edit: from your comment it looks like the simplest option is to pass method name as string, like this



           class Paginator {
          function __consturct($db, $counter_func) ...

          function get_count() {
          $args = func_get_args();
          return call_user_func_array(
          array($this->db, $this->counter_func),
          $args);
          }
          }

          new Paginator($db, 'get_num_products');





          share|improve this answer























          • Is there a cleaner way to do it? Colour Blend's answer is fairly simple.
            – andrew
            Nov 14 '09 at 9:52










          • I have a database class (db) which contains functions such as get_num_images(). I want to use functions from my db class in my paginator class AND i want to be able to change the function that the paginator class uses. So in some situations i will ask paginator class to use db->get_num_images() and other times tell it to use db->get_num_products.
            – andrew
            Nov 14 '09 at 11:07










          • Have a look at the original question, i have updated it with more detail
            – andrew
            Nov 14 '09 at 11:08














          1












          1








          1






          you are almost there



              class db {
          function a(){ echo 'I run a query';}
          function b(){ echo 'im the other query';}
          }


          class YourClass {
          var $fcn;
          function __construct() {
          $this->db = new db();
          }
          function invoke() {
          call_user_func(array(
          $this->{$this->fcn[0]},
          $this->fcn[1]
          ));
          }

          }

          $instance = new YourClass;

          $instance->fcn = array('db', 'a');
          $instance->invoke();
          $instance->fcn = array('db', 'b');
          $instance->invoke();


          the syntax is quite fancy, but it works



          // edit: from your comment it looks like the simplest option is to pass method name as string, like this



           class Paginator {
          function __consturct($db, $counter_func) ...

          function get_count() {
          $args = func_get_args();
          return call_user_func_array(
          array($this->db, $this->counter_func),
          $args);
          }
          }

          new Paginator($db, 'get_num_products');





          share|improve this answer














          you are almost there



              class db {
          function a(){ echo 'I run a query';}
          function b(){ echo 'im the other query';}
          }


          class YourClass {
          var $fcn;
          function __construct() {
          $this->db = new db();
          }
          function invoke() {
          call_user_func(array(
          $this->{$this->fcn[0]},
          $this->fcn[1]
          ));
          }

          }

          $instance = new YourClass;

          $instance->fcn = array('db', 'a');
          $instance->invoke();
          $instance->fcn = array('db', 'b');
          $instance->invoke();


          the syntax is quite fancy, but it works



          // edit: from your comment it looks like the simplest option is to pass method name as string, like this



           class Paginator {
          function __consturct($db, $counter_func) ...

          function get_count() {
          $args = func_get_args();
          return call_user_func_array(
          array($this->db, $this->counter_func),
          $args);
          }
          }

          new Paginator($db, 'get_num_products');






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 14 '09 at 14:22

























          answered Nov 14 '09 at 9:35









          user187291

          45.1k1677126




          45.1k1677126












          • Is there a cleaner way to do it? Colour Blend's answer is fairly simple.
            – andrew
            Nov 14 '09 at 9:52










          • I have a database class (db) which contains functions such as get_num_images(). I want to use functions from my db class in my paginator class AND i want to be able to change the function that the paginator class uses. So in some situations i will ask paginator class to use db->get_num_images() and other times tell it to use db->get_num_products.
            – andrew
            Nov 14 '09 at 11:07










          • Have a look at the original question, i have updated it with more detail
            – andrew
            Nov 14 '09 at 11:08


















          • Is there a cleaner way to do it? Colour Blend's answer is fairly simple.
            – andrew
            Nov 14 '09 at 9:52










          • I have a database class (db) which contains functions such as get_num_images(). I want to use functions from my db class in my paginator class AND i want to be able to change the function that the paginator class uses. So in some situations i will ask paginator class to use db->get_num_images() and other times tell it to use db->get_num_products.
            – andrew
            Nov 14 '09 at 11:07










          • Have a look at the original question, i have updated it with more detail
            – andrew
            Nov 14 '09 at 11:08
















          Is there a cleaner way to do it? Colour Blend's answer is fairly simple.
          – andrew
          Nov 14 '09 at 9:52




          Is there a cleaner way to do it? Colour Blend's answer is fairly simple.
          – andrew
          Nov 14 '09 at 9:52












          I have a database class (db) which contains functions such as get_num_images(). I want to use functions from my db class in my paginator class AND i want to be able to change the function that the paginator class uses. So in some situations i will ask paginator class to use db->get_num_images() and other times tell it to use db->get_num_products.
          – andrew
          Nov 14 '09 at 11:07




          I have a database class (db) which contains functions such as get_num_images(). I want to use functions from my db class in my paginator class AND i want to be able to change the function that the paginator class uses. So in some situations i will ask paginator class to use db->get_num_images() and other times tell it to use db->get_num_products.
          – andrew
          Nov 14 '09 at 11:07












          Have a look at the original question, i have updated it with more detail
          – andrew
          Nov 14 '09 at 11:08




          Have a look at the original question, i have updated it with more detail
          – andrew
          Nov 14 '09 at 11:08











          0














          I am guessing that you are using php here. Php supports variable functions which might solve you problem but as far as I am aware does not support delegates/function pointers.



          What database are you using? I would be against putting queries within the code and using stored procedures as an alternative, if this is supported in the database you are using. This may solve the underlying problem you have.






          share|improve this answer





















          • Hi, i am using php and mysql
            – andrew
            Nov 14 '09 at 8:14










          • MySql supports stored procedure from 5.0 onwards: dev.mysql.com/tech-resources/articles/… Here is an example calling a stored procedure from php which needs you to build php with mysqli: java2s.com/Tutorial/MySQL/0201__Procedure-Function/…
            – bobwah
            Nov 14 '09 at 8:56
















          0














          I am guessing that you are using php here. Php supports variable functions which might solve you problem but as far as I am aware does not support delegates/function pointers.



          What database are you using? I would be against putting queries within the code and using stored procedures as an alternative, if this is supported in the database you are using. This may solve the underlying problem you have.






          share|improve this answer





















          • Hi, i am using php and mysql
            – andrew
            Nov 14 '09 at 8:14










          • MySql supports stored procedure from 5.0 onwards: dev.mysql.com/tech-resources/articles/… Here is an example calling a stored procedure from php which needs you to build php with mysqli: java2s.com/Tutorial/MySQL/0201__Procedure-Function/…
            – bobwah
            Nov 14 '09 at 8:56














          0












          0








          0






          I am guessing that you are using php here. Php supports variable functions which might solve you problem but as far as I am aware does not support delegates/function pointers.



          What database are you using? I would be against putting queries within the code and using stored procedures as an alternative, if this is supported in the database you are using. This may solve the underlying problem you have.






          share|improve this answer












          I am guessing that you are using php here. Php supports variable functions which might solve you problem but as far as I am aware does not support delegates/function pointers.



          What database are you using? I would be against putting queries within the code and using stored procedures as an alternative, if this is supported in the database you are using. This may solve the underlying problem you have.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 14 '09 at 7:39









          bobwah

          1,42612239




          1,42612239












          • Hi, i am using php and mysql
            – andrew
            Nov 14 '09 at 8:14










          • MySql supports stored procedure from 5.0 onwards: dev.mysql.com/tech-resources/articles/… Here is an example calling a stored procedure from php which needs you to build php with mysqli: java2s.com/Tutorial/MySQL/0201__Procedure-Function/…
            – bobwah
            Nov 14 '09 at 8:56


















          • Hi, i am using php and mysql
            – andrew
            Nov 14 '09 at 8:14










          • MySql supports stored procedure from 5.0 onwards: dev.mysql.com/tech-resources/articles/… Here is an example calling a stored procedure from php which needs you to build php with mysqli: java2s.com/Tutorial/MySQL/0201__Procedure-Function/…
            – bobwah
            Nov 14 '09 at 8:56
















          Hi, i am using php and mysql
          – andrew
          Nov 14 '09 at 8:14




          Hi, i am using php and mysql
          – andrew
          Nov 14 '09 at 8:14












          MySql supports stored procedure from 5.0 onwards: dev.mysql.com/tech-resources/articles/… Here is an example calling a stored procedure from php which needs you to build php with mysqli: java2s.com/Tutorial/MySQL/0201__Procedure-Function/…
          – bobwah
          Nov 14 '09 at 8:56




          MySql supports stored procedure from 5.0 onwards: dev.mysql.com/tech-resources/articles/… Here is an example calling a stored procedure from php which needs you to build php with mysqli: java2s.com/Tutorial/MySQL/0201__Procedure-Function/…
          – bobwah
          Nov 14 '09 at 8:56











          0














          Are you asking if PHP has functional references? It doesn't. But it does let you call functions by putting their name in a string, or an array of a class name and method name.
          See call_user_func() for a description, and variable functions.






          share|improve this answer




























            0














            Are you asking if PHP has functional references? It doesn't. But it does let you call functions by putting their name in a string, or an array of a class name and method name.
            See call_user_func() for a description, and variable functions.






            share|improve this answer


























              0












              0








              0






              Are you asking if PHP has functional references? It doesn't. But it does let you call functions by putting their name in a string, or an array of a class name and method name.
              See call_user_func() for a description, and variable functions.






              share|improve this answer














              Are you asking if PHP has functional references? It doesn't. But it does let you call functions by putting their name in a string, or an array of a class name and method name.
              See call_user_func() for a description, and variable functions.







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Nov 14 '09 at 7:48

























              answered Nov 14 '09 at 7:38









              dlamblin

              26.7k1773108




              26.7k1773108























                  0














                  class DB {
                  function a(){ echo 'I run a query';}
                  function b(){ echo 'im the other query';}
                  }

                  class B {

                  protected $db;
                  private $method;

                  function __constructor($db) { $this->db; }

                  function invoke($m){
                  $this->method = $m;
                  // Non static call
                  call_user_func( array( $this->db, $this->method ) );
                  }
                  }

                  $db = new DB();

                  $b = new B($db);
                  $b->invoke('a');


                  I have made little modifications to my initial answer. You could also check out this post, it may help:



                  Database and OOP Practices in PHP






                  share|improve this answer




























                    0














                    class DB {
                    function a(){ echo 'I run a query';}
                    function b(){ echo 'im the other query';}
                    }

                    class B {

                    protected $db;
                    private $method;

                    function __constructor($db) { $this->db; }

                    function invoke($m){
                    $this->method = $m;
                    // Non static call
                    call_user_func( array( $this->db, $this->method ) );
                    }
                    }

                    $db = new DB();

                    $b = new B($db);
                    $b->invoke('a');


                    I have made little modifications to my initial answer. You could also check out this post, it may help:



                    Database and OOP Practices in PHP






                    share|improve this answer


























                      0












                      0








                      0






                      class DB {
                      function a(){ echo 'I run a query';}
                      function b(){ echo 'im the other query';}
                      }

                      class B {

                      protected $db;
                      private $method;

                      function __constructor($db) { $this->db; }

                      function invoke($m){
                      $this->method = $m;
                      // Non static call
                      call_user_func( array( $this->db, $this->method ) );
                      }
                      }

                      $db = new DB();

                      $b = new B($db);
                      $b->invoke('a');


                      I have made little modifications to my initial answer. You could also check out this post, it may help:



                      Database and OOP Practices in PHP






                      share|improve this answer














                      class DB {
                      function a(){ echo 'I run a query';}
                      function b(){ echo 'im the other query';}
                      }

                      class B {

                      protected $db;
                      private $method;

                      function __constructor($db) { $this->db; }

                      function invoke($m){
                      $this->method = $m;
                      // Non static call
                      call_user_func( array( $this->db, $this->method ) );
                      }
                      }

                      $db = new DB();

                      $b = new B($db);
                      $b->invoke('a');


                      I have made little modifications to my initial answer. You could also check out this post, it may help:



                      Database and OOP Practices in PHP







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited May 23 '17 at 12:13









                      Community

                      11




                      11










                      answered Nov 14 '09 at 10:21









                      Tebo

                      6,716104261




                      6,716104261























                          0














                          The Observer Design Pattern may be useful for this sort of thing, or it might be a misuse of the pattern; I don't know yet. Anyway, for your consideration:



                          class DbObserver implements SplObserver
                          {
                          public function update(SplSubject $subject) // Required
                          {
                          $method = $subject->getObserverMethod();
                          $args = $subject->getObserverArgs();
                          $this->$method($args);
                          }

                          private function a($args)
                          {
                          echo 'I run query ' . $args[0] . '<br />';
                          }

                          private function b($args)
                          {
                          echo 'I run query ' . $args[0] . ' because ' . $args[1] . '<br />';
                          }

                          private function c()
                          {
                          echo 'I have no argument' . '<br />';
                          }
                          }

                          class ObserverObserver implements SplObserver
                          {
                          public function update(SplSubject $subject) // Required
                          {
                          if (count($subject->getAttached()) > 1) {
                          echo 'I saw that<br />';
                          } else {
                          echo 'Nothing happened<br />';
                          }
                          }
                          }

                          class DbSubject implements SplSubject
                          {
                          private $observerMethod;
                          private $observerArgs = array();
                          private $attached = array();

                          public function notify() // Required
                          {
                          foreach ($this->attached as $each) {
                          $each->update($this);
                          }
                          }

                          public function attach(SplObserver $observer) // Required
                          {
                          $this->attached = $observer;
                          }

                          public function detach(SplObserver $observer) // Required
                          {
                          $key = array_keys($this->attached, $observer);
                          unset($this->attached[$key[0]]);
                          }

                          public function setObserverMethod($method, $args = array())
                          {
                          $this->observerMethod = $method;
                          $this->observerArgs = $args;
                          return $this;
                          }

                          public function getObserverMethod()
                          {
                          return $this->observerMethod;
                          }

                          public function getObserverArgs()
                          {
                          return $this->observerArgs;
                          }

                          public function getAttached()
                          {
                          return $this->attached;
                          }
                          }

                          $db_subj = new DbSubject;
                          $db_obs = new DbObserver;
                          $db_subj->attach($db_obs);
                          $args = array('A');
                          $db_subj->setObserverMethod('a', $args)->notify();
                          $args = array('B', 'I can');
                          $db_subj->setObserverMethod('b', $args)->notify();
                          $obsvr = new ObserverObserver;
                          $db_subj->attach($obsvr);
                          $db_subj->setObserverMethod('c')->notify();
                          $db_subj->detach($db_obs);
                          $db_subj->notify();

                          /**
                          I run query A
                          I run query B because I can
                          I have no argument
                          I saw that
                          Nothing happened
                          **/





                          share|improve this answer


























                            0














                            The Observer Design Pattern may be useful for this sort of thing, or it might be a misuse of the pattern; I don't know yet. Anyway, for your consideration:



                            class DbObserver implements SplObserver
                            {
                            public function update(SplSubject $subject) // Required
                            {
                            $method = $subject->getObserverMethod();
                            $args = $subject->getObserverArgs();
                            $this->$method($args);
                            }

                            private function a($args)
                            {
                            echo 'I run query ' . $args[0] . '<br />';
                            }

                            private function b($args)
                            {
                            echo 'I run query ' . $args[0] . ' because ' . $args[1] . '<br />';
                            }

                            private function c()
                            {
                            echo 'I have no argument' . '<br />';
                            }
                            }

                            class ObserverObserver implements SplObserver
                            {
                            public function update(SplSubject $subject) // Required
                            {
                            if (count($subject->getAttached()) > 1) {
                            echo 'I saw that<br />';
                            } else {
                            echo 'Nothing happened<br />';
                            }
                            }
                            }

                            class DbSubject implements SplSubject
                            {
                            private $observerMethod;
                            private $observerArgs = array();
                            private $attached = array();

                            public function notify() // Required
                            {
                            foreach ($this->attached as $each) {
                            $each->update($this);
                            }
                            }

                            public function attach(SplObserver $observer) // Required
                            {
                            $this->attached = $observer;
                            }

                            public function detach(SplObserver $observer) // Required
                            {
                            $key = array_keys($this->attached, $observer);
                            unset($this->attached[$key[0]]);
                            }

                            public function setObserverMethod($method, $args = array())
                            {
                            $this->observerMethod = $method;
                            $this->observerArgs = $args;
                            return $this;
                            }

                            public function getObserverMethod()
                            {
                            return $this->observerMethod;
                            }

                            public function getObserverArgs()
                            {
                            return $this->observerArgs;
                            }

                            public function getAttached()
                            {
                            return $this->attached;
                            }
                            }

                            $db_subj = new DbSubject;
                            $db_obs = new DbObserver;
                            $db_subj->attach($db_obs);
                            $args = array('A');
                            $db_subj->setObserverMethod('a', $args)->notify();
                            $args = array('B', 'I can');
                            $db_subj->setObserverMethod('b', $args)->notify();
                            $obsvr = new ObserverObserver;
                            $db_subj->attach($obsvr);
                            $db_subj->setObserverMethod('c')->notify();
                            $db_subj->detach($db_obs);
                            $db_subj->notify();

                            /**
                            I run query A
                            I run query B because I can
                            I have no argument
                            I saw that
                            Nothing happened
                            **/





                            share|improve this answer
























                              0












                              0








                              0






                              The Observer Design Pattern may be useful for this sort of thing, or it might be a misuse of the pattern; I don't know yet. Anyway, for your consideration:



                              class DbObserver implements SplObserver
                              {
                              public function update(SplSubject $subject) // Required
                              {
                              $method = $subject->getObserverMethod();
                              $args = $subject->getObserverArgs();
                              $this->$method($args);
                              }

                              private function a($args)
                              {
                              echo 'I run query ' . $args[0] . '<br />';
                              }

                              private function b($args)
                              {
                              echo 'I run query ' . $args[0] . ' because ' . $args[1] . '<br />';
                              }

                              private function c()
                              {
                              echo 'I have no argument' . '<br />';
                              }
                              }

                              class ObserverObserver implements SplObserver
                              {
                              public function update(SplSubject $subject) // Required
                              {
                              if (count($subject->getAttached()) > 1) {
                              echo 'I saw that<br />';
                              } else {
                              echo 'Nothing happened<br />';
                              }
                              }
                              }

                              class DbSubject implements SplSubject
                              {
                              private $observerMethod;
                              private $observerArgs = array();
                              private $attached = array();

                              public function notify() // Required
                              {
                              foreach ($this->attached as $each) {
                              $each->update($this);
                              }
                              }

                              public function attach(SplObserver $observer) // Required
                              {
                              $this->attached = $observer;
                              }

                              public function detach(SplObserver $observer) // Required
                              {
                              $key = array_keys($this->attached, $observer);
                              unset($this->attached[$key[0]]);
                              }

                              public function setObserverMethod($method, $args = array())
                              {
                              $this->observerMethod = $method;
                              $this->observerArgs = $args;
                              return $this;
                              }

                              public function getObserverMethod()
                              {
                              return $this->observerMethod;
                              }

                              public function getObserverArgs()
                              {
                              return $this->observerArgs;
                              }

                              public function getAttached()
                              {
                              return $this->attached;
                              }
                              }

                              $db_subj = new DbSubject;
                              $db_obs = new DbObserver;
                              $db_subj->attach($db_obs);
                              $args = array('A');
                              $db_subj->setObserverMethod('a', $args)->notify();
                              $args = array('B', 'I can');
                              $db_subj->setObserverMethod('b', $args)->notify();
                              $obsvr = new ObserverObserver;
                              $db_subj->attach($obsvr);
                              $db_subj->setObserverMethod('c')->notify();
                              $db_subj->detach($db_obs);
                              $db_subj->notify();

                              /**
                              I run query A
                              I run query B because I can
                              I have no argument
                              I saw that
                              Nothing happened
                              **/





                              share|improve this answer












                              The Observer Design Pattern may be useful for this sort of thing, or it might be a misuse of the pattern; I don't know yet. Anyway, for your consideration:



                              class DbObserver implements SplObserver
                              {
                              public function update(SplSubject $subject) // Required
                              {
                              $method = $subject->getObserverMethod();
                              $args = $subject->getObserverArgs();
                              $this->$method($args);
                              }

                              private function a($args)
                              {
                              echo 'I run query ' . $args[0] . '<br />';
                              }

                              private function b($args)
                              {
                              echo 'I run query ' . $args[0] . ' because ' . $args[1] . '<br />';
                              }

                              private function c()
                              {
                              echo 'I have no argument' . '<br />';
                              }
                              }

                              class ObserverObserver implements SplObserver
                              {
                              public function update(SplSubject $subject) // Required
                              {
                              if (count($subject->getAttached()) > 1) {
                              echo 'I saw that<br />';
                              } else {
                              echo 'Nothing happened<br />';
                              }
                              }
                              }

                              class DbSubject implements SplSubject
                              {
                              private $observerMethod;
                              private $observerArgs = array();
                              private $attached = array();

                              public function notify() // Required
                              {
                              foreach ($this->attached as $each) {
                              $each->update($this);
                              }
                              }

                              public function attach(SplObserver $observer) // Required
                              {
                              $this->attached = $observer;
                              }

                              public function detach(SplObserver $observer) // Required
                              {
                              $key = array_keys($this->attached, $observer);
                              unset($this->attached[$key[0]]);
                              }

                              public function setObserverMethod($method, $args = array())
                              {
                              $this->observerMethod = $method;
                              $this->observerArgs = $args;
                              return $this;
                              }

                              public function getObserverMethod()
                              {
                              return $this->observerMethod;
                              }

                              public function getObserverArgs()
                              {
                              return $this->observerArgs;
                              }

                              public function getAttached()
                              {
                              return $this->attached;
                              }
                              }

                              $db_subj = new DbSubject;
                              $db_obs = new DbObserver;
                              $db_subj->attach($db_obs);
                              $args = array('A');
                              $db_subj->setObserverMethod('a', $args)->notify();
                              $args = array('B', 'I can');
                              $db_subj->setObserverMethod('b', $args)->notify();
                              $obsvr = new ObserverObserver;
                              $db_subj->attach($obsvr);
                              $db_subj->setObserverMethod('c')->notify();
                              $db_subj->detach($db_obs);
                              $db_subj->notify();

                              /**
                              I run query A
                              I run query B because I can
                              I have no argument
                              I saw that
                              Nothing happened
                              **/






                              share|improve this answer












                              share|improve this answer



                              share|improve this answer










                              answered Nov 14 '09 at 17:49









                              GZipp

                              4,71311614




                              4,71311614























                                  0














                                  You need to make this change:



                                  $arguments = array('apple','banana','pineapple');
                                  $a = new A();
                                  $use_function = array(&$a,"a"); // Make this changes to your code

                                  $instance = new B();
                                  $instance->invoke($use_function,$arguments);





                                  share|improve this answer




























                                    0














                                    You need to make this change:



                                    $arguments = array('apple','banana','pineapple');
                                    $a = new A();
                                    $use_function = array(&$a,"a"); // Make this changes to your code

                                    $instance = new B();
                                    $instance->invoke($use_function,$arguments);





                                    share|improve this answer


























                                      0












                                      0








                                      0






                                      You need to make this change:



                                      $arguments = array('apple','banana','pineapple');
                                      $a = new A();
                                      $use_function = array(&$a,"a"); // Make this changes to your code

                                      $instance = new B();
                                      $instance->invoke($use_function,$arguments);





                                      share|improve this answer














                                      You need to make this change:



                                      $arguments = array('apple','banana','pineapple');
                                      $a = new A();
                                      $use_function = array(&$a,"a"); // Make this changes to your code

                                      $instance = new B();
                                      $instance->invoke($use_function,$arguments);






                                      share|improve this answer














                                      share|improve this answer



                                      share|improve this answer








                                      edited Nov 20 at 2:30









                                      Pang

                                      6,8601563101




                                      6,8601563101










                                      answered Nov 14 '09 at 16:05









                                      Tebo

                                      6,716104261




                                      6,716104261























                                          0














                                          class A {
                                          function a(){ echo 'I run a query';}
                                          function b(){ echo 'im the other query';}
                                          }

                                          class B {

                                          function Test() {
                                          invoke(new $A(), "a");
                                          }

                                          function invoke($obj, $method){
                                          // Non static call
                                          call_user_func( array( $obj, $method ) );

                                          // Static call
                                          //call_user_func( array( 'ClassName', 'method' ) );
                                          }
                                          }


                                          I hope this helps.






                                          share|improve this answer























                                          • could you make this a complete example this is nearly the best example, sorry I'm just learning php i need is spelled out for me
                                            – andrew
                                            Nov 14 '09 at 10:15










                                          • I made another post. Let me know if that's what you want.
                                            – Tebo
                                            Nov 14 '09 at 10:26
















                                          0














                                          class A {
                                          function a(){ echo 'I run a query';}
                                          function b(){ echo 'im the other query';}
                                          }

                                          class B {

                                          function Test() {
                                          invoke(new $A(), "a");
                                          }

                                          function invoke($obj, $method){
                                          // Non static call
                                          call_user_func( array( $obj, $method ) );

                                          // Static call
                                          //call_user_func( array( 'ClassName', 'method' ) );
                                          }
                                          }


                                          I hope this helps.






                                          share|improve this answer























                                          • could you make this a complete example this is nearly the best example, sorry I'm just learning php i need is spelled out for me
                                            – andrew
                                            Nov 14 '09 at 10:15










                                          • I made another post. Let me know if that's what you want.
                                            – Tebo
                                            Nov 14 '09 at 10:26














                                          0












                                          0








                                          0






                                          class A {
                                          function a(){ echo 'I run a query';}
                                          function b(){ echo 'im the other query';}
                                          }

                                          class B {

                                          function Test() {
                                          invoke(new $A(), "a");
                                          }

                                          function invoke($obj, $method){
                                          // Non static call
                                          call_user_func( array( $obj, $method ) );

                                          // Static call
                                          //call_user_func( array( 'ClassName', 'method' ) );
                                          }
                                          }


                                          I hope this helps.






                                          share|improve this answer














                                          class A {
                                          function a(){ echo 'I run a query';}
                                          function b(){ echo 'im the other query';}
                                          }

                                          class B {

                                          function Test() {
                                          invoke(new $A(), "a");
                                          }

                                          function invoke($obj, $method){
                                          // Non static call
                                          call_user_func( array( $obj, $method ) );

                                          // Static call
                                          //call_user_func( array( 'ClassName', 'method' ) );
                                          }
                                          }


                                          I hope this helps.







                                          share|improve this answer














                                          share|improve this answer



                                          share|improve this answer








                                          edited Nov 20 at 2:30









                                          Pang

                                          6,8601563101




                                          6,8601563101










                                          answered Nov 14 '09 at 9:25









                                          Tebo

                                          6,716104261




                                          6,716104261












                                          • could you make this a complete example this is nearly the best example, sorry I'm just learning php i need is spelled out for me
                                            – andrew
                                            Nov 14 '09 at 10:15










                                          • I made another post. Let me know if that's what you want.
                                            – Tebo
                                            Nov 14 '09 at 10:26


















                                          • could you make this a complete example this is nearly the best example, sorry I'm just learning php i need is spelled out for me
                                            – andrew
                                            Nov 14 '09 at 10:15










                                          • I made another post. Let me know if that's what you want.
                                            – Tebo
                                            Nov 14 '09 at 10:26
















                                          could you make this a complete example this is nearly the best example, sorry I'm just learning php i need is spelled out for me
                                          – andrew
                                          Nov 14 '09 at 10:15




                                          could you make this a complete example this is nearly the best example, sorry I'm just learning php i need is spelled out for me
                                          – andrew
                                          Nov 14 '09 at 10:15












                                          I made another post. Let me know if that's what you want.
                                          – Tebo
                                          Nov 14 '09 at 10:26




                                          I made another post. Let me know if that's what you want.
                                          – Tebo
                                          Nov 14 '09 at 10:26


















                                          draft saved

                                          draft discarded




















































                                          Thanks for contributing an answer to Stack Overflow!


                                          • Please be sure to answer the question. Provide details and share your research!

                                          But avoid



                                          • Asking for help, clarification, or responding to other answers.

                                          • Making statements based on opinion; back them up with references or personal experience.


                                          To learn more, see our tips on writing great answers.





                                          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                                          Please pay close attention to the following guidance:


                                          • Please be sure to answer the question. Provide details and share your research!

                                          But avoid



                                          • Asking for help, clarification, or responding to other answers.

                                          • Making statements based on opinion; back them up with references or personal experience.


                                          To learn more, see our tips on writing great answers.




                                          draft saved


                                          draft discarded














                                          StackExchange.ready(
                                          function () {
                                          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f1733582%2fpass-functions-to-a-class%23new-answer', 'question_page');
                                          }
                                          );

                                          Post as a guest















                                          Required, but never shown





















































                                          Required, but never shown














                                          Required, but never shown












                                          Required, but never shown







                                          Required, but never shown

































                                          Required, but never shown














                                          Required, but never shown












                                          Required, but never shown







                                          Required, but never shown







                                          Popular posts from this blog

                                          If I really need a card on my start hand, how many mulligans make sense? [duplicate]

                                          Alcedinidae

                                          Can an atomic nucleus contain both particles and antiparticles? [duplicate]