0

I have created two classes User and Post. In the Post class I have created a method getPostUser that should return the User object for the passed postId. With my code, it is setting all property but when I am trying to get the value either from the Post or User object it is giving me the following error.

Fatal error: Uncaught Error: Typed property App\User\User::$phone must not be accessed before initialization in ...\www\learnphp\src\User\User.php:72 Stack trace: #0 ...\www\learnphp\index.php(18): App\User\User->getPhone() #1 {main} hrown in ...\www\learnphp\src\User\User.php on line 72

What I want to know is

  1. Is the way I am writing code correct or wrong?
  2. How to get the entire User object by passing postId?
  3. Is there any better way to write such code?

User Class

<?php

namespace App\User;


class User
{

    /**
     * @var int
     */
    private int    $userId;

    /**
     * @var string
     */
    private string $userName;

    /**
     * @var string
     */
    public string $email;

    /**
     * @var int
     */
    public int $phone;

    /**
     * User constructor.
     *
     * @param int    $userId
     * @param string $userName
     */
    public function __construct(int $userId, string $userName)
    {
        $this->userId   = $userId;
        $this->userName = $userName;
    }

    /**
     * @return string
     */
    public function getEmail()
    : string
    {
        return $this->email;
    }

    /**
     * @param string $email
     */
    public function setEmail(string $email)
    : void {
        $this->email = $email;
    }

    /**
     * @return int
     */
    public function getPhone()
    : int
    {
        return $this->phone;
    }

    /**
     * @param int $phone
     */
    public function setPhone(int $phone)
    : void {
        $this->phone = $phone;
    }


    /**
     * @return int
     */
    public function getUserId()
    : int
    {
        return $this->userId;
    }

    /**
     * @param int $userId
     */
    public function setUserId(int $userId)
    : void {
        $this->userId = $userId;
    }

    /**
     * @return string
     */
    public function getUserName()
    : string
    {
        return $this->userName;
    }

    /**
     * @param string $userName
     */
    public function setUserName(string $userName)
    : void {
        $this->userName = $userName;
    }


}

Post Class

<?php

namespace App\Post;


use App\User\User;

class Post
{
    /**
     * @var int
     */
    private int $postId;

    /**
     * @var int
     */
    private int $userId;

    /**
     * @var string
     */
    private string $userName;

    /**
     * @var string
     */
    private string $content;

    /**
     * @param string         $content
     * @param \App\User\User $user
     *
     * @return \App\Post\Post
     */
    public function createPost(string $content, User $user)
    : Post {

        $this->content  = $content;
        $this->userId   = $user->getUserId();
        $this->userName = $user->getUserName();

        $this->postId = 10; //db generated postId

        return $this;
    }

    /**
     * @param int $postId
     *
     * @return \App\User\User
     */
    public function getPostUser(int $postId)
    : User {

        if ($this->postId == $postId) {
            $user = new User($this->userId, Post::class);
            $user->setEmail('johndoe@email.com');
            $user->setPhone(457845412);

            return $user;
        }

        return NULL;

    }

    /**
     * @return int
     */
    public function getPostId()
    : int
    {
        return $this->postId;
    }

    /**
     * @param int $postId
     */
    public function setPostId(int $postId)
    : void {
        $this->postId = $postId;
    }

    /**
     * @return int
     */
    public function getUserId()
    : int
    {
        return $this->userId;
    }

    /**
     * @param int $userId
     */
    public function setUserId(int $userId)
    : void {
        $this->userId = $userId;
    }

    /**
     * @return string
     */
    public function getContent()
    : string
    {
        return $this->content;
    }

    /**
     * @param string $content
     */
    public function setContent(string $content)
    : void {
        $this->content = $content;
    }

    /**
     * @return string
     */
    public function getUserName()
    : string
    {
        return $this->userName;
    }

    /**
     * @param string $userName
     */
    public function setUserName(string $userName)
    : void {
        $this->userName = $userName;
    }


}

Index File

<?php

use App\Post\Post;
use App\User\User;

require "vendor/autoload.php";

$user = new User(7, 'johndoe');
$post = new Post();

echo '<pre>', print_r($post->createPost('This is the hello world post.', $user), TRUE);
echo $post->getPostId(), '<br>';
echo $post->getContent(), '<br>';
echo $post->getUserName(), '<br>';
echo $post->getUserId(), '<br>';


var_dump($post->getPostUser(10));

echo $user->getPhone();
yivi
  • 42,438
  • 18
  • 116
  • 138
Code Lover
  • 8,099
  • 20
  • 84
  • 154
  • 1
    `public int $phone;` tells the PHP interpreter that `$phone` is going to be an `int`. What you are doing is a [lazy initialization](https://wiki.php.net/rfc/typed-properties) and PHP doesn't like it. You can set the phone number to some dummy value I presume in the constructor, however this isn't a good idea. You better have phone number passed in the constructor for proper object properties initialization. – nice_dev Dec 17 '19 at 12:18
  • I think if you set the properties to null it should be fine – Dharman Dec 17 '19 at 12:19
  • @vivek_23 thanks for the details. How I can get the value for instance `Phone` in this case from the `Post` object method `getPostUser` as this is returning `User` object or there is no way to get the Phone number from the `Post` object and must have to use `User` object? – Code Lover Dec 17 '19 at 12:37
  • 2
    @CodeLover You would have to do `$post->getPostUser(10)->getPhone()` to get the phone number. Ideally, you should have an instance variable inside Post class which holds the user object through the lifecycle of post object. – nice_dev Dec 17 '19 at 12:47
  • For future reference: https://meta.stackoverflow.com/questions/333952/why-should-i-provide-a-minimal-reproducible-example-for-a-very-simple-sql-query – Strawberry Dec 18 '19 at 10:12

1 Answers1

-1

The error you are getting is because your $phone variable in the User class has been declared but not initiated. When you call getPhone on the User object, its phone number has no value:

$user = new User(7, 'johndoe');
$post = new Post();

echo '<pre>', print_r($post->createPost('This is the hello world post.', $user), TRUE);
echo $post->getPostId(), '<br>';
echo $post->getContent(), '<br>';
echo $post->getUserName(), '<br>';
echo $post->getUserId(), '<br>';

var_dump($post->getPostUser(10));

echo $user->getPhone(); // phone attribute has not been set

You could either initiate it in the constructor or directly inline with declaration with a default value

public int $phone = 0

As mentioned in the comments above, you should probably define a constructor for the User class with phone as a mandatory parameter if all users must have a phone number.

Concerning your will to retrieve a user by ID, the only viable way in a real application would be to set up a SQL repository and fetch the user by post ID using SQL queries (or an ORM if you are using one)

Daniel
  • 807
  • 8
  • 24