homepage Welcome to WebmasterWorld Guest from 54.227.40.166
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member
Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
Forum Library, Charter, Moderators: coopster & jatar k

PHP Server Side Scripting Forum

    
PHP5: Class within a class
problems using a class within a class in PHP5
elbowlobstercowstand




msg:3498304
 1:18 am on Nov 7, 2007 (gmt 0)

Narrative

Good day mates. Not from down under, but I want to visit there someday. Check it: I have an address_class that has several methods/functions. Two of the functions are to a) provide a form for users to input a state and b) to validate that input.

The address_class works great when used on it's own. However, I have a new class (let's call it new_class) where I want to use the address_class. But, I'm currently not able to do so, even though I'm almost sure it's possible.

PS: new_class is already extending another class, so I can't use that feature (can't extend multiple classes, according to php manual).

Current Code


[i]address-class.php[/i]
class my_address {
#declare vars
public $name, $label;
#input function
function input_state() {
//display an input form for the user
}
#validate function
function validate_state() {
//validate the input of the user
}
}


[i]new-class.php[/i]
class new_class extends another_class {
#declare vars
public $state, $message, ;
#this function always runs when object instantiated
function __construct() {
include_once('address-class.php');
//instantiate object
$state = new my_address();
$state->label = 'State';
$state->name = 'state';
}
#validate the state
//there's probably a way better way, but here she is
function validate_state2() {
if(!$state->validate_state()) {
$this->message[] = $message;
}
}
#do a bunch of stuff and input the state
function do_stuff() {
//do a bunch of things
//and input the state
$state->input_state();
}
}


[i]users-go-here.php[/i]
include('new-class.php');
$x = new new-class();
$x->validate_state2();

Ok. I know this seems a little kooky, but I actually have a valid reason for doing things this way (basically, to not repeat code). Anyway, this code throws some errors:

Notice: Undefined variable: state
Call to a member function validate_state() on a non-object

Anyone have any ideas on a solution? Perhaps my structure is altogether bad. Let me know, and many thanks in advance!

 

phparion




msg:3498422
 5:31 am on Nov 7, 2007 (gmt 0)

You cannot include a class within a class in PHP. However you can try including the class in the constructor of new_class and it might work. But I do not encourage doing it. What is the merit of using a class if you cannot reuse it? simple add the validate function in new_class rather than making it a separate class.

I had discussed similar topic in very detail on zend website and am giving you link AND humbly request Mods not to truncate the link. Sometimes you need to allow links to other sites as they have very good information that, at least I, cannot post here in a single reply.

Here is link http://www.zend.com/forums/index.php?t=msg&goto=2452&S=13898f738a806e520602a8a42a1498c9 [zend.com]

eelixduppy




msg:3498506
 7:50 am on Nov 7, 2007 (gmt 0)

Try moving the include outside of the class completely like the following:

