Get parent page title from Model

Hello. I’m working with a model to dynamically create the title. How do I get the value of the parent title? $this->parent()->title() doesn’t seem to work, getting a message that reads, “Using $this when not in object context”. Any insight would be appreciated.

Could you please post your complete code? Thank you!

Sure. I’m looking to use the page’s parent title and the current page’s start and end dates.

<?php
use Kirby\Cms\Page;
class SessionPage extends Page
{
  public static function create(array $props)
	{
		$start_date = strtotime($props['content']['camp_start_date']); 
		$start_date = date('m/d/Y', $start_date);
		$end_date = strtotime($props['content']['camp_end_date']); 
		$end_date = date('m/d/Y', $end_date);

		$props['content']['title'] = $this->parent()->title() .' '. $start_date .' - ' . $end_date;
		$props['slug'] = uniqid();
		$props['draft'] = false;
		return parent::create($props);
	}
}

I should note that I’m using the Custom Add Fields Plugin. That’s how I’m getting the start/end dates early on (in the create page dialog). That works as expected, but I just don’t know how to grab the parent’s title.

Is the parent dynamic or always the same page? If so, you can hardcode the page

$props['content']['title'] = page('parentpagepath')->title() .' '. $start_date .' - ' . $end_date;

The create method is a static method, so that mean that inside this static method we cannot use $this, because that only works within non-static methods.

The parent could be different.

Another option would be to create a temporary page object from the props:

public static function create(array $props)
{
    $start_date = strtotime($props['content']['camp_start_date']); 
    $start_date = date('m/d/Y', $start_date);
	$end_date = strtotime($props['content']['camp_end_date']); 
	$end_date = date('m/d/Y', $end_date);
    $props['slug'] = uniqid();
    $props['draft'] = false;
    $page = Page::factory($props);

    $props['content']['title'] = $page->parent()->title() . ' ' . $start_date . ' - ' . $end_date;

    return parent::create($props);
}

See above.

Amazing! Yes. This works, but I’m not sure why.

Where are the nitty gritty details on all this stuff? Admittedly I find myself copying and pasting and wishing for the best.

Thanks @texnixe

The problem is that to refer to call a dynamic method of a class inside a static method, you have to actually create a new instance of this class. You cannot use self in to call a non-static method.

I see. Thanks!

Hello again. I’m using the above model to dynamically build a title at the creation of the page. What if I also wanted this code to fire at the save of the page. Ideally I want the start date, end date and location to be in the title. If the user changes any of those bits of data I’ll want the title to be updated. Any insight?

For this, you would have to overwrite the update() page method and modify the input, see PageActions.php for the signature of the method.

I’m a bit over my head with this task. What might that look like? I do not have a firm (or even loose grasp of OOP). I can’t quite find documentation on how to achieve these feats with models.

I have yet to test this myself first because I’m not sure if the title is even part of $input in this method, maybe not. In that case, I guess you would have to a hook instead.

Thanks for the reply @pixelijn

This works, kind of:

public function update(array $input = null, string $language = null, bool $validate = false)
{
  
    if ($this->isDraft() === true) {
        $validate = false;
    }

    $page = parent::update($input, $language, $validate);
    $page = $page->changeTitle('Hello World');

    // if num is created from page content, update num on content update
    if ($page->isListed() === true && in_array($page->blueprint()->num(), ['zero', 'default']) === false) {
        $page = $page->changeNum($page->createNum());
    }

    return $page;
}

Or adding the new title to the $input array instead:

public function update(array $input = null, string $language = null, bool $validate = false)
{
  
   $input['title'] = 'Hallo Nachwelt';

   return parent::update($input, $language, $validate);
}

But the downside of this approache is that the title is not updated in real time but only after the page is reloaded. Which is the same as when you use a hook.

@texnixe, thank you for providing additional information on this.