1
votes

I'm currently learning extbase and fluid. I read along this SO post TYPO3 extbase & IRRE: add existing records with 'foreign_selector' to set up a relation in my extension. I got roles and people. N people can have M roles. Now everything works fine in the backend. While in the frontend I don't see the objects when I use f:debug. My problem is that the relation isn't correctly resolved by extbase (I think?).

This is my relation class:

<?php
namespace Vendor\People\Domain\Model;
/**
 * Class PersonRoleRelation
 * @scope prototype
 * @entity
 * @package Vendor\People\Domain\Model
 */
class PersonRelation extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {
    /**
     * @var \Vendor\People\Domain\Model\Person
     */
    protected $person;
    /**
     * @var \Vendor\People\Domain\Model\Role
     */
    protected $role;
    /**     
     * @param \Vendor\People\Domain\Model\Person $person
     */
    public function setPerson($person) {
        $this->person = $person;
    }
    /**
     * @return \Vendor\People\Domain\Model\Person
     */
    public function getPerson() {
        return $this->person;
    }
    /**
     * @param \Vendor\People\Domain\Model\Role $role
     */
    public function setRole($role) {
        $this->role = $role;
    }
    /**
     * @return \Vendor\People\Domain\Model\Role
     */
    public function getRole() {
        return $this->role;
    }
}

This is entity person:

<?php
namespace Vendor\People\Domain\Model;
/**
 * Class Person
 * @scope prototype
 * @entity
 * @package Vendor\People\Domain\Model
 */
class Person extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {

    public function __construct() {
        $this->initStorageObjects();
    }

    /**
     * @return void
     */
    protected function initStorageObjects() {
        $this->roles = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
    }
    /**
     * Roles
     * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\Vendor\People\Domain\Model\PersonRelation>
     */
    protected $roles = NULL;

    /**
     * the person's first name
     * @var string
     * @validate StringLength(minimum = 3, maximum = 50)
     */
    protected $firstname;

    /**
     * the person's last name
     * @var string
     * @validate StringLength(minimum = 3, maximum = 50)
     */
    protected $lastname;

    /**
     * the person's responsibilities within the company
     * @var string
     */
    protected $role;

    /**
     * Photo
     * @var \TYPO3\CMS\Extbase\Domain\Model\FileReference
     */
    protected $photo;

    /**
     * detail text about the person
     * @var string
     * @dontvalidate
     */
    protected $description;

    /**
     * @param string $firstname
     * @return void
     */
    public function setFirstname($firstname) {
        $this->firstname = $firstname;
    }

    /**
     * @return string
     */
    public function getFirstname() {
        return $this->firstname;
    }

    /**
     * @param string $lastname
     * @return void
     */
    public function setLastname($lastname) {
        $this->lastname = $lastname;
    }

    /**
     * @return string
     */
    public function getLastname() {
        return $this->lastname;
    }

    /**
     * @param string $role
     * @return void
     */
    public function setRole($role) {
        $this->role = $role;
    }

    /**
     * @return string
     */
    public function getRole() {
        return $this->role;
    }

    /**
     * @param string $description
     * @return void
     */
    public function setDescription($description) {
        $this->description = $description;
    }

    /**
     * @return string
     */
    public function getDescription() {
        return $this->description;
    }

    /**
     * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference> $photo
     * @return void
     */
    public function setPhoto($photo) {
        $this->photo = $photo;
    }

    /**
     * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference>
     */
    public function getPhoto() {
        return $this->photo;
    }

    /**
     * @return\TYPO3\CMS\Extbase\Persistence\ObjectStorage<\Vendor\People\Domain\Model\PersonRelation>
     */
    public function getRoles() {
        return $this->roles;
    }
}
?>

and this is role:

<?php
namespace Vendor\People\Domain\Model;
/**
 * Class Role
 * @scope prototype
 * @entity
 * @package Vendor\People\Domain\Model
 */
class Role extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {

    /**
     * the role's title
     * @var string
     * @validate StringLength(minimum = 3, maximum = 50)
     */
    protected $name;

