Forum Moderators: coopster

Message Too Old, No Replies

Class/OOP question?

OOp problem

         

Matthew1980

6:01 pm on May 31, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi all,

Just a thought:-

<?php
error_reporting(E_ALL | E_STRICT);
Class foo{
//var declarations here
.
..
.
//Start functions... include relevent files
function __constructor(){
if(file_exists("../control/control.php")){
include("../control/control.php");
}
else{
echo "<div>Warning, controller file is missing</div>";
exit;
}
return $control;
}


Then from this point inside the class I refer to the array as $this->control['a_value']; (as it is defined in the control file as $control[] etc) but the more I think about it I think as I am approaching this in completely the wrong way :(

Is this the correct way to include a file from within a class or is there an alternative, because no matter what I call the physical file, there is no error thrown.. Or maybe there is but because I don't return the error message to the main index/parsing file, I only want this IN the class file, theragain this is probably where the private declaration comes in?

I am more than likely approaching this incorrectly, so I just thought I would ask those in the know. Other than that I seem to be getting the hang of classes now ;)

Cheers,
MRb

Tommybs

7:43 pm on May 31, 2010 (gmt 0)

10+ Year Member



Hi,

Not too sure I follow what you're trying to do here. I don't actually see where $control is defined unless it's in control.php but due to the lack of $this->control in the return I don't see if you're actually returning anything relating to the class instance.


Then from this point inside the class I refer to the array

What array? Are you able to explain a bit more what you are trying to achieve and what the contents of control.php might look like? As I said earlier I don't quite grasp what you want to do hence I'm not too sure what to recommend. Is it purely how to include files in classes, and if so can we ignore the $control variable and array statements above?

Sorry I couldn't be more help!

Matthew1980

8:03 pm on May 31, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi there Tommybs,

Firstly
The $control var is defined within the control.php as $control = array(); Then all as I have done is something like this:-

$control['a_value'] = "my_value";
$control['b_value'] = "another_value";

Secondly
I just want to include a file directly into my class file (check if it exists first, and throwing an error if its not there) Because at the moment I include the file in the main parsing file and pass the $control var into the class using the standard method ie:-

$myClass = new foo();
$myClass = $control;//This passes the array into the class

I just want to know if I am approaching this is the right way by using the __constructor() call and getting the $control array available to the rest of the class from the constructor..

I have read a few tutorials regarding this but just wanted to see if I could use it so that I don't have to include a file from the main parsing file...

As you may have guessed I am just starting out in OOP and I am just trying different ways of doing things ;)

Thanks for any advice/hints/tips

[EDIT]: Update:-

I have defined the var $control directly after the class name ie:-

Class foo{

var $control;

function __construct(){
if(file_exists("./control/control.php")){
include("./control/control.php");
return $this->control = $control;
}
}
}
This appears to work, but I'm not sure how to return an error if the file is missing....


Cheers,
MRb

Matthew1980

8:41 pm on May 31, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi all,

Solved it I hope ;)

Class foo{

var $control;

function __construct(){
if(file_exists("./control/control.php")){
include("./control/control.php");
return $this->control = $control;
}else{
define('CONTROL_FILE', 1);//set error as a constant so that its available throughout the script
}
}
}

Then in the main parsing file:-

<?php echo(defined('CONTROL_FILE') ? '<div>Warning the controller file is missing</div>':'');?>

It seems to do what I want it to anyway ;)

Thanks for the help anyway,

Cheers,
MRb

rocknbil

4:42 pm on Jun 1, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



If it works, it works . . . but generally, constants are somewhere else, like in a configuration file, not buried in a class. They remain constant throughout the program and are available everywhere. I also wouldn't waste memory on a constant if setting it to 1 for an error trap is it's only purpose . . . .

"script.cfg" - which will likely contain a LOT of other stuff.

define('CONTROL_FILE', $SERVER['DOCUMENT_ROOT']."/control/control.php");

then in your script,

include($SERVER['DOCUMENT_ROOT']."/conf/script.cfg");


function __construct(){
$ctrl = CONTROL_FILE;
$err=null;
if (file_exists($ctrl)){
include($ctrl);
return $this->control = $control;
}
else{ $err = "No control file"; }
return $this->error = $err;
}


Something like that, you get the idea . . .

Matthew1980

7:07 pm on Jun 1, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi there Rocknbil,

