Jump to content

Archived

This topic is now archived and is closed to further replies.

anatak

passing object to function ??

Recommended Posts

Hello,

I am trying to slowly move to a more OO approach of my code but of course I have a few questions.
here is a specific problem I have that is a symptom of the general design change

I have an object to connect to my DB
[code]
$dbread = &ADONewConnection('mysql');
$dbread->Connect($Host, $SelectUser, $SelectPassword, $Database);
$dbread->debug = $debug;
[/code]

I have to pass that object to a function
[code]
$result=get_message(1, $dbread);

//here is the function
function get_message($mess, $dbread)
{
// echo $mess;
$lan= "Lan_".$_SESSION['userlanguage'];
$table01 = "language_message";
$query = "SELECT Lan_001, $lan
FROM $table01
WHERE Id = $mess;";

// echo $query;
$result = $dbread->CacheGetRow(60,$query);
// $result->Close();
return $result;

}
[/code]

but if I want to call that function from another function I have to pass the object again to the first function to pass the object to the function (get_message()) that the first function (login_table) calls.
here is an example
[code]
login_table($dbread);
//here is the function
FUNCTION login_table($dbread)
{
// comment start: START form voor login
// comment end
?>
<form method="POST" action="<?php echo $_SERVER['PHP_SELF'] . "?page=authenticate"?>" >
<?php
// comment start: START nested tabel voor login form
// comment end
?>
<table width ="100%" border ="1" cellpadding ="2" cellspacing ="0">
<tr><td align = "left" valign = "top">
<?php  $result=get_message(3, $dbread); display_message($result);?>: </td></tr>
<tr><td><INPUT size="16" type="text" name="UserHandle" /></td></tr>
<tr><td align="left" valign="top"><?php  $result=get_message(4, $dbread); display_message($result);?>: </td></tr>
<tr><td><INPUT size="16" type="password" name="UserPassword" /></td></tr>
<tr>
<td>
<input type="submit" name="submit" value="Submit">
<input type="reset" value="Clear">
</td>
</tr>
</table>
<?php
// comment start: END nested tabel voor login form
// comment end
?>
</form>
<?php
// comment start: END form voor login
// comment end
}
[/code]

I fear that this is a totally wrong approach.
Could anybody please comment on this ?
would it be better to create an object login_table ?
and does anyone know a good OO php tutorial specifically explaining what is allowed and what not ?
I learned programming in JAVA (long time ago) but I am not sure if all the JAVA OO principles are allowed in PHP.
I am mostly interessted in inheritance and public / private implementation in PHP.

Or do you think that the way it is now is fine ?
I fear that it is not a memory efficient way of coding.

kind regards
anatak

Share this post


Link to post
Share on other sites
For the 'pass object to function'-part you may change [code]$result=get_message(1, $dbread);[/code] to [code]$result=get_message(1, &$dbread);[/code]

Share this post


Link to post
Share on other sites
Hey Daniel0
can you please explain what the difference is ?

Share this post


Link to post
Share on other sites
& is the reference operator, it makes it refer to the object instead of copying it.

Share this post


Link to post
Share on other sites
Just to expand on Daniel0's reply for anyone newer to programming:

When you pass variables into functions, they're usually passed by value.  Let's say you have the following function:
[code]<?php
function some_func($arg1, $arg2){
  // does something cool
}
?>[/code]

When you call some_func from somewhere else in your code:
[code]<?php
  $val1 = 2;
  $val2 = 3;
  some_func($val1, $val2);
?>[/code]
At the point of the function call, memory is allocated and set aside for the function.  The amount of memory allocated is dependent on how many arguments and local variables the function contains.  In the case of some func, it needs to allocate memory for at least the two incoming arguments.  What happens is the [i]values[/i] that $val1 and $val2 contain are [i]copied[/i] into the newly allocated memory; hence we call this type of argument [i]passing by value[/i].

Here is a more detailed look at the memory to help illustrate:
Memory Address   |  Value | Variable
0xFF00A100            15        $val1
0xFF00A104            32        $val2

Now you call the function and memory is created, those values are copied into the new memory:
Memory Address   |  Value | Variable
0xFF00A100            15        $val1
0xFF00A104            32        $val2
.
.
.
0xFF00B100            15         $arg1
0xFF00B104            32         $arg2

