OOP beginner can't set property inside class to $_GET[] value

Hello

I’m learning OOP in PHP today. I’m trying to define a property inside a class using a value in the $_GET array.

class Pager
{
    public $page_list = array(0 => "faq", 
    						1 => "faq_02",
    						2 => "faq_03",
    						3 => "faq_04");
    						
    public $current_location = $_GET['pg'];
    
}

When I use a webpage to echo the $current_location property, like this:

$obj = new Pager;
echo 'current location is ' . $obj->current_location;

I get this error: Parse error: syntax error, unexpected T_VARIABLE in nextprev.php on line 12

btw line 12 is public $current_location = $_GET[‘pg’];

if i just assign any old string, like 'hello’, to public $current_location, this whole thing works fine.

Is there a reason why it won’t let me use $_GET ? Thanks

You cannot assign a variable to an object like that. Try this. :slight_smile:


<?php
class Pager
{
  public $current_location;
  
  public function __construct($current_location = ''){
    $this->current_location = $current_location;
  }
}

$obj = new Pager($_GET['pg']);
echo $obj->current_location;

Thanks Anthony.

As a rule, is it impossible to assign variables to class properties inside the class?

The thing is, at this stage I’m pretty sure that I want every object from this class to use $_GET[‘pg’] as its $current_location. So it seems flawed that I need to specify this every time I instantiate an object from this class.

Is it that if ANY pre-existing data comes from outside the object (e.g. from the $_GET array) and is used to set a property, it MUST be set using a method (like the constructor, for example)?

I’m just trying to understand the idea of classes and objects properly.

Yes, this is right. See the manual page on this subject. :slight_smile:

Well, you see a class is a blueprint or template for an object. A class should not contain state, an object should. Whilst you’re saying the data you need will always be at $_GET[‘pg’], the data at that location is variable.

The key to good OOP, is to make everything as generic as possible; this encourages code reuse and flexibility. Once you hard-code data into a class, you have to literally modify the class before you can change its behaviour, which kinda negates its usefulness.

Check out the Open/Closed Principle and [URL=“http://en.wikipedia.org/wiki/Single_responsibility_principle”]Single Responsibility Principle, then maybe [URL=“http://en.wikipedia.org/wiki/Solid_(object-oriented_design)”]SOLID too. I suck at explaining this stuff. :slight_smile:

All variable properties must be assigned using a method. You can assign constant values to your properties, however (see PHP: Properties - Manual)

The following code would also be valid for what you are wanting to do, but it would be considered a no-no as far as general Object oriented programming principles are concerned. You would only want to use this if you are sure you aren’t going to want to change the way your code works in the future (which is almost never the case, which is why there are general OOP principles and best practices in the first place).

class Pager
{
  public $current_location;
  
  public function __construct(){
  $this->current_location = $_GET['pg'];
  }
}

$obj = new Pager();
echo $obj->current_location;

However, the technically correct way of doing it would be to use a setter function to set the variable and a getter function to retrieve the variable and to input any information into the class where you instantiate it. This is because a class is supposed to work like a little “black box”. It is supposed to be able to be used whenever and wherever you instantiate it, under whatever circumstances. Therefore, the information it requires should be input at instantiation. So, for example, if the same class is being used later in an environment where the information contained in “pg” is coming from somewhere else (say, post data) this black box is still reusable.

However, I think most people understand that not every design situation is the same, and with all that being said, I do still write class methods that gather information directly from get, post and sessions in my web sites(though I try to do it sparingly).

Also, the reason for the getter and setter functions relates to what I said above. A setter is a function that allows you to parse and manipulate the input from one location, therefore if in the future you want to do something to ‘current_location’ before it is used elsewhere in your class, you can do that all at one location (rather than having to change it in every place it is used in your class). In case you are unfamiliar with it, this is what people mean when they talk about ‘encapsulation’. It is a difficult fancy word that for the most part simply means what I just said.

So for example:


class Pager
{
   public $current_location;
  
   public function __construct(){
      //some stuff to do
   }
   public function setCurrentLocation($currentLocation) {
     $this->current_location = $currentLocation;
   }
   public function getCurrentLocation() {
      return $this->current_location;
   }
  //now add 20 more methods filled with code using $this->current_location before the end of the class
}


Now, what if you have used $this->current_location 25 more times in your class methods, and you decide next week that you want to validate the incoming data ‘pg’? It is very convenient to have your getter and setter methods all set up for this purpose. If you had your methods grab the data raw, from the GET array every time, it would require re-writing the code 25 times.

Now setting current_location in your __construct() method could also serve this same purpose (as in anthony’s example), but once you start dealing with lots of properties and lots of methods, this gets messy fast. For a small project using the __construct() function should be sufficient.

So… my conclusion would be only grab raw data directly from your methods when you know you are not going to need to use that code differently in your design in the future. And, since you can never know the future, never do it. And yes, I am a hypocrit for saying that, as I do not follow this example purely in every case myself. :wink:

Excellent reply Joe, thanks!

The problem that you’re having stems from the fact that the declaration of the property is set at compile-time… before your app is running, so the $_GET collection doesn’t exist yet.

You need to set the property at run-time, which is why the __construct() is the perfect place to do it and achieve your desired “default state” functionality.

In general, in OO, you shouldn’t set class properties to anything in their declaration - always in the construct. It’s better for lots of things, including the above issue, as well as memory usage.