Thanks for the advice, as you can see I am still finding my feet in the world of class's and how to use them in correct context. I have looked for the reason behind using _construct() but as yet I can't find a decent definition of what _construct() actually is - I can guess from the name of it, but that is what was bugging me as I kinda know that you either shouldn't or can't access it from $ClassInstance->_construct(); because it shouldn't be accessed like that.

Sorry to go on, but I am just after a pointer on this stuff ;)

I see what you have done from your example there too, nifty, I shall play around with that when I get chance to ;)

Cheers,
MRb

Tommybs

7:32 pm on Jun 1, 2010 (gmt 0)

10+ Year Member



Hi,

__construct is what is used to create a new instance of your class, so any methods are then applied to the current class instance, hence why the keyword $this is used to represent the current instantiated method of the class. So when you call new myClass(); That is what calls the class __construct method.
Then within your class you $this->myvar refers to the myvar property of this (Which is the current object). The idea of using classes is because you have objects, that have many things in common and it allows for better maintenance of your code. i.e you can make a change to the class and all instances of it will be updated. If you find yourself doing a lot of things with arrays to store values for 1 item you should most likely use an object.

I'm not the greatest at explaining these things, but once it clicks you will know. The best advice I can give is to keep playing around with class,posting here and learning how they work. There a few good books out there, I have found "Head First Object Orientated Analyisis and Design", and "head first design patterns" to be excellent books on learning about the subject ( though I should warn you the code examples are in Java I think ).

T

Matthew1980

7:52 pm on Jun 1, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi there Tommybs,

Thanks for taking the time to explain that for me, much appreciated :)

Ok - I now understand what __construct() does, but now I have another issue which again I may be approaching incorrectly but, say I have another file I would like to include another file similar to the method as rocknbil mentions, is this possible because I would think that you can only have 1 __construct() function therefore only 1 file/return instruction.

This second file would behave in a similar way to a config file, but this time the Il8n instructions/vars etc, you get the idea.

Though the more I think of this the more I realize or at least think that the easier way would be to have a file full of constants - then at least the data is available within the entire scope of my project, therefore negating the need to include the file directly into the class, hmm, I seem to be talking my self out of that ;)

I endeavour to learn :)

Cheers,
MRb

Tommybs

8:01 pm on Jun 1, 2010 (gmt 0)

10+ Year Member



Yeah second point sounds more logical to me. Are the contents of the second file going to be exclusively for the class or are they going to be used throughout the project. If the latter, then you are definitely better off going down the constants route. If the contents are going to be specific to the type of your class then we could look at static variables. However I don't want to throw these out there if the constants are going to be used throughout the project and not just in this class

Matthew1980

8:17 pm on Jun 1, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi there Tommybs,

Logic has prevailed \0/ I have gone the constant route and now I have a working script, though I am now thinking was the former of the two options even possible if I wanted to use them just for the scope of the class? Static var's ? Looks like I shall have a look at this book you have referred to, I have heard of static functions as I have a captcha class that calls a functions statically (!$varname::phpcaptcha($input)) which works nicely.

Oh in answer to your question, the constants are only in the class for the time being, I shall more than likely do another file to act for the whole script as the project gets bigger, this keeps it cleaner semantically as I think of more things to add to it - cool!

Again, thanks for the input, much appreciated,

Cheers,
MRb

Tommybs

8:37 pm on Jun 1, 2010 (gmt 0)

10+ Year Member



Just as a quick pointer, a static variable or function does not need a specific instance of a class to be called. For instance consider the following


class myClass{
private $id;

public function __construct($i){
$this->id = $i;
}
public function getID(){
return $this->id;
}
public static function doSomthing(){
return "I don't need a class";
}

}

Basically for the function getId() to work you must have an instance of myClass otherwise it won't return anything.

$o = new myClass(1);
echo $o->getID();


For the static method however, it does not need an instance of myClass to work, it can be called using the following syntax

echo myClass::doSomething();

I've often seen these in authentication classes. The class itself might have methods for returning the current user, logging the user in etc, yet it might have a static method for displaying the login form ( your not going to show the login form if someone is logged in afterall).


Static variables are similar, they are often used for things like counters so that you can actually increment the variable everytime a function is called

public class myClass{
static $count = 0;
public function __construct(){
self::$count++;
}
}

