Jump to content

OOP - Properties


benanamen

Recommended Posts

In the following class, it works with or without line 4 public $num. So why is it there?

<?php
class mathematics
    {
    public $num;

    public function addTwo()
        {
        return $this->num + 2;
        }
    }


$math = new mathematics;
$math->num = 3;

echo $math->addTwo();
?>
Edited by benanamen
Link to comment
Share on other sites

PHP can add properties dynamically, but you should avoid this at any cost, because you won't get documentation, you won't get code completion, and you cannot easily distinguish between legitimate attributes which just aren't declared and plain programming errors (e. g. mistyped attributes).

 

In this particular example, it's also problematic that the attribute can be uninitialized when you use it.

Edited by Jacques1
Link to comment
Share on other sites

Appreciate the response, but when it comes to OOP I need answers really dumbed down until I get a grasp of this. I want to understand why to do things and not just do it because it works.

 

PHP can add properties dynamically

 

How does it do that?

 

but you should avoid this at any cost

 

How do you avoid it? By having the line in question? Would that line generally be public or private? Is it just because you won't get documentation or are their more reasons? Is their any special name for a property with no value like the line mentioned?

 

you won't get code completion, and you cannot easily distinguish between legitimate attributes which just aren't declared and plain programming errors

 

Lost me here. I looked up code completion and it seems to only apply to IDE's and thus far is the only place I have been aware of it. The rest is russian to me so far.

Edited by benanamen
Link to comment
Share on other sites

So now this tutorial I am studying uses another example and the same type of line previously asked about equals an empty string public $username = "";. I tried it without the empty string like public $username; and it still works. What is there to know about this?

 

Any recommendations that give detailed explanations of the code?

 

* Edit, now elsewhere I am also seeing var $some_variable; for the same type of line. So there is Public, Private, Protected and Var?

 

OOP is making my head hurt.

<?php
class Member
    {
    public $username = "";
    }
$member           = new Member();
$member->username = "Fred";
echo $member->username;
?>
Edited by benanamen
Link to comment
Share on other sites

PHP lets you do almost anything, but if you want to learn proper OOP, you should adhere to very strict standards – regardless of what the PHP interpreter says.

 

The reason why you should declare attributes (with a line saying public/protected/private $attName) is that you need to know the attributes of an object to write correct code. When I type $obj->num with a properly declared attribute, my IDE immediately gives me a lot of important information:

  • whether the attribute actually exists (I could have made a mistake)
  • the type and meaning of the attribute through the documentation
  • the initial value
  • where the attribute comes from (could be a superclass) and where it's used

With dynamically added attributes, you get none of this. You're flying blind. This may be OK for a simple test class, but when you're dealing with a complex architecture and dozens of classes, you definitely need to know what's going on. “It works” isn't enough.

 

The point of initializing an attribute (with public/protected/private $attName = ...) is to make sure the attribute has a reasonable default value as opposed to null. Unfortunately, the example code is a fairly bad example. It would make a lot more sense to assign the name through the constructor:

<?php

class Member
{
    /**
     * @var string
     */
    protected $username;

    /**
     * @param string $username
     */
    public function __construct(string $username)
    {
        $this->username = $username;
    }
}

This provides several benefits:

  • A member object is always completely initialized with a valid name. In your case, the name is initially empty.
  • PHP can check the type of the input (only in PHP 7). In your case, nothing prevents me from setting the username to 123.
  • The attribute is safe, because it cannot simply be manipulated from the outside. In your case, any part of the application can change it to any nonsense value at any time.

The latter is also the reason why attributes should almost never be public. You don't want uncontrolled changes and nonsense values. If you need to expose the attribute at all, you do it through getters and setters. A getter method simply returns the attribute value so that it can be read (but not changed) from the outside. A setter method takes one argument, validates it and assigns it to the attribute (if the value is valid). This allows the outside world to change the attribute in a controlled(!) manner.

<?php

class Member
{
    /**
     * @var string
     */
    protected $username;

    /**
     * Getter for the username
     *
     * @return string
     */
    public function getUsername()
    {
        return $this->username;
    }

    /**
     * Setter for the username; this must be omitted if the username should be read-only
     *
     * @param string $username the new username
     */
    public function setUsername(string $username)
    {
        // validation (can be much more strict)
        if ($username == '')
        {
            throw new InvalidArgumentException('Username cannot be empty');
        }

        $this->username = $username;
    }

    /**
     * @param string $username
     */
    public function __construct(string $username)
    {
        $this->username = $username;
    }
}

* Edit, now elsewhere I am also seeing var $some_variable; for the same type of line. So there is Public, Private, Protected and Var?

 

No. The var keyword comes from PHP 4 and is long obsolete. If you see it being used in a tutorial, pick a different tutorial.

Edited by Jacques1
Link to comment
Share on other sites

The reason why you should declare attributes (with a line saying public/protected/private $attName) is that you need to know the attributes of an object to write correct code.

 

That answers an upcoming question I had. With all these classes in an app, how do you know how to use them. 

 

 

Unfortunately, the example code is a fairly bad example.

 

That is the problem I am going to run into until I get this down. I wouldnt know bad OOP staring me in the face. Any OOP tutorial recommendations?

 

 

The var keyword comes from PHP 4 and is long obsolete. If you see it being used in a tutorial, pick a different tutorial.

 

