Field method collision

It’s a question and maybe a suggestion if it’s not solved already.

Does Kirby handle field method collisions in any way? Here I have two field methods with the same method name.

field::$methods['title'] = function($field) {
	return 'Price title: ' . $field->value;
};

field::$methods['title'] = function($field) {
	if( $field->key == 'seo') {
		return 'My seo title: ' . $field->value;
	}
};

Calling them like this:

echo $page->price()->title();
echo $page->seo()->title();

In the second field method I try to only run the field method if the field key is seo and if not, don’t return anything. I was hoping it instead would return what the previous field method already had stored but it did not work like that.

Possible solutions

To have the field method understand that it should inherit the parent field method there are some ways to go. All of them has to do with what is returned.

return false; // Risky if fields want to return false
return $field;
return 'inherit';

Why it’s important

Many plugins may have the same field methods but they work differently.

1 Like

Look at the syntax: What you do when adding field methods is to set a key in the $methods array to a function. It’s just a normal array and therefore the last one overwrites the previous ones with the same name. There is no inheritance there.

What you would need to do is to check if a method with that name is already defined and then create a “backup” of it so you can call it from your new method.

Ahh. Then I think something like this would have been possible

field::$methods['title'] = function($field) {
  return 'Price title: ' . $field->value;
};

field::$methods['title'] = function($field) {
  if( $field->key == 'seo') {
    return 'My seo title: ' . $field->value;
  }

  return field::$methods['title']; // Return value of the previous field method
};

If field key is not seo it returns an object and craches the tab because the object takes time to load. Shouldn’t it return a string?

Is it possible to do something similar, but working?

No, that syntax is not going to work. You need something like this:

field::$methods['title'] = function($field) {
  return 'Price title: ' . $field->value;
};

//////////////////////////////////////

if(isset(field::$methods['title'])) {
  $titleMethod = field::$methods['title'];
}

field::$methods['title'] = function($field) use($titleMethod) {
  if($field->key == 'seo') {
    return 'My seo title: ' . $field->value;
  }
  
  // Fallback to old title method
  if($titleMethod) return $titleMethod($field);
  
  // Fallback to unchanged value
  return $field->value;
};

Advanced stuff!

Maybe I’ll try it out tomorrow for my SEO field (because I’m not completely happy with the current syntax).

Well, that’s just PHP. :slight_smile: