Forum Moderators: coopster

Message Too Old, No Replies

I have to ask as I just don't know this

Passing a class function to another class

         

Matthew1980

7:21 pm on Oct 15, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi there people of WebmasterWorld,

Example

class MyClass{

public function foo($error_string){
//code here
}
}

class OtherClass{
public function bar(){<-- don't know what to pass it as here?
//code here
mysql_query()
}
}

$FirstClass = new MyClass();
$SecondClass = new OtherClass();

//example
$query = mysql_query(...queryStuffHere....) or $FirstClass->foo(mysql_error());

$SecondClass->bar($FirstClass->foo(mysql_error()));

I have no idea how to do what I am trying to do, I have only being learning classes over the last couple of months, and I have now come to a point where I need to pass the method of one class into another, preferably without passing it as a parameter of the 'second class' function.

I think what I am trying to do is make a method available from one class available inside another class, but I am driving blind here, and as I don't know what I am looking for in the manual, I can't find it!

If I have a logic flaw in this concept please tell me as I would rather do it right than completely screw it up...

Cheers,
MRb

Matthew1980

8:24 pm on Oct 15, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



UPDATE:-

After consulting the manual, I see that using the gloabl keyword from INSIDE the method/function I want to apply the 'other class' function to, works, it grabs the data from my already instantiated class, then all I have to do is point to the desired function.. Cool!

Unless there is an easier way to do this, I think I have answered my own question..

Cheers anyway,
MRb

nanat

4:12 am on Oct 16, 2010 (gmt 0)

10+ Year Member



hi matthex1980 i think this example will help you