This is worth it's weight in gold!

 

When you explain things the way you just did I can get a good grasp of it. All the tutorials I have seen don't really explain in detail. They just say do this, do that.

 

So, if I understand correctly I don't want to do protected $username =""; right?

Edited by benanamen
Link to comment
Share on other sites

How do you know how to use them? Well - you wrote them presumably, so use them for the thing(s) that they were designed for.

 

As for your original question. Creating a property inside a class without the declaration at the top is like creating a local variable in a normal (non-oop) function. It's local to the scope and is not known outside of that function, although your examples may lead to that being not true.

 

When you create an object property inside a method you are going against the concept of an object. An object is a well-defined thing that has properties and methods and is meant to function as the entity that it was defined as, not with additional "things" tacked on that are not defined and not known to be part of the object. IOW - it's kinda like what M$ does with their software, and we know where that gets you.

  • Like 1
Link to comment
Share on other sites

Any OOP tutorial recommendations?

 

Not really. Unfortunately, PHP isn't a great language for learning OOP, because all OOP parts have been added on top of the procedural paradigm at a very late stage. This is why they often seem unnatural and hard to understand. If you're really interested in OOP, you should consider learning it together with a language that has been designed in an object-oriented manner from the ground up. My personal favorite is Ruby (which is a scripting language), and of course there are classical OOP language like Java (which is heavier).

 

 

 

So, if I understand correctly I don't want to do protected $username =""; right?

 

In the above case, you want a protected attribute without initialization. It doesn't hurt to initialize the attribute with an empty string, but it's simply unnecessary when the name is immediately assigned within the constructor. Initialization makes sense when you don't assign a value in the constructor.

Link to comment
Share on other sites

When extending the class, does it matter if you do classname::method or if you do parent::method? Is there a best practice on this?

 

Best practice is to use parent, because it allows you do change the class names at any time. If the names are hard-coded everywhere in the methods, that's a lot more difficult.

Link to comment
Share on other sites

As for your original question. Creating a property inside a class without the declaration at the top is like creating a local variable in a normal (non-oop) function. It's local to the scope and is not known outside of that function, although your examples may lead to that being not true.

 

It actually isn't true. An attribute created within a method is a real attribute. It's not limited to the method scope in any way.

 

 

 

When you create an object property inside a method you are going against the concept of an object. An object is a well-defined thing that has properties and methods and is meant to function as the entity that it was defined as, not with additional "things" tacked on that are not defined and not known to be part of the object. IOW - it's kinda like what M$ does with their software, and we know where that gets you.

 

Dynamic properties are valid (that's why the magic methods __get() and __set() exist). They just shouldn't be used unnecessarily.

Link to comment
Share on other sites

Not really. Unfortunately, PHP isn't a great language for learning OOP, because all OOP parts have been added on top of the procedural paradigm at a very late stage. This is why they often seem unnatural and hard to understand. If you're really interested in OOP, you should consider learning it together with a language that has been designed in an object-oriented manner from the ground up. My personal favorite is Ruby (which is a scripting language), and of course there are classical OOP language like Java (which is heavier).

 

Am I better off heading straight to ruby first? Does ruby knowledge transfer over to Php OOP? Are you on any ruby help forums?

Link to comment
Share on other sites

Ruby takes a slightly different approach to OOP, but that's a good thing: It's more pure, more elegant and has many best practices already built in:

  • Every value is an object, including numbers, strings, booleans, arrays etc. Even classes are objects which allows for some interesting design choices: Ruby doesn't need the concept of static attributes or methods, because a class object can have methods and attributes just like any other object.
  • There's a clear class hierarchy with BasicObject as the root node.
  • There's no raw attribute access like in PHP. A object only exposes methods, and attributes are implemented as a getter and/or setter method together with an internal object variable. So everything I told you above is already part of the language.
  • Error handling is implemented purely with exceptions. There are no low-level errors like in PHP. So instead of fumbling with error handlers and all kinds of edge cases, you can simply wrap the main code in a begin-rescue statement (Ruby's equivalent of try-catch).

The every-value-is-an-object rule in particular makes the language very elegant. For example, instead of using a for loop, you can simply call the upto() or downto() method of an integer:

1.upto(10) do |i|
  print i
end

vs.

for ($i = 1; $i <= 10; $i++)
{
    echo $i;
}

Instead of using a foreach loop, you call the each() method of the collection object (similar to jQuery):

chars = ['H', 'e', 'l', 'l', 'o']
chars.each do |ch|
  print ch
end

vs.

$chars = ['H', 'e', 'l', 'l', 'o'];
foreach ($chars as $ch)
{
    echo $ch;
}

So, yes, I would give it a try and jump straight to Ruby. You'll learn a lot about OOP, you'll learn a new language, and you might actually like what you see.

 

Unlike PHP, Ruby has some great books (particularly the famous “pickaxe book” and a well-written introduction from the language author), code you find online is usually OK, and there are plenty of knowledgeable programmers around. If there's permanent interest, I'm sure we can open a new Ruby forum here.

 

One small warning, though: Ruby is a general-purpose language, so it's less plug-and-play when it comes to web applications. For hobby stuff, you can install the Sinatra framework and use its built-in webserver. For more serious applications, you'll need an application server like Puma behind Apache/nginx.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.