For Programmers: Free Programming Magazines  


Home > Archive > PHP Language > May 2004 > Tricky problem with classes!









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Tricky problem with classes!
Lars Plessmann

2004-05-14, 6:30 pm

Problem: I try to store data in a objects field and read it out again.
Sounds easy, yeah. But its a bit tricky here.... ;-)


This is the class Customer.php with some setter and getter functions to
store customers data within an object.
It works.
Furthermore, it includes a synchronize method, which calls the
individual setXXX function and takes the data
from the $_POST or $_GET var.
Therefore the fieldnames from the HTML form and objectfields have to be
equal, so that data for $obj->fieldB
can be found at $_GET['fieldB']. Well, no problem, yet.

sample:
$obj->synchronize("fieldA");

will call the function setFieldA($_GET/POST['fieldA']) from
the objects methods


So this is the Customer.php (shortened to the basics we might need here):

--CODE-----------------------------------------------

...

// setter and getter of a class customer

function getName()
{
return $this->name;
}

function setName($name)
{
if(strlen($id) <= 40) {
$this->name = $name;
return true;
}
else {
return false;
}
}

...

// $obj.synchronize calls the setter function set{$PARAM} of a class
object, to fill the object with Data

function synchronize($param, $method="POST")
{
$functionName = 'set'.ucfirst($param);
if (method_exists($this, $functionName)) {
$buf = null;
if(strtoupper($method)=="POST") {
$buf = $_POST[$param];
}
elseif(strtoupper($method)=="GET") {
$buf = $_GET[$param];
}

if($buf <> null) {
return call_user_func( array($this, $functionName), $buf );
}
else {
return false;
}
}
else {
return false;
}
}

...


-----------------------------------------------------

Well. The class Customer.php itself works!
But now, I try to send data to the object via the synchronize function.
To do this, I use the following sample script, which receives data via
method GET by URL as you can see:


.../step2.php?name=JohnDoe


--CODE-----------------------------------------------

<?php

include_once 'Customer.php';

$newCust = new Customer();
$method = "GET";

if (!$newCust->synchronize("name",$method)) {
printError( "Der Name ist nicht korrekt!");
};

print "Result: ".$newCust->getName();

?>


------------------------------------------------------

Well thats all.
It should send "JohnDoe" to the $newCust->name variable and print out:

Result: JohnDoe

But in fact, it prints: Result:


To make it more clear what I need:
The expected result could be reached by doing the following from the
step2.php:

$newCust->setName($_GET['name']);

But I have so many fields and forms which change often, that this is not
an effective way!
I need to do this via my synchronize method, that calls the
corresponding setXXX function automatically.
Well, the call of the function in the class itself works, but I cannot
read the object's field at the end!
I tried putting a >>print "test: $name"<< within the setName function
and it seems to work correctly!
So the value is sored somewhere, but I don'T know where it is stored!
Maybe I write it to a wrong new object? is $this wrong? do I need to
point to $parent?

I hope anybody can help me!?

Thanks in advance,
Lars
Janwillem Borleffs

2004-05-15, 4:30 am

Lars Plessmann wrote:
> function setName($name)
> {
> if(strlen($id) <= 40) {
> $this->name = $name;
> return true;
> }
> else {
> return false;
> }
> }
>
> ...


The snipper above does not specify the origin of $id (global, class
property), so it will always resort to the else clause and therefore returns
false.


JW



Janwillem Borleffs

2004-05-15, 4:30 am

Janwillem Borleffs wrote:
> The snipper above does not specify the origin of $id (global, class
> property), so it will always resort to the else clause and therefore
> returns false.
>


Not entirely true, because when undefined, $id will be created with an empty
value.

Remove $id anyway, because it isn't used:

function setName($name) {
$this->name = $name;
return true;
}

Use require_once instead of include_once to test if the class file has been
included properly. Rather then include_once, require_once throws a fatal
error when inclusion fails.

Note: Always develop your code with the highest error_reporting level E_ALL.


JW



Lars Plessmann

2004-05-15, 5:30 am

Janwillem Borleffs wrote:

