TYPO3: Reading the values of a TCA 'type'

2019-08-19 07:13发布

问题:

I need to show a selection of days in an event in the frontend:

in my TCA I set the field like this:

'days' => [
    'exclude' => true,
    'label' => 'choose weekdays',
    'config' => [
        'type' => 'check',
        'eval' => 'required,unique',
        'items' => [
            ['monday',''],
            ['thuesday',''],
            ['wednesday',''],
            ['thursday',''],
            ['friday',''],
            ['saturday',''],
            ['sunday',''],
        ],
        'cols' => 'inline',
    ],
],

That stores an integer in the db, but now I have to display the selected days in a fluid template in the frontend.

This is the reference regarding in the TYPO3 documentation which explains that I should check the bit-0 of values ... I've searched a lot but couldn't find anything except this question here on stack overflow, which I cannot get to work.

回答1:

I strongly recommend not to use the bitmasking feature of the check field. It's rarely worth the overhead to split the values apart again and also is a lot harder to understand for most developers.

Instead you can use a select field, in this case selectCheckBox should serve you well. Given a static list of items you will get a CSV string with the selected values which is a lot easier to split, e.g. in a getter method of an Extbase domain model. If it makes sense you can even use a relation to records instead which is even cleaner but requires additional work.

If you still want to continue with bitmasks this answer may help you.



回答2:

SOLUTION 1: using Mathias's solution mixed with the one of Dimitri L.

I wanted to give it here as a full solution to this particular question, so add this in the domain model:

/**
 * @var int
 */
protected $days;

and then following for all the days:

/**
 * Get day 1
 *
 * @return int
 */
public function getDay1()
{
    return $this->days & 0b00000001 ? 1 : 0;
}

/**
 * Set day 1
 *
 * @param int $day1
 */
public function setDay1($day1) {
    if ($day1) {
        $this->days |= 0b00000001;
    } else {
        $this->days &= ~0b00000001;
    }
}

/**
 * And so on for the other 7 days
 */

You can now use it in extbase $object->getDay1() or in fluid {object.day1}

As Mathias stated, it quickly gets very complicated, I preferred this solution since I use it only to display the days an event takes place in a week, and in a calendar so a 0 or 1 solution was just fine.

SOLUTION 2: I ended up using the decimal bitmask value from the database directly in a viewhelper: (solution is adepted for the number of checkboxes used, in my case the 7 weekdays)

use \TYPO3\CMS\Extbase\Utility\LocalizationUtility;

/**
 * News extension
 *
 * @package TYPO3
 * @subpackage tx_news
 */
class CoursedaysViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractTagBasedViewHelper
{
    /**
     * @param string $days (bitmask)
     * @return string checked weekdays seperated by /
     */
    public function render($days)
    {
        // render binary, 7 digits, split into array and reverse
        $days = decbin($days);
        $days = sprintf('%07d', $days);
        $days = str_split($days);
        $days = array_reverse($days);

        foreach($days as $day){
            $key = 'days.' . ++$a;
            if($day) $coursedays .= LocalizationUtility::translate($key, 'news_ext') . '/';
        }
        return  substr($coursedays, 0, -1);
    }
}