Custom attribute type, package, installation

Permalink
Long time PHP developer....new to C5 Integration. Stuck on attribute inclusion into a package and feel like i'm doing something really basic...really wrong. At this point i'm just working on the framework and trying to get it to install correctly.

Concrete version 8+

The error i get on install is "Error Call to a member function getController() on null from …\src\Attribute\Category\AbstractCategory.php:236

my package controller is located at :
\packages\blog_mailer\attributes\blog_mailer_list\controller.php
\packages\blog_mailer\attributes\blog_mailer_list\form.php

My Controller:
namespace Concrete\Package\BlogMailer\Attributes\BlogMailerList;
use Concrete\Core\Attribute\FontAwesomeIconFormatter;
class Controller extends \Concrete\Attribute\Number\Controller{
    public function getIconFormatter(){ return new FontAwesomeIconFormatter('list-alt'); }
    public function form(){
    }
}


My install routine:
$key=new Pagekey();
$key->setAttributeKeyHandle('BlogMailerList');
$key->setAttributeKeyName('Mailing List');
$key->setIsAttributeKeySearchable(false);
$key=$category->add('blog_mailer_list',$key,null,$pkg);

 
Justin1978 replied on at Permalink Reply
Justin1978
I haven't done things with attributes for a while but just judging from your code and looking at Concrete's code it seems you have to pass an existing
Concrete\Core\Entity\Attribute\Type
entity or its handle. The 'add' method you are calling installs a new instance of
Concrete\Core\Entity\Attribute\Key\Key
with the 'Type' entity or its handle as first argument. If you pass a the handle (which you are doing) then this method attempts to fetch the type from the database (it is a Doctrine model). But because no such type exists in the database, 'getController' is called on null (missing null check in the Concrete code). So I think the first thing you have to do is create the `Type' instance in your install script. You can use the
Concrete\Core\Attribute\TypeFactory::add
method to create it. Then pass it as first argument in your method call. I think this should work.

Something like this (haven't tried it so might need some tweaking):
$typeFactory = $this->application->make(TypeFactory::class);
/* @var TypeFactory $typeFactory */
$type = typeFactory->add('blog_mailer_list', 'Blog Mailer List', $pkg);
$key = new Pagekey();
$key->setAttributeKeyHandle('BlogMailerList');
$key->setAttributeKeyName('Mailing List');
$key->setIsAttributeKeySearchable(false);
$key = $category->add($type, $key, null, $pkg);