This should increment count so you get 1,2,3,4 so on when you create a new instance as opposed to it being bound to a specific instance of the class.

Apologies if I'm going too fast at the moment, but i thought it might help to grasp what I was talking about above. I'm no expert but I've been learning with a number of books and doing examples and, it's only been recently for me but suddenly things just slide into place. The above mentioned books are excellent for grasping some of these concepts.

Matthew1980

8:51 pm on Jun 1, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi there Tommybs,

Thank you for taking the time to explain that to me, I shall read it in detail when I have more time. I have checked the books out on amazon and they seem to be highly recommended, so thanks for the heads up on those.

As with anything new, there is always the period where nothing makes sense until you actually try it. I am hoping that the time I am investing now will pay me back soon enough, it's good to add more things to your skills set, especially when there is an appraisal/review pending or there is a project you would love to be involved in :)

Again, thanks for the help,

Cheers,
MRb

penders

12:00 am on Jun 2, 2010 (gmt 0)

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



Just to pick up on something mentioned a few times above...

function __construct() {  
$ctrl = CONTROL_FILE;
$err=null;
if (file_exists($ctrl)) {
include($ctrl);
return $this->control = $control;
}
else { $err = "No control file"; }
return $this->error = $err;
}


You can't (/shouldn't) return anything from a constructor.

When you instantiate a class, an object is (nearly) ALWAYS returned:
eg. $myObject = new MyClass();
$myObject will ALWAYS be an object, regardless of anything you try to return in your __construct() method. (An exception to this is if an Exception was thrown in the constructor.)

The OOP way to check for an error occurring in the constructor (during the instantiation of the object) is to set an error state in the class itself (which is implied by rocknbil's code) and check this once the object has been instantiated. eg...

class MyClass { 
public $error = false;
public function __construct() {
// Initialise some stuff...
// But something is wrong...
$this->error = true;
}
}
$myObject = new MyClass();
if ($myObject->error) {
// An error occurred!
}


Also, your code is a bit of a mix between PHP4 and PHP5. "__construct()" is PHP5, "var $control" is PHP4 (but it still works). And you should always declare the property/method visibility (new with PHP5) ie. public, protected or private. If you don't, it is assumed to be public. In the example above, both the $error property and the __construct() method are declared as public.

Matthew1980

7:31 am on Jun 2, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi there Penders,

Now I am confused :/ Your saying that it is 'the right way' or 'better coding practice' to have __construct() not return anything? The entire reason I posted was to ask if I was right to use this way to include a file (control.php) directly into the class.

I have this working now, so I am happy with it, but if you are saying that I am using the __construct() in the wrong context, (to include a file that is ONLY used in context with the class) how else do you include a file directly into a class and return the contents of the file (in this case a defined array) by attaching it to the $this->myVar = $control;

This is what I think may be correct (using your example):-


[size=2]class MyClass {
public $error = false;
[b]public $control;[/b] //define var in correct php way ;)
public function __construct() {
if(file_exists(PATH_TO_FILE."control.php")){
include(PATH_TO_FILE."control.php");
[b]$this->control = $control;[/b]//assign array name to declared class var
}else{
// But something is wrong...
$this->error = true;
}
}
}[/size]


Yes, with respect to 'mix and match', my ignorence to the fact as I am mixing php4 & php5, the tutorial I was reading that set me off did not explain that to me, so thanks for the pointer there ;)

[EDIT:] Since reading over these posts, I have understood why you shouldn't return anything from the __construct() because assigning $this->control = $control; means that its is already available in the class - consider the penny dropped :)

Cheers,
MRb

penders

8:32 am on Jun 2, 2010 (gmt 0)

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



Yeah, I think you've got it. Sorry, I wasn't touching on the include - yes, that is fine. In fact I quite often do something very similar in order to import user defined settings into a class instance (or read from an INI file, or read from a DB, etc.).

Just to reiterate the inability to return anything from the constructor (when a new class is instantiated)...

class MyClass {  
public $error = false;
public function __construct() {
// Initialise some stuff...
// But something is wrong...
return false;
}
}
$myObject = new MyClass();
if ($myObject == false) {
// This NEVER happens, because $myObject is an object, not (bool)false
}


It's not "because assigning $this->control = $control; means that its is already available in the class" (although that is true), it's simply that you can't return anything when the __construct() method is called as part of the class instantiation (different to when you call a class method in the usual way).