    public function __construct() {
    }

    /**
     * @param string $name
     * @return void
     */
    public function setName($name) {
        $this->name = $name;
    }

    /**
     * @return string
     */
    public function getName() {
        return $this->name;
    }
}
?>

ext_tables.sql:

CREATE TABLE tx_people_domain_model_person (
  uid int(11) NOT NULL auto_increment,
  pid int(11) DEFAULT '0' NOT NULL,
  tstamp int(11) DEFAULT '0' NOT NULL,
  crdate int(11) DEFAULT '0' NOT NULL,
  deleted tinyint(4) DEFAULT '0' NOT NULL,
  hidden tinyint(4) DEFAULT '0' NOT NULL,
  firstname varchar(225) DEFAULT '' NOT NULL,
  lastname varchar(225) DEFAULT '' NOT NULL,
  role varchar(225) DEFAULT '' NOT NULL,
  roles int(11) unsigned DEFAULT '0' NOT NULL,
  description mediumtext DEFAULT '' NOT NULL,
  photo mediumblob NOT NULL,
  PRIMARY KEY (uid),
  KEY parent (pid)
) ENGINE=InnoDB;

CREATE TABLE tx_people_domain_model_role (
  uid int(11) NOT NULL auto_increment,
  pid int(11) DEFAULT '0' NOT NULL,
  tstamp int(11) DEFAULT '0' NOT NULL,
  crdate int(11) DEFAULT '0' NOT NULL,
  deleted tinyint(4) DEFAULT '0' NOT NULL,
  hidden tinyint(4) DEFAULT '0' NOT NULL,
  name varchar(225) DEFAULT '' NOT NULL,
  PRIMARY KEY (uid)
  KEY parent (pid)
) ENGINE=InnoDB;

CREATE TABLE tx_people_domain_model_person_role_rel (
  uid_local int(11) unsigned DEFAULT '0' NOT NULL,
  uid_foreign int(11) unsigned DEFAULT '0' NOT NULL,
  sorting int(11) unsigned DEFAULT '0' NOT NULL,
  KEY uid_local (uid_local),
  KEY uid_foreign (uid_foreign)
) ENGINE=InnoDB;

TCA config:

tx_people_domain_model_person.php:

