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
|
|
|
|
|