try
{
$query = mysql_query(ect...)
catch(Exception $e)
{
$FirstClass->foo("error");// return false
}


i think this parameter is illegal for error handle.. $FirstClass->foo(mysql_error());

Matthew1980

9:44 am on Oct 16, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi there nanat,

Thanks for the suggestion, it seems that using global as a key word within a method allows php to fetch everything associated with that object and makes it available within the other class. I have it functional now, but I have to declare a new function to 'import' the other function for use in the first class! Sounds a little convoluted to me, hence why I think it's not exactly good practice.

Also, I have error_reporting(E_ALL|E_STRICT|E_DEPRECATED); turned on, and as yet it's not moaning!

I haven't used try/catch before, so I'll have a read up on it later on today.

Thanks for the pointer though.

Cheers,
MRb

Matthew1980

8:18 pm on Oct 17, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi all,

Ack! I still can't work this out, I am starting to think that it isn't meant to be a thing done in OOP - should you be able to make methods interchangeable within class context?

I even wondered if I could do it though __construct() so that I don't have to effectively have this function seconded from the first class via a third party 'reference' function, but you can't return values from __construct() and you certainly can't use the Global keyword in this way either.

Could anyone give me food for thought on this, I really don't want to rewrite my SQL handler class just because I can't append a function to another class.. I am stumped. But I endeavour to see this to a 'good practise' sollution.

Cheers,
MRb

penders

10:51 am on Oct 18, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I would have said using the global keyword in this way was best avoided. Do you really need to pass the method of one class to another? In your example, you are passing the output of foo(), not 'foo' itself. You can pass method names as strings and later call_user_func() [uk.php.net] inside of the other method/function and you can pass a class instance to another class, but I don't think it is necessary in this case.

Do you ever need more than 1 instance of MyClass?

You could make your SQL handler class (MyClass) into a static [php.net] class, if it is being called globally - although this might require a bit of rewriting. The static class is never instantiated, but called like so...
class MyClass{  
public static function foo($error_string){
//code here
}
}
$query = mysql_query(...queryStuffHere....) or MyClass::foo(mysql_error());


And this could be called from any scope eg. inside a method of another class. You can't use $this inside a static method, use self:: instead. And you might want to declare the __contruct() method as private to prevent direct instantiation.

Or you could make MyClass into a singleton [php.net] - the class is instantiated, but the singleton pattern ensures you only ever have 1 instance of the class.

Or, may be OtherClass could simply extend MyClass?

enigma1

11:10 am on Oct 18, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You don't need to pass any methods, you need to have the objects available at any time. You will need to think in OOP and simplify the code initially. So get rid of the OOP details in PHP5 and concentrate in the structure.

so create an interface to handle common objects

// Objects Interface Begin
class common_stuff {
static $_objects = array();

static function create($name) {
if( !class_exists($name) ) {
die('invalid class: ' . $name);
}
if( !isset(common_stuff::$_objects[$name]) ) {
common_stuff::$_objects[$name] = new $name;
}
}

static function &get($name) {
common_stuff::create($name);
return common_stuff::$_objects[$name];
}

static function get_array() {
$result_array = array();
$args = func_get_args();

foreach( $args as $class ) {
$result_array[$class] =& common_stuff::get($class);
}
return $result_array;
}
}
// Objects Interface End


Now create the common helpers lets say for database and sessions

class sql_handlers {

function query($string) {
$result_array = array('empty sql_handlers array');
// sql query or $this->error()
// .......
return $result_array;
}

function num_rows($resource) {
$result = 0;
// num_rows
// .......
return $result;
}
function error() {
$qerr = mysql_error();
if( !empty($qerr) ) {
// An error occurred
echo $qerr;
}
return !empty($qerr);
}

}

class session_handlers {
var $_data;
function session_handlers() {
$this->_data = array('session default data');
}

function start() {
// Start session
return true;
}

function &get() {
return $this->_data;
}

}


And finally create the application section to utilize the common helpers. The application doesn't need to know the interface details but it needs to have a way to get all objects it needs at any time.


class foo {
function some_function() {
// Get multiple objects
extract(common_stuff::get_array('sql_handlers', 'session_handlers'));

// Utilize the objects and do something
$string = 'select from table........';
$result_array = $sql_handlers->query($string);
print_r($result_array);

$session_handlers->start($string);
$result_array =& $session_handlers->get();
print_r($result_array);

// Get a single object - complicated use the get_array instead
$cSQL =& common_stuff::get('sql_handlers');
$result_array = $cSQL->query($string);
$rows = $cSQL->num_rows($string);

print_r($result_array);
echo $rows;
}
}

echo '<pre>';
$cfoo = new foo;
$cfoo->some_function();
echo '</pre>';

So the interface section handles the objects then the application code utilizes it.

In this example the sql class is instantiated the moment another piece of code needs it and only keeps a single object in the objects array. If an objects is already present is returned. If you wanted to sql error handling you do it inside the sql_handlers class. It's the one that performs the queries.

The extract method makes a series of objects immediately available to any function that needs them, therefore the application needs to know the methods of the classes (ie: it needs to know there is a method called query in order to use it). An alternative call is also shown, if you wanted say a single object reference. Object instantiation is dynamic, totally transparent to the application and to the helper classes.

Because the particular helper classes typically require a single instance in a script, with this example the interface is static.

So in OOP break down the requirements establish a logic for the primitive objects and write the application to utilize them.

In your example if you wanted to print the mysql error you do that in the sql class and/or have other functions from other classes to print it via an interface because they can call the helper methods having the objects available at any time. So this class that you have now,

class OtherClass{
function bar() {
// get the sql object
extract(common_stuff::get_array('sql_handlers'));
// do queries, print the error get result
// query...... $sql_handlers->query('select....')
if( $sql_handlers->error() ){
die('Error');
}
}
}

doesn't need to get any arguments, it retrieves the sql object and invokes an sql method to print the error if it exists. And also it doesn't use directly the mysql methods but it provides the helper making the code more portable to be used with other database types because and you don't need to change the application details when you port it. Usually you have the sql methods print the error as it is typically a critical/syntax one if the query fails.

Matthew1980

12:25 pm on Oct 18, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi all,

Penders & Enigma1, Thank you very much for your detailed answers, you have given me plenty of things to think about here. I shall have a play with this later on, and see what I come up with. Once I have something that I would consider as a working model that does what I want it to, I shall post an update, and let you know how things turn out.

Thank you,
MRb