For regular variables, this isn't a huge issue.  There's a lot of factors that play into this, but most "regular" variables are 4 or 8 bytes in length.  So to have the computer constantly allocate and free a small amount of memory isn't a big deal.

But let's say you're passing an object.  Let's also say this object represents an employee at your work.  In addition to containing a lot of properties such as the employee's name, address, social security, phone number, age, description, etc. it also contains a photo and a voice audio sample.  The photo and the audio sample are going to be big; at least a few hundred kilobytes, maybe even several megabytes.

Now let's say you want to pass this employee object to several functions.  You certainly don't want the computer to constantly allocate and free megabytes of memory if you can avoid it.  This is where [i]passing by reference[/i] comes in.  Instead of passing a copy of the object, we'll pass instead the memory address where the original object lives.

Memory Address   |  Value              | Variable
0xFF00A100            15                    $val1
0xFF00A104            32                    $val2
.
.
.
0xFF00B100            0xFF00A100         $arg1
0xFF00B104            0xFF00A104         $arg2


Notice now that $arg1 and $arg2 hold the [i]address[/i] of the original data.  There is a side effect to passing by reference; anything you do in the function to the data will have happened to the [i]original[/i] data!  So if you change the data and leave the function, the original data will have changed as well.  In other languages, you can declare an argument to a function as [b]const[/b] which prevents the function from changing the data; I'm not sure if a similar mechanism is provided by PHP.

A small disclaimer, I am in no way, shape, or form an expert on the internal mechanisms by which PHP passes arguments to function.  The memory examples I gave are accurate for passing pointers in C and C++.  I'm not sure exactly how references are passed internally in any language, although I can't imagine they're passed much differently than a pointer.  That said, the overall idea is accurate:

If you have large objects, that is they require lots of memory, pass them by reference to your functions but be aware that changing them within the function will change the [i]original[/i] data!

Share this post