<?php
return array(
    'ctrl' => array(
        'title' => 'Person',
        'label' => 'firstname',
        'label_alt' => ',lastname',
        'label_alt_force' => TRUE,
        'tstamp' => 'tstamp',
        'crdate' => 'crdate',
        'dividers2tabs' => TRUE,
        'delete' => 'deleted',
        'enablecolumns' => array(
          'disabled' => 'hidden',
        ),
        'iconfile' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath('people') . 'ext_icon.gif'
    ),
     'types' => array(
        '1' => array('showitem' => 'firstname, lastname, role, description, photo, roles')
     ),
     'columns' => array(
        'hidden' => array(
            'exclude' => 1,
            'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.hidden',
            'config' => array(
                'type' => 'check'
            )
        ),
        'firstname' => array(
            'exclude' => 0,
            'label' => 'Vorname',
            'config' => array(
                'type' => 'input',
                'size' => 225,
            )
        ),
        'lastname' => array(
            'exclude' => 0,
            'label' => 'Nachname',
            'config' => array(
                'type' => 'input',
                'size' => 225,
            )
        ),
        'role' => array(
            'exclude' => 0,
            'label' => 'Rolle',
            'config' => array(
                'type' => 'input',
                'size' => 225,
            )
        ),
        'description' => array(
            'exclude' => 0,
            'label' => 'Beschreibung',
            'config' => array(
                'type' => 'text',
            )
        ),
        'roles' => array(
            'label' => 'Rollen',
            'config' => array(
                'type' => 'select',
                'size' => 10,
                'maxitems' => 3,
                'foreign_table' => 'tx_people_domain_model_role',
                'MM' => 'tx_people_domain_model_person_role_rel',
                // 'foreign_table' => 'tx_people_domain_model_person_role_rel',
                // 'foreign_field' => 'uid_person',
                // 'foreign_label' => 'uid_role',
                // 'foreign_selector' => 'uid_role',
                // 'foreign_unique' => 'uid_role',
                // 'foreign_sortby' => 'sorting',
            ),
        ),
        'photo' => array(
            'exclude' => 0,
            'label' => 'Foto',
            'config' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getFileFieldTCAConfig('photo', array(
                'appearance' => array(
                    'createNewRelationLinkTitle' => 'Bild hinzufügen',
                    'collapseAll' => FALSE,
                ),
                'maxitems' => 1,
            ), $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'])
        ),
     ),
);
?>

tx_domain_model_person_role_rel.php:

<?php
return array(
    'ctrl' => array(
        'title' => 'Relation Table',
        'hideTable' => TRUE,
        'sortBy' => 'sorting',
        // 'tstamp' => 'tstamp',
        // 'crdate' => 'crdate',
        // 'dividers2tabs' => TRUE,
        // 'delete' => 'deleted',
        // 'enablecolumns' => array(
        //   'disabled' => 'hidden',
        // ),
        // 'iconfile' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath('people') . 'ext_icon.gif'
    ),
     'types' => array(
        '0' => array('showitem' => 'uid_person, uid_role')
     ),
     'palettes' => array(),
     'columns' => array(
        // 'hidden' => array(
        //     'exclude' => 1,
        //     'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.hidden',
        //     'config' => array(
        //         'type' => 'check'
        //     )
        // ),
        'uid_local' => array(
            'label' => 'Person',
            'config' => array(
                'type' => 'select',
                'MM' => 'tx_people_domain_model_person_role_rel',
                'foreign_table' => 'tx_people_domain_model_person',
                'size' => 1,
                'minitems' => 0,
                'maxitems' => 1,
            ),
        ),
        'uid_foreign' => array(
            'label' => 'Rolle',
            'config' => array(
                'type' => 'select',
                'MM' => 'tx_people_domain_model_person_role_rel',
                'foreign_table' => 'tx_people_domain_model_role',
                'size' => 1,
                'minitems' => 0,
                'maxitems' => 1,
            ),
        ),
     ),
);
?>

tx_domain_model_role.php:

<?php
return array(
    'ctrl' => array(
        'title' => 'Rolle',
        'label' => 'name',
        'tstamp' => 'tstamp',
        'crdate' => 'crdate',
        'dividers2tabs' => TRUE,
        'delete' => 'deleted',
        'enablecolumns' => array(
          'disabled' => 'hidden',
        ),
        'iconfile' => \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath('people') . 'ext_icon.gif'
    ),
     'types' => array(
        '1' => array('showitem' => 'name')
     ),
     'columns' => array(
        'hidden' => array(
            'exclude' => 1,
            'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.hidden',
            'config' => array(
                'type' => 'check'
            )
        ),
        'name' => array(
            'label' => 'Bezeichnung',
            'config' => array(
                'type' => 'input',
                'size' => 225,
            )
        ),
        // 'people' => array(
        //     'label' => 'Personen',
        //     'config' => array(
        //         'type' => 'inline',
        //         'foreign_table' => 'tx_people_domain_model_person_role_rel',
        //         'foreign_field' => 'uid_role',
        //         'foreign_label' => 'uid_person'
        //     ) ,
        // )
     ),
);
?>

ext_typoscript_setup.txt:

config.tx_extbase {
    persistence {
        classes {
            Domain\People\Domain\Model\PersonRelation {
                mapping {
                    tableName = tx_people_domain_model_person_role_rel
                    columns {
                        uid_local.mapOnProperty = person
                        uid_foreign.mapOnProperty = role
                    }
                }
            }

        }
    }
}

update debug output:

Domain\People\Domain\Model\Personprototypepersistent entity (uid=1, pid=18)
   roles => TYPO3\CMS\Extbase\Persistence\ObjectStorageprototypeobject (3 items)
      000000001bb500c600007fe33c9a2f36 => Domain\People\Domain\Model\PersonRelationprototypepersistent entity (uid=1, pid=20)
         person => NULL
         role => NULL
         uid => 1 (integer)
         _localizedUid => 1 (integer)modified
         _languageUid => NULL
         _versionedUid => 1 (integer)modified
         pid => 20 (integer)
      000000001bb5002400007fe33c9a2f36 => Domain\People\Domain\Model\PersonRelationprototypepersistent entity (uid=2, pid=20)
         person => NULL
         role => NULL
         uid => 2 (integer)
         _localizedUid => 2 (integer)modified
         _languageUid => NULL
         _versionedUid => 2 (integer)modified
         pid => 20 (integer)
      000000001bb500d100007fe33c9a2f36 => Domain\People\Domain\Model\PersonRelationprototypepersistent entity (uid=3, pid=20)
         person => NULL
         role => NULL
         uid => 3 (integer)
         _localizedUid => 3 (integer)modified
         _languageUid => NULL
         _versionedUid => 3 (integer)modified
         pid => 20 (integer)
   firstname => 'Max' (3 chars)
   lastname => 'Mustermann' (10 chars)
   role => 'Rolle' (5 chars)
   photo => TYPO3\CMS\Extbase\Domain\Model\FileReferenceprototypepersistent entity (uid=25, pid=18)
   description => 'Beschreibungstext' (17 chars)
   uid => 1 (integer)
   _localizedUid => 1 (integer)modified
   _languageUid => NULL
   _versionedUid => 1 (integer)modified
   pid => 18 (integer)

So the problem is that I need to access those related objects (or the roles of a person) in the frontend. edit: I think I'm a bit confused about the type of relation I need at all right now. 1 Person can have n roles. I don't want to relate people to roles later on anyways. I just want to create roles and later on assign roles to different people. So it would be a 1:n relation I guess. If that makes it any easier.

1
put the classes here. 90% of users won't open the links.Gianmarco
You don't need the relation as a class, at least noc for TYPO3. If your application needs it though (e.g. if you need attributes on the relation), create two relations: 1:n from RolePerson to Role and 1:n from RolePerson to Person.Jost
Also, please show is the corresponding ext_tables.sql file and the TCA configuration for your models, and any TypoScript mappings, if you have done some. I think this may be a problem with a missing setter and/or naming conventions.Jost
Also I got the right number of relations objects but I can't access it's Role/Person objects.. they're NULL apparentlycaevv
What I'm trying to archieve is basically to be able to access every role that is related to the person. So I wanna have an object of class person with a class member of role.caevv

1 Answers

1
votes

The solution was to add the following methods and variables in my Person class:

/**
 * roles
 *
 * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\Domain\People\Domain\Model\Role>
 */
protected $roles = NULL;

/**
 * __construct
 */
public function __construct() {
    //Do not remove the next line: It would break the functionality
    $this->initStorageObjects();
}

/**
 * Initializes all ObjectStorage properties
 * Do not modify this method!
 * It will be rewritten on each save in the extension builder
 * You may modify the constructor of this class instead
 *
 * @return void
 */
protected function initStorageObjects() {
    $this->roles = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
}

/**
 * Adds a Role
 *
 * @param \Domain\People\Domain\Model\Role $role
 * @return void
 */
public function addRole(\Domain\People\Domain\Model\Role $role) {
    $this->roles->attach($role);
}

/**
 * Removes a Role
 *
 * @param \Domain\People\Domain\Model\Role $roleToRemove The Role to be removed
 * @return void
 */
public function removeRole(\Domain\People\Domain\Model\Role $roleToRemove) {
    $this->roles->detach($roleToRemove);
}

/**
 * Returns the roles
 *
 * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\Domain\People\Domain\Model\Role> $roles
 */
public function getRoles() {
    return $this->roles;
}

/**
 * Sets the roles
 *
 * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\Domain\People\Domain\Model\Role> $roles
 * @return void
 */
public function setRoles(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $roles) {
    $this->roles = $roles;
}