include_once('address-class.php');
class new_class extends another_class {
#etc...

elbowlobstercowstand




msg:3498522
 8:12 am on Nov 7, 2007 (gmt 0)

phparion... it's definitely a small world. I read that entire thread at zend dot com prior to making my post here at webmasterworld. I thought it would get deleted, but looks like they're keeping it which is definitely in the best interest of this post (thanks Mods).

The zend dot com post was a helpful post, but I was unable to successfully apply the solution suggested. In the interest of thoroughness, I'll include it here:

{zend dot com snippet}
You can also do the include outside the class declaration all together, such as:

[code]
<?php

include("someclass.php");

class NewClass
{
private $someObj;

public function __construct()
{
$someObj = new SomeClass();
}
}

?>

This is the easiest and most common way that classes are included in PHP. The reason for doing the includes elsewhere in your code or in your class are usually for performance reasons, as it will save io by not having to include the file if it is not always needed.
{/zend dot com snippet}

eelixduppy: Thanks for the reply. I tried doing an include extraneous to the class, but that didn't seem to work.

I wonder if there is a special way I need to refer to objects when they reside in other classes? Maybe it's something similar to when you echo an item of an array, you have to put it in curly braces when using double quotes:

eg. echo "This is an item of an array {$row['key']}";

PS: I can get things to work, but it is messy. Within each function of new-class, where I want to use the address class, I have to instantiate the object (and all it's variables). Like I said, it's messy, but it sort of works. I thought the constructor would take care of this and make the new object "global" in scope to the rest of the methods in the class, but I am doing something wrong, or it is just not possible (which is hard for me to believe).

elbowlobstercowstand




msg:3498524
 8:17 am on Nov 7, 2007 (gmt 0)

The underlying question here: How does one get classes to play nicely together?

That is what I'm hoping to figure out in this thread. I'm pretty new to classes (which I try to hide by saying "instantiate" a lot), so maybe my concept for using them is skewed.

FourDegreez




msg:3498682
 1:33 pm on Nov 7, 2007 (gmt 0)

If my class uses another class, I always put the include ontop. But actually, I use require_once. It should definitely work. But you have to make sure to have the right classpath.

[edited by: FourDegreez at 1:34 pm (utc) on Nov. 7, 2007]

whoisgregg




msg:3498715
 2:21 pm on Nov 7, 2007 (gmt 0)

I have a database connection class. Anytime I write a class that needs to connect to the database, I just pass the handle to the instantiation of the database class:

$db = new dbClass('host', 'user', 'pass');
$user = new userClass($db);

Then userClass calls db functions like so:

$this->db->select_single_to_array('`table`', '`userId`, `userName`', "WHERE `userEmail`='sampl@example.com'");

Added: I also use "instantiate" a lot to cover my lack of knowledge. :) I'm sure this approach, while it works for me, isn't the "right" way.

elbowlobstercowstand




msg:3498849
 5:05 pm on Nov 7, 2007 (gmt 0)

K guys. You are definitely giving me hope. Thanks so much for replying. I'm always blown away by the humility of the people on this board, and the technability! Sometimes the best words are made up.

whoisgregg: your syntax $this->db->function_u_rule might be the magic bullet I was looking for. I have never seen this syntax before and will try it, along with an extraneous include to the parent class above the original class.

I see you passed the $db object $into the $user object.


$db = new dbClass('host', 'user', 'pass');
$user = new userClass($db);

Is that what I was missing? I didn't know you could do this. But I'm a bit confused at this point, because that means the constructor of $user would have to do something to the $db object. But does that mean you could use any methods from $db in $user? I'm betting I need to think more and write less. Sorry for the rambling.

PS: I don't know what a handle is. I mean, on an iron I do. But once I learn it, I'm going to start throwing it around like it were instantiate's birthday.

whoisgregg




msg:3498907
 6:25 pm on Nov 7, 2007 (gmt 0)

Here's what I do, in a nutshell:

userClass.php:
class userClass {
function userClass($database){
$this->db= $database;
}
function signIn($email, $password){
$signIn = $this->db->select_single_to_array( '`userTable`' , '*', "WHERE `email`='".mysql_real_escape_string($email)."' LIMIT 1;");
if($signIn!== false){
// check password, etc.
} else {
$this->errors('No user with that email exists');
return false;
}
}
... more userClass functions ...
}

Now, the database class has a function called select_single_to_array that builds the appropriate database query strings and pushes the returned data into arrays (or returns false if there was an error or no records were found).

I mean, on an iron I do. But once I learn it, I'm going to start throwing it around like it were instantiate's birthday

lol

elbowlobstercowstand




msg:3499133
 10:16 pm on Nov 7, 2007 (gmt 0)

whoisgregg: it looks like your writing the php4 class method... I'm in php5. Regardless, your code makes sense, but I still can't figure out why mine won't work. I just build two test scripts that I'll detail below with the output:

class1.php
<?php
class class1 {
public $name, $age;
public function print_name() {
echo $this->name;
}
public function print_age() {
echo $this->age;
}
}
?>

test.php
<?php
include("class1.php");
class class2 {
public $object;
public function __construct() {
$object->age = 13;
$object = new class1();
$object->name = 'skeeter';
$object->print_name();
}
public function name_and_age() {
echo "<br />$object->name is $object->age old.";
}
}
$object2 = new class2();
$object2->name_and_age();
?>

And here is the output/error I'm getting:

skeeter
Notice: Undefined variable: object in ..../test.php on line 13

Notice: Trying to get property of non-object in ..../test.php on line 13

Notice: Undefined variable: object in ..../test.php on line 13

Notice: Trying to get property of non-object in ..../test.php on line 13

is old.

I'm not even sure if this is supposed to work?!

whoisgregg




msg:3499159
 10:38 pm on Nov 7, 2007 (gmt 0)

When you set public $object in class2, you must reference it as
$this->object throughout the rest of class2.

So $object = new class1(); becomes $this->object = new class1(); and $object->print_name(); becomes $this->object->print_name();

That should get it working.

elbowlobstercowstand




msg:3499316
 4:20 am on Nov 8, 2007 (gmt 0)

Who is Gregg? I'll tell you who Gregg is... he's a freaking genius!

Thanks so much whoisgregg... your solution/update totally totally works! AND... it makes sense; and that part is huge for me. Because I don't just have a solution, but have a lesson learned.

Now go instantiate some handles. :o) (I just tried to tell my wife that joke/story and she went into a coma.)