> Janwillem Borleffs wrote:
>
>
>
> Not entirely true, because when undefined, $id will be created with an empty
> value.
>
> Remove $id anyway, because it isn't used:
>
> function setName($name) {
> $this->name = $name;
> return true;
> }
>
> Use require_once instead of include_once to test if the class file has been
> included properly. Rather then include_once, require_once throws a fatal
> error when inclusion fails.
>
> Note: Always develop your code with the highest error_reporting level E_ALL.
>
>
> JW
>
>
>


Yes. You are right. $id should be $name (i'm a copy paste fool *g*)
I replaced include_once by require_once and error_reporting is set to E_ALL.
But the bug still exists!

By the way:


--------------------
function setName($name)
{
if(strlen($name) <= 40) {
$this->name = $name;
print "WRITTEN '$this->name' | ";
return true;
}
else {
return false;
}
}
--------------------

A call to setName($name) shows me "WRITTEN Testname | " if the $name is
set to "Testname". So the setter itself seems to be okay!
But after function synchronize the object could not store the value.
I see this, when I make a $obj->getName().

Same at the synch func. It goes to the step it should go:

----------------------
function synchronize($param, $method="POST")
{
$functionName = 'set'.ucfirst($param);
if (method_exists($this, $functionName)) {
$buf = null;
if(strtoupper($method)=="POST") {
$buf = $_POST[$param];
}
elseif(strtoupper($method)=="GET") {
$buf = $_GET[$param];
}

if($buf <> null) {
print "OKAY / WAS EXECUTED! ";
return call_user_func( array($this, $functionName), $buf );
}
else {
return false;
}
}
else {
return false;
}
}
--------------------------

So a $obj->synchronize("name") call with the URI of ?name=Testname
prints out the following text:

OKAY / WAS EXECUTED! WRITTEN 'Testname' |

So I think the code itself should be okay, but the data goe to a wrong
object address? Might be this the bug? So that a getName() call does not
bring he the expected data?


thanks,
Lars
Janwillem Borleffs

2004-05-15, 7:30 am

Lars Plessmann wrote:
> So I think the code itself should be okay, but the data goe to a wrong
> object address? Might be this the bug? So that a getName() call does
> not bring he the expected data?
>


See if the following works for you, it does on my test environment:

http://www.jwscripts.com/playground/sync.phps


JW



Lars Plessmann

2004-05-15, 7:30 am

Janwillem Borleffs wrote:

> Lars Plessmann wrote:
>
>
>
> See if the following works for you, it does on my test environment:
>
> http://www.jwscripts.com/playground/sync.phps
>
>
> JW
>
>
>


when I call the script with
http://127.0.0.1:8081/metallboerse/...hp?name=JohnDoe
I get this message:
------------------
Notice: Undefined property: name in C:\Programme\Apache
Group\Apache2\htdocs\metallboerse\step1.php on line 8
Result:
------------------

so I added the $name to the class Customer.
Now it runs without any error messages, but the result does not appear.
its empty:
-------------
Result:
------------


Maybe it's a register_globals=off problem, when it runs on your environment?
it doesn't run on my env. properly.
Result with the upper data should be:
-------------
Result: JohnDoe
-------------


Any idea?

Lars
Janwillem Borleffs

2004-05-15, 8:30 am

Lars Plessmann wrote:
> when I call the script with
> http://127.0.0.1:8081/metallboerse/...hp?name=JohnDoe
> I get this message:
> ------------------
> Notice: Undefined property: name in C:\Programme\Apache
> Group\Apache2\htdocs\metallboerse\step1.php on line 8
> Result:
> ------------------


Because $name isn't defined and set before getName() is called through the
synchronize() method, you will indeed get this error when you start with
calling setName().

>
> Maybe it's a register_globals=off problem, when it runs on your
> environment? it doesn't run on my env. properly.


I'm working with defaults, so register_globals is disabled. Does step1.php
contain exactly the same code as the example?


JW



Janwillem Borleffs

2004-05-15, 8:30 am

Janwillem Borleffs wrote:
> Because $name isn't defined and set before getName() is called
> through the synchronize() method, you will indeed get this error when
> you start with calling setName().
>


Mixed up getName and setName here, this sentence should read:

Because $name isn't defined and set before setName() is called
through the synchronize() method, you will indeed get this error when
you start with calling getName().


JW




Lars Plessmann

2004-05-15, 8:30 am

Janwillem Borleffs wrote:

> Lars Plessmann wrote:
>
>
>
> Because $name isn't defined and set before getName() is called through the
> synchronize() method, you will indeed get this error when you start with
> calling setName().
>


Yes, I know. I changed that and added $name to the class. Then its okay.

>
>
>
> I'm working with defaults, so register_globals is disabled. Does step1.php
> contain exactly the same code as the example?
>
>
> JW
>
>
>


Okay. I'm working with defaults too. Only few changed for gd lib were
neccessairy, but thats not the point, I think.

i started your script (after adding $name to the Customer class) via
browser by

http://127.0.0.1:8081/step1.php?name=JohnDoe

but there is no result at the end.
I get

Result:

instead of

Result: JohnDoe



Lars
Janwillem Borleffs

2004-05-15, 8:30 am

Lars Plessmann wrote:
> i started your script (after adding $name to the Customer class) via
> browser by
>
> http://127.0.0.1:8081/step1.php?name=JohnDoe
>
> but there is no result at the end.


Weird, the example works for me on both PHP 4.3 and PHP 5 default
installations as it should...

Does it work when you skip the synchronize method and call setName directly?


JW



Lars Plessmann

2004-05-15, 8:30 am

Janwillem Borleffs wrote:

> Janwillem Borleffs wrote:
>
>
>
> Mixed up getName and setName here, this sentence should read:
>
> Because $name isn't defined and set before setName() is called
> through the synchronize() method, you will indeed get this error when
> you start with calling getName().
>
>
> JW
>
>
>
>


but I defined it in the class now, and it doesn't work:


<?

class Customer {

var $name; // now its defined :-)

function getName() {
return $this->name;
}

function setName($name) {
$this->name = $name;
return true;
}

function synchronize($param, $method="POST") {
$functionName = 'set'.ucfirst($param);
if (method_exists($this, $functionName)) {
$buf = null;
if(strtoupper($method)=="POST") {
$buf = $_POST[$param];
} elseif(strtoupper($method)=="GET") {
$buf = $_GET[$param];
}

if($buf <> null) {
return call_user_func( array($this, $functionName), $buf );
} else {
return false;
}
} else {
return false;
}
}
}

$newCust = new Customer();
$method = "GET";

if (!$newCust->synchronize("name",$method)) {
print "Der Name ist nicht korrekt!";
};

print "Result: ".$newCust->getName();

?>
Lars Plessmann

2004-05-15, 8:30 am

Janwillem Borleffs wrote:

> Lars Plessmann wrote:
>
>
>
> Weird, the example works for me on both PHP 4.3 and PHP 5 default
> installations as it should...
>
> Does it work when you skip the synchronize method and call setName directly?
>
>
> JW
>
>
>


Yes. That works:

$newCust->setName("JohnDoe");

returns as expected:

Result: JohnDoe


it's tricky, isn't it!?
Janwillem Borleffs

2004-05-15, 9:30 am

Lars Plessmann wrote:
> Yes. That works:
>
> $newCust->setName("JohnDoe");
>
> returns as expected:
>
> Result: JohnDoe
>
>
> it's tricky, isn't it!?


I see what the problem is. When calling call_user_func within a class, the
object must be passed by reference in PHP 4.3. In PHP 5 it works both ways.

So the fix is to change the following line:

return call_user_func( array($this, $functionName), $buf );

into:

return call_user_func( array(&$this, $functionName), $buf );


JW




Lars Plessmann

2004-05-15, 9:30 am

Janwillem Borleffs wrote:

> Lars Plessmann wrote:
>
>
>
> I see what the problem is. When calling call_user_func within a class, the
> object must be passed by reference in PHP 4.3. In PHP 5 it works both ways.
>
> So the fix is to change the following line:
>
> return call_user_func( array($this, $functionName), $buf );
>
> into:
>
> return call_user_func( array(&$this, $functionName), $buf );
>
>
> JW
>
>
>
>


Yeah!!!!!!!!!!
You seem to be a real php guru :)
I thank you very much....

(by the way I thought about that, but I changd both $this to &$this and
that didn't work)


Lars
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com