Drupal 8 Field Plugin带字段类型managed_file

时间:2016-08-17 11:59:36

标签: drupal-8

我正在创建一个包含引号,名称,公司和可选头像的新字段类型。

我的代码在

下面
modules/mymodule/src/FieldType/Testimonial.php

<?php

namespace Drupal\dods\Plugin\Field\FieldType;

use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\TypedData\DataDefinition;
use Drupal\Core\Field\FieldStorageDefinitionInterface as StorageDefinition;

/**
 * Plugin implementation of the 'Testimonial' field type.
 *
 * @FieldType(
 *   id = "Testimonial",
 *   label = @Translation("Testimonial"),
 *   description = @Translation("Stores Testimonial Information."),
 *   category = @Translation("Custom"),
 *   default_widget = "TestimonialDefaultWidget",
 *   default_formatter = "TestimonialDefaultFormatter"
 * )
 *
 * Class Testimonial
 * @package Drupal\dods\Plugin\Field\FieldType
 */
class Testimonial extends FieldItemBase
{

/**
 * Field type properties definition.
 *
 * Inside this method we defines all the fields (properties) that our
 * custom field type will have.
 *
 * @param StorageDefinition $storage
 * @return array
 */
public static function propertyDefinitions(StorageDefinition $storage)
{
    $properties['testimonial_quote'] = DataDefinition::create('string')->setLabel(t('Quote'));
    $properties['testimonial_name'] = DataDefinition::create('string')->setLabel(t('Name'));
    $properties['testimonial_company'] = DataDefinition::create('string')->setLabel(t('Company'));
    $properties['testimonial_headshot'] = DataDefinition::create('integer')->setLabel(t('Headshot'));

    return $properties;
}

/**
 * Field type schema definition.
 *
 * Inside this method we defines the database schema used to store data for
 * our field type.
 * @param StorageDefinition $storage
 * @return array
 */
public static function schema(StorageDefinition $storage)
{
    $schema['columns']['testimonial_quote'] = ['type' => 'text'];
    $schema['columns']['testimonial_name'] = ['type' => 'char', 'length' => 100];
    $schema['columns']['testimonial_company'] = ['type' => 'char', 'length' => 100];
    $schema['columns']['testimonial_headshot'] = ['type' => 'int'];

    return $schema;
}

/**
 * Define when the field type is empty.
 *
 * This method is important and used internally by Drupal. Take a moment
 * to define when the field type must be considered empty.
 *
 * @return bool
 */
public function isEmpty()
{
    return empty($this->get('testimonial_quote')->getValue()) && empty($this->get('testimonial_name')->getValue()) && empty($this->get('testimonial_company')->getValue());
}

}

我的小部件看起来像这样

modules/mymodule/src/Plugin/Field/FieldWidget/TestimonialDefaultWidget.php

<?php

namespace Drupal\dods\Plugin\Field\FieldWidget;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;

/**
 * Plugin implementation of the 'TestimonialDefaultWidget' widget.
 *
 * @FieldWidget(
 *   id = "TestimonialDefaultWidget",
 *   label = @Translation("Testimonial Information"),
 *   field_types = {
 *     "Testimonial"
 *   }
 * )
 *
 * Class TestimonialDefaultWidget
 * @package Drupal\dods\Plugin\Field\FieldWidget
 */
class TestimonialDefaultWidget extends WidgetBase
{

/**
 * Define the form for the field type.
 *
 * Inside this method we can define the form used to edit the field type.
 *
 * @param FieldItemListInterface $items
 * @param int $delta
 * @param array $element
 * @param array $form
 * @param FormStateInterface $formState
 * @return array
 */
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $formState)
{
    $element['testimonial_quote'] = [
        '#type' => 'textarea',
        '#title' => t('Quote'),
        '#default_value' => isset($items[$delta]->testimonial_quote) ? $items[$delta]->testimonial_quote : null,
        '#empty_value' => '',
        '#placeholder' => t('Quote'),
    ];
    $element['testimonial_name'] = [
        '#type' => 'textfield',
        '#title' => t('Name'),
        '#default_value' => isset($items[$delta]->testimonial_name) ? $items[$delta]->testimonial_name : null,
        '#empty_value' => '',
        '#placeholder' => t('Name'),
    ];
    $element['testimonial_company'] = [
        '#type' => 'textfield',
        '#title' => t('Company'),
        '#default_value' => isset($items[$delta]->testimonial_company) ? $items[$delta]->testimonial_company : null,
        '#empty_value' => '',
        '#placeholder' => t('Company'),
    ];

    $element['testimonial_headshot'] = array(
        '#type' => 'managed_file',
        '#upload_validators' => array(
            'file_validate_extensions' => array('gif png jpg jpeg'),
            'file_validate_size' => array(25600000),
        ),
        '#required' => false
    );

    return $element;
}

}

一切看起来很好,但是当我尝试保存任何东西时,我都会收到此错误

此值应为正确的基本类型。

任何想法我都会感激我碰到了一堵砖墙:(

更新

感觉有点hacky但是为了得到这个工作我必须做以下

添加formElement()

$element['testimonial_headshot_revision'] = [
        '#type' => 'hidden',
        '#default_value' => isset($items[$delta]->testimonial_headshot) ? $items[$delta]->testimonial_headshot : null
    ];

在同一个文件中添加一个新功能,如此

/**
 * {@inheritdoc}
 */
public function massageFormValues(array $values, array $form, FormStateInterface $form_state)
{
    foreach ($values as &$value) {
        if (count($value['testimonial_headshot'])) {
            foreach ($value['testimonial_headshot'] as $fid) {
                $value['testimonial_headshot'] = $fid;
            }
        } else {
            $value['testimonial_headshot'] = $value['testimonial_headshot_revision'] !== '' ? $value['testimonial_headshot_revision'] : '0';
        }

    }

    return $values;
}

1 个答案:

答案 0 :(得分:0)

这是因为您将testimonial_headshot定义为int,但提供了文件上传小部件。作为一般提示:每当你编程&#34;新&#34;这些东西,看看你是否能找到与你尝试做的类似的东西,然后只是扩展/修改它。

实施例: 对我来说,你的新领域基本上是一个带有一些额外文本字段的图像字段。所以你可以做的是查看ImageItem字段类型并使用testimonial_quote等扩展它。

所以你的新字段类型可能如下所示:

class TestimonialItem extends ImageItem

然后:

public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
    // get the image item properties
    $properties = parent::propertyDefinitions($field_definition);

    // if you don't need some properties of the parent do this:
    unset($properties['some_property_of_parent']);

    // add your thing
    $properties['testimonial_quote'] = DataDefinition::create('string')
      ->setLabel(t('Quote'))
      ->setDescription(t("This is the quote of the testimonial"));

    // etc.

    return $properties;
}

这是主要的想法,对schema()方法和小部件类也这样做。抓住父母并扩展它。

希望这有帮助。