phparion




msg:3499330
 5:01 am on Nov 8, 2007 (gmt 0)

Bad Boy, Do not scare your wife with such stuff :P

phparion




msg:3499334
 5:07 am on Nov 8, 2007 (gmt 0)

btw about Gregg's approach, it is my purely personal opinion, that it could be a better idea to inherit class rather than sending handle. In fact I would request Gregg to shed some light on this that what difference it makes to send handle in constructor and inheriting the class?

thank you

elbowlobstercowstand




msg:3499404
 7:25 am on Nov 8, 2007 (gmt 0)

phparion: Sometimes I have to tell a real human what I'm doing. Even if they fall asleep while I'm telling them. :)

I'm actually not replicating whoisgregg's handle syntax... that didn't work for my needs. I think I'm inheriting a class (see my last post on page 1 #3499133 for my example). I'm using that exact same structure, with whoisgregg's updated syntax (so it actually works).

Is that what you mean by inheriting a class? (Which, I assume, is much different than extending a class.)

phparion




msg:3499429
 8:19 am on Nov 8, 2007 (gmt 0)

Which, I assume, is much different than extending a class
really? can you please explain?

Also have you checked scope resolution operator [php.net]

[edited by: eelixduppy at 5:22 pm (utc) on Nov. 8, 2007]
[edit reason] changed link to php.net [/edit]

elbowlobstercowstand




msg:3499730
 4:00 pm on Nov 8, 2007 (gmt 0)

K. I probably shouldn't have said "much different." Like I said, I'm pretty new to classes. But I think the differences between inheriting a class and extending a class are as follows:

WARNING: note the phrase "I think" above. I haven't done thorough research on this, but here's what I know now.

My definitions: Extending = the php5 manual definition.
Inheritance = When you include (either externally or in the constructor) an existing class in a new class. You have to instantiate the existing class in the new class.

1) When extending, you can only extend once. A class can't have multiple extends.

2) The syntax in extending is shorter (and more straight forward, IMHO) than the syntax in inheritance.

3) In extends, the two classes sort of meld together. In inheritance, the objects within the inherited class need to be instantiated in order to access them.

Corrections, additions, etc. welcome definitely welcome.

PS: I've checked out the scope resolution operator b4. Haven't had much use for it, or more likely, am too ignorant to know when to use it.

whoisgregg




msg:3500000
 7:59 pm on Nov 8, 2007 (gmt 0)

btw about Gregg's approach, it is my purely personal opinion, that it could be a better idea to inherit class rather than sending handle. In fact I would request Gregg to shed some light on this that what difference it makes to send handle in constructor and inheriting the class?

See? I knew I was doing it wrong. ;)

I never understood class inheritance... Frankly the whole "make an animal class, then extend it with your dog class and cat class" metaphor never had any significance to what I do.

However, the idea that a class needs a database connection and the ability to send the handle to the correct instantiation of a db class to that class made sense to me, so I just started doing it that way. I don't want my page class and my user class to each have their own database connections anyway, I want them to all use a single database connection.

So I reuse my single db class instantiation for all the other classes that need it. I've never seen the point of making classes inherit the db class's functions since it's so easy to "tunnel" through to those functions inside the db class anyway.

I'm sure it's just my own ignorance that keeps me from being able to wrap my head around inheritance and why it's the right way to do it. I'd actually love to learn more about it. My OOP knowledge is just hacked together from making lots of mistakes.

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved