Understand scope in PHP classes
Learn how to control property visibility in PHP classes to protect internal data and provide controlled access through public methods.
Lesson Content
So far, we’ve just dealt with the public scope, which is the default scope visibility in PHP. However, two others scope visibilities exist, named private and protected.
Let’s say we wanted to protect the author name so its value cannot be changed outside of the context of this PHP class.
If we go back to functions.php, and after this $author1 assignment, let’s assign a new value to the name property, for example Steve Jobs.
$author1 = new Author('Mark Shust');
$author1->name = 'Steve Jobs';
If you refresh the page, you’ll see that Steve is now replacing me! I don’t ever want this to happen, because over time I may have a lot of code floating around, and it’ll be impossible to predict which PHP classes change or modify other PHP class properties. So, we can add a restriction to any class property that makes sure this can’t be done.
Let’s change our class property scope to private. This completely changes the visibility of this class so it cannot be accessed outside of the scope of this class.
Here's the updated classes/Author.php:
<?php declare(strict_types=1);
class Author
{
public function __construct(
private string $name
) {}
public function getName(): string
{
return $this->name;
}
}
If we refresh our page, we will get an error that tells us that it cannot access this class property. This is exactly what we want! Let’s check our functions.php file again, and of course, PHPStorm is also telling us this.
Let’s remove this assignment of Steve Jobs. But you’ll notice that this updated scope visibility also affected the output of these class properties. This is because this class property is now completely private!
Since we now have no way to retrieve the $name property, we need to create a new class method with a public visibility, which retrieves the value of this class property.
Let’s create a new public function named getName:
<?php declare(strict_types=1);
class Author
{
public function __construct(
private string $name
) {}
public function getName(): string
{
return $this->name;
}
}
We will be sure to define a return type of string to keep our code predictable. The call to $this->name refers to the $name class property we are creating within the constructor. This function is simple — it just returns that value. This means that we can now access the name property from outside of this class.
We can now assign update the author values of the posts array to call getName() rather than the direct property reference, since this is no longer an option.
<?php declare(strict_types=1);
require('classes/Author.php');
function getPosts(): array
{
$author1 = new Author('Mark Shust');
$author2 = new Author('Betsy Sue');
return [
[
'title' => 'How to learn PHP',
'content' => 'This is how you learn PHP.',
'author' => $author1->getName(),
],
[
'title' => 'How to learn MySQL',
'content' => 'This is how you learn MySQL.',
'author' => $author1->getName(),
],
[
'title' => 'How to learn Nginx',
'content' => 'This is how you learn Nginx.',
'author' => $author2->getName(),
],
];
}
function getPostText(int $numPosts): string
{
return $numPosts === 1 ? 'post' : 'posts';
}
When we refresh the page, we can see that we can now once again access this name class property.
Scope essentially locks down how class properties are accessed outside of the context of a class. We won’t go into the protected property scope, but know that it is a slightly more open scope & visibility than private, as it lets classes of classes access class properties. private locks it down so only direct instances of a class can access the property.
Code Diff
diff --git a/classes/Author.php b/classes/Author.php
index f40e6fe..a10fbb8 100644
--- a/classes/Author.php
+++ b/classes/Author.php
@@ -3,6 +3,11 @@
class Author
{
public function __construct(
- public string $name
+ private string $name
) {}
+
+ public function getName(): string
+ {
+ return $this->name;
+ }
}
diff --git a/functions.php b/functions.php
index 5c73ce8..513bb1b 100644
--- a/functions.php
+++ b/functions.php
@@ -11,17 +11,17 @@ function getPosts(): array
[
'title' => 'How to learn PHP',
'content' => 'This is how you learn PHP.',
- 'author' => $author1->name,
+ 'author' => $author1->getName(),
],
[
'title' => 'How to learn MySQL',
'content' => 'This is how you learn MySQL.',
- 'author' => $author1->name,
+ 'author' => $author1->getName(),
],
[
'title' => 'How to learn Nginx',
'content' => 'This is how you learn Nginx.',
- 'author' => $author2->name,
+ 'author' => $author2->getName(),
],
];
}
<?php declare(strict_types=1);
class Author
{
public function __construct(
private string $name
) {}
public function getName(): string
{
return $this->name;
}
}
<?php declare(strict_types=1);
require('classes/Author.php');
function getPosts(): array
{
$author1 = new Author('Mark Shust');
$author2 = new Author('Betsy Sue');
return [
[
'title' => 'How to learn PHP',
'content' => 'This is how you learn PHP.',
'author' => $author1->getName(),
],
[
'title' => 'How to learn MySQL',
'content' => 'This is how you learn MySQL.',
'author' => $author1->getName(),
],
[
'title' => 'How to learn Nginx',
'content' => 'This is how you learn Nginx.',
'author' => $author2->getName(),
],
];
}
function getPostText(int $numPosts): string
{
return $numPosts === 1 ? 'post' : 'posts';
}
+<?php declare(strict_types=1);
+
+require('classes/Author.php');
+
+function getPosts(): array
+{
+ $author1 = new Author('Mark Shust');
+ $author2 = new Author('Betsy Sue');
+
+ return [
+ [
+ 'title' => 'How to learn PHP',
+ 'content' => 'This is how you learn PHP.',
+ 'author' => $author1->getName(),
+ ],
+ [
+ 'title' => 'How to learn MySQL',
+ 'content' => 'This is how you learn MySQL.',
+ 'author' => $author1->getName(),
+ ],
+ [
+ 'title' => 'How to learn Nginx',
+ 'content' => 'This is how you learn Nginx.',
+ 'author' => $author2->getName(),
+ ],
+ ];
+}
+
+function getPostText(int $numPosts): string
+{
+ return $numPosts === 1 ? 'post' : 'posts';
+}
<?php
declare(strict_types=1);
class Foo
{
public function __construct(
private string $name
) {}
public function getName(): string
{
return $this->name;
}
}
<?php
declare(strict_types=1);
require 'classes/Foo.php';
function getPosts(): array
{
$foo1 = new Foo('Mark Shust');
$foo2 = new Foo('Betsy Sue');
return [
[
'title' => 'How to learn PHP',
'content' => 'This is how you learn PHP.',
'author' => $foo1->getName(),
],
[
'title' => 'How to learn MySQL',
'content' => 'This is how you learn MySQL.',
'author' => $foo1->getName(),
],
[
'title' => 'How to learn Nginx',
'content' => 'This is how you learn Nginx.',
'author' => $foo2->getName(),
],
];
}
function getPostText(int $numPosts): string
{
return $numPosts === 1 ? 'post' : 'posts';
}
Join the discussion!
Comments
Want to comment on this lesson?
Log in to leave comments.