How to Access $user from a Page Model?

I need to get the name of a user from inside a Page Model. Based on a very helpful post from @texnixe, I tried this:

<?php
	
	class ArticlePage extends Page { 
		
		public function author_name(){
			if($user = kirby()->site()->user()){
				return $user->username();
			} else {
				return "USER UNKNOWN";
			}
		}
	} 

Unfortunately, this gives me “USER UNKNOWN” every time. I’ve also already tried: $this->site()->user(), and just site()->user(), they don’t work, either.

I know that it’s getting the site object without problems, because even if I try just site()->title(), it works. It seems it just can’t get the user object… Am I missing something obvious?

All guidance is much appreciated!

Ok, it seems I can get the $users collection, but not the currently logged-in $user:

<?php

class ArticlePage extends Page { 

    public function testdump(){
		
    $output = '';
		
        $user = site()->user();
	$usertype = gettype($user);
	$output .= isset($user) ? "<br>USER is set - it is type {$usertype}." : "<br>USER is NOT set.";
		
	$parentuser = parent::site()->user();
	$parentusertype = gettype($parentuser);
	$output .= isset($parentuser) ? "<br>PARENTUSER is set - it is type {$parentusertype}." : "<br>PARENTUSER is NOT set.";
		
	$users = site()->users();
	$userstype = gettype($users);
	$output .= isset($users) ? "<br>USERS is set - it is type {$userstype}." : "<br>USERS is NOT set.";
		
	$firstuser = site()->users()->first();
	$firstusertype = gettype($firstuser);
	$output .= isset($firstuser) ? "<br>FIRSTUSER is set - it is type {$firstusertype}." : "<br>FIRSTUSER is NOT set.";
		
	$curruser = site()->users()->first()->current();
	$currusertype = gettype($curruser);
	$output .= isset($curruser) ? "<br>CURRUSER is set - it is type {$currusertype}." : "<br>CURRUSER is NOT set.";
		
	$knownuser = site()->users()->find('administrator');
	$knownusertype = gettype($knownuser);
	$output .= isset($curruser) ? "<br>KNOWNUSER is set - it is type {$knownusertype}." : "<br>KNOWNUSER is NOT set.";
		
	$output .= "<br> KNOWNUSER NAME: {$knownuser->firstName()} {$knownuser->lastName()}.";
		
	return $output;
		
    }
}

The output is:

USER is set - it is type boolean.
PARENTUSER is set - it is type boolean.
USERS is set - it is type object.
FIRSTUSER is set - it is type object.
CURRUSER is set - it is type boolean.
KNOWNUSER is set - it is type object.
KNOWNUSER NAME: Site Administrator.

This is fine for my current purposes right now - I can easily use site()->users()->find() to get what I need - but I’m wondering whether the inability to get the current user inside a Page Model is by design, or by accident? Should it be reported as a bug? Am I missing something?

site()->user() returns the currently logged in user, otherwise it will return false.

if ($user = site()->user()) {
  return $user; // returns username when converted to string
} else {
  // no user logged in
}

I tried the above on a model and it worked.

What do you want to achieve?

Given that you are creating a model for an article template, wouldn’t you want to store the author in a field from the Panel? Your code would always return the currently logged in user, which will mean that every visitor will see no author.

@lukasbestle Indeed, that is what I’m doing: storing the username - but for display on the article page and blogroll, I’d like to show firstName & lastName instead.

@pedroborges if you have a look at my test code above, you’ll see that I’ve already tried site()->user(), and it didn’t work - I get a Boolean instead of the current user.

For my current scenario, the solution I came across was fine - I’ve been able to get firstName & lastName from the stored username. But I found it strange that you cannot get the current user inside the model - there would be other types of models (which might deal with private access content) that might have computed properties that need to check the current user. I guess this type of code in most cases might be better either in a controller, or plugin, but I still find it odd you can’t do it from the model.

Unless I’ve missed something…

But then you don’t want to get the current user but the user object of the username that was stored for the article:

<?php

class ArticlePage extends Page { 
  public $author;
  
  public function author() {
    if($this->author !== null) return $this->author;
    
    try {
      $user = new User(parent::author());
    } catch(\Exception $e) {
      $user = false;
    }
    
    return $this->author = $user;
  }
}

This solution requires that the author’s username is stored in the author field. The model method will then return the appropriate user object so that you can output the name of the user.

That’s because there was no user authenticated. With an authenticated user you would get an object that return true inside a conditional statement. That’s why I asked what specifically you were trying to achieve, @lukasbestle has the answer above.

@lukasbestle thank you for your solution, but as I’d shown in my second post above, I had already found a single-line solution using:

$useraccount = site()->users()->find($this->author());

This is the test for KNOWNUSER above, and it works in this scenario, because I have the username stored. It’s a single-line solution, which will always work in this case, as the “author” field is a required User field. The entire function inside the model then becomes just:

public function authorname(){
  $useraccount = site()->users()->find($this->author());
  return $useraccount->firstName() . ' ' . $useraccount->lastName();
}

@pedroborges I am, indeed, already authenticated. If I put code in the controller to get site()->user(), it gets an object. If the same code is put into the model, it gets a boolean (a falsy value, I assume). I’m calling the code from the same situation: while I’m logged in.

As I explained above, the model seems to be able to get site()->users(), but not site()->user(). If I’m indeed doing something wrong, please feel free to point it out to me.