Link to post
Share on other sites
[quote author=anatak link=topic=112100.msg454845#msg454845 date=1161337762]
I am mostly interessted in inheritance and public / private implementation in PHP.


[/quote]

If you want to use public/private ownerships you need to use PHP5. You'll find its object model much closer to Java implementation. And objects are passed by reference by default with PHP5 whereas PHP4, by default, passes copies of objects.

Share this post


Link to post
Share on other sites
[quote author=Daniel0 link=topic=112100.msg454857#msg454857 date=1161338918]
For the 'pass object to function'-part you may change [code]$result=get_message(1, $dbread);[/code] to [code]$result=get_message(1, &$dbread);[/code]
[/quote]

Is it allowed to pass by reference using the & in PHP5 ?
Or is there a drawback in using the & in php5 ?
Does PHP5 allow this or will it give problems ?

thanks
anatak

Share this post


Link to post
Share on other sites
You can still use =& in PHP 5, but it will do absolutely nothing if you're using it on objects. The default (only) behavior in PHP 5 for referring to objects does the same exact thing as using =&. If you do, indeed, want a copy of an object, then use the clone keyword - as follows.

This code is PHP 5.

[code]
<?php
$object = new Object(); //Object is some pre-defined class.
$object2 = $object;
?>[/code]

And now, if we were to print_r on $object2 and $object, we would find that they point to the same exact object. To actually create a duplicate object of $object, we'd do this:

[code]
<?php
$object2 = clone $object;
?>[/code]

Share this post


Link to post
Share on other sites
Thank you everybody.
Passing by reference is now a lot clearer to me and I realize I have to change almost all my code as I thought that passing by reference was the default behaviour.

I would like to know the scope and syntax of public private classes now.
how do you create a public class ?
what are the drawbacks of public classes ?
If I remember correctly in Java my teacher used to say that we should try to use as much private classes as public classes tended to be a risk to mess up later programming.

the problem is that I forgot most of it I am afraid.

I think he meant that a public class / variables where available to all classes and thus posed the risk that the public variables can be altered by all methods.
A private variable can only be altered by the methods defined in the class wich the variable belongs to.

Is this more or less correct ?

Share this post


Link to post
Share on other sites
[quote author=Daniel0 link=topic=112100.msg454857#msg454857 date=1161338918]
For the 'pass object to function'-part you may change [code]$result=get_message(1, $dbread);[/code] to [code]$result=get_message(1, &$dbread);[/code]
[/quote]Those are actually incorrect, runtime parameter references were disabled many moons ago. However, this doesn't appear to be what you were referring to, below is what I think you wanted:

[code]function get_message($number, &$dbread)
{
  // do stuff..
}[/code]

Share this post


Link to post
Share on other sites
I'm not sure how many times I can say this, but if you use PHP 5, you DO NOT NEED the & operator. As a matter of fact, if you use the & operator, it will break. And judging from the third or so post in, we're talking about PHP 5 here.

Note this code:
[code]#!/usr/bin/php
<?php

class Test
{
    protected $asdf;
}

$test = new Test();
$test2 &= $test;
$test3 = $test;

print_r($test);
print_r($test2);
print_r($test3);
?>[/code]

And this output:

[code] $ ./test.php
Test Object
(
    [asdf:protected] =>
)
0Test Object
(
    [asdf:protected] =>
)
[/code]

Note the 0 before the second Test Object - that's the result of the &= operator. Absolutely nothing.

Share this post


Link to post
Share on other sites
Actually, the 0 is a result of your incorrect Syntax. It's =& not &=

Try this ;)
[code]<?php

class Test
{
    protected $asdf;
}

$test = new Test();
$test2 =& $test;
$test3 = $test;

print_r($test);
print_r($test2);
print_r($test3);
?>[/code]

You'll get an E_STRICT message informing you that php5 no longer requires reference operator, and that's it. All else will continue as is in PHP4.

Share this post


Link to post
Share on other sites
well, by golly, I was wrong again. That puts me into the double digits, darn it.

Thanks for pointing it out, Jenk.

Share this post


Link to post
Share on other sites
hmm passing by reference behaves a bit weird around here :D

so I have my object dbread
[code]
$dbread = &ADONewConnection('mysql');
$dbread->Connect($Host, $SelectUser, $SelectPassword, $Database);
[/code]

and then a function wich uses that object
[code]
$result=get_message(1, &$dbread);
[/code]

here is the function
[code]
function get_message($mess, $dbread)
{
// echo $mess;
$lan= "Lan_".$_SESSION['userlanguage'];
$table01 = "language_message";
$query = "SELECT Lan_1, $lan
FROM $table01
WHERE Id = $mess;";

// echo $query;
$result = &$dbread->CacheGetRow(60,$query);
// $result->Close();
return $result;

}
[/code]

If I pass by reference with &
I get these errors

Warning: Call-time pass-by-reference has been deprecated - argument passed by value; If you would like to pass it by reference, modify the declaration of [runtime function name](). If you would like to enable call-time pass-by-reference, you can set allow_call_time_pass_reference to true in your INI file. However, future versions may not support this any longer. in c:\program files\easyphp1-8\www\kyushunetwork\public_html\index.php on line 68

If I change in the function get_message($mess, $dbread)
this line
$result = $dbread->CacheGetRow(60,$query);
into this
$result = &$dbread->CacheGetRow(60,$query);

I don't get any errors.
I am a bit confused here.
I thought to pass by reference you had to pass the object with & to the function that uses the object.
Am I creating multiple objects (using PHP4 ?) I understand that in PHP5 this is not a problem.

anatak

Share this post


Link to post
Share on other sites
http://www.phpfreaks.com/forums/index.php/topic,112100.msg456283.html#msg456283

Share this post


Link to post
Share on other sites
whoooops
sorry misviewed this.
so when you instantiate an object you don't use &
when you pass the object you don't use the &
in the function that receives the object you use the &

is this correct ?
[code]
$dbread = &ADONewConnection('mysql');
$dbread->Connect($Host, $SelectUser, $SelectPassword, $Database);
$dbread->debug = $debug;
[/code]

[code]
$result=get_message(1, $dbread);
[/code]

[code]
function get_message($mess, &$dbread)
{
// echo $mess;
$lan= "Lan_".$_SESSION['userlanguage'];
$table01 = "language_message";
$query = "SELECT Lan_001, $lan
FROM $table01
WHERE Id = $mess;";

// echo $query;
$result = &$dbread->CacheGetRow(60,$query);
// $result->Close();
return $result;

}
[/code]

and passing from function to function
[code]
login_table($dbread);
//here is the function
FUNCTION login_table(&$dbread)
{
// comment start: START form voor login
// comment end
?>
<form method="POST" action="<?php echo $_SERVER['PHP_SELF'] . "?page=authenticate"?>" >
<?php
// comment start: START nested tabel voor login form
// comment end
?>
<table width ="100%" border ="1" cellpadding ="2" cellspacing ="0">
<tr><td align = "left" valign = "top">
<?php  $result=get_message(3, $dbread); display_message($result);?>: </td></tr>
<tr><td><INPUT size="16" type="text" name="UserHandle" /></td></tr>
<tr><td align="left" valign="top"><?php  $result=get_message(4, $dbread); display_message($result);?>: </td></tr>
<tr><td><INPUT size="16" type="password" name="UserPassword" /></td></tr>
<tr>
<td>
<input type="submit" name="submit" value="Submit">
<input type="reset" value="Clear">
</td>
</tr>
</table>
<?php
// comment start: END nested tabel voor login form
// comment end
?>
</form>
<?php
// comment start: END form voor login
// comment end
}
[/code]

is this line of code then correct
[code]<?php  $result=get_message(3, $dbread); display_message($result);?>: </td></tr>[/code]
or should it be like this ? because the function login_table(&$dbread) accepts &$dbread ?
[code]<?php  $result=get_message(3, &$dbread); display_message($result);?>: </td></tr>[/code]

I am still confused on how many different objects I would have with the above code  ???

Share this post


Link to post
Share on other sites
[code]<?php

class Foo
{
    var $bar = 'foo';
    function doSomething()
    {
        $this->bar = 'foobar!';
    }
    function shoutBar()
    {
        echo $this->bar;
    }
}

function doSomething(&$object)
{
    $object->doSomething();
}

$var = new Foo;
$var->shoutBar();
doSomething($var);
$var->shoutBar();

?>[/code]

Share this post


Link to post
Share on other sites
[quote]what are the drawbacks of public classes ?
If I remember correctly in Java my teacher used to say that we should try to use as much private classes as public classes tended to be a risk to mess up later programming.[/quote]

I think you mean public/private functions

In a public function: You can access the function from within the class and outside the class (from the object)
In a private function: You can only access the function from within the class
Additionally in a static function: You can only access the function from outside the class....and not the object either

Example

[code=php:0]class Foo
  public Foo() {
  }
  public functionA($showB = false) {
    echo "A";
    if($showB)
        $this->functionB();
  }
  private functionB() {
    echo "B";
  }
  static functionC() {
      echo "Static C";
  }
}

$var = new Foo();
$var->functionA(); //would show A
$var->functionA(true); //would show AB

$var->functionB(); //would return an error because it's private
$var->functionC(); //would return an error for non-object whatever

Foo:functionC(); //would show Static C[/code]



Share this post


Link to post
Share on other sites
Just to extend on Zanus' post, you can reference a static method from within an object, however you must remember that static properties and methods are not included in the object instantiation. ergo they are not part of the object and must be used and referenced as such.

[code]<?php

class Foo
{
    static $bar;

    static function fooBarToo()
    {
        echo self::$foo;
    }

    public function fooBar()
    {
        self::fooBarToo();
    }
}

?>[/code]

This is handy for instances where you will have one function that will accomodate in all objects of that class, but you don't want that function weighing down all of the objects, such as a text formatting function or similar.

[code]<?php

class Loader
{
    private static function formatName($name)
    {
        $name = str_replace('_', ' ', $name);
        $name = str_replace(' ', '/', ucwords($name));
        return $name;
    }

    public function loadClass($className)
    {
        $className = self::formatName($className) . '.php';
        if (!is_file($className) || !is_readable($className))
        {
            throw new Loader_Exception('the file "' . $className . '" does not exist, or cannot be read');
        }
        else
        {
            include($className);
        }
    }
}

$load = new Loader;

try
{
    $load->loadClass('Path_To_My_Class.php');
}
catch (Loader_Exception $e)
{
    echo $e;
}

?>[/code]for an example of real world use.

Share this post


Link to post
Share on other sites

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.