admin管理员组

文章数量:1387350

I am able to create a module with two columns, c1 and c2 in my example, but get the dreaded

Drupal\Core\Entity\Query\QueryException: 'my_2c' not found in Drupal\Core\Entity\Query\Sql\Tables->ensureEntityTable() (line 373 of core/lib/Drupal/Core/Entity/Query/Sql/Tables.php).

when I try to add it with demo2c_entity_base_field_info().

Complete enough code follows.

My demo2c.info.yml.

name: Demo With Two Column Field Type
type: module
description: Fails with hook_entity_base_field_info().
core_version_requirement: ^11.0
package: Demo

The src/Plugin/Field/FieldType/Demo2CType.php file.

<?php

namespace Drupal\demo2c\Plugin\Field\FieldType ;

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

/**
 * A field type with two integer columns.
 *
 * @FieldType(
 *   id = "demo2c_field_type",
 *   label = @Translation( "Demo Two Column Field Type" ),
 *   module = "demo2c",
 *   description = @Translation( "Fails when added with hook_entity_base_field_info()." ),
 *   default_widget = "demo2c_field_widget",
 *   default_formatter = "demo2c_field_formatter"
 * )
 */
class Demo2CType extends FieldItemBase {

    /**
     * {@inheritdoc}
     */
    public static function schema( FieldStorageDefinitionInterface $field_definition ) {
        return [ 'columns' => [ 'c1' => [ 'type' => 'int',
                                          'size' => 'normal',
                                          'not null' => FALSE ],
                                'c2' => [ 'type' => 'int',
                                          'size' => 'normal',
                                          'not null' => FALSE ] ] ] ;
    }

    /**
     * {@inheritdoc}
     */
    public function isEmpty() {
        return $this->get( 'c1' )->getValue() === NULL
            && $this->get( 'c2' )->getValue() === NULL ;
    }

    /**
     * {@inheritdoc}
     */
    public static function propertyDefinitions( FieldStorageDefinitionInterface $field_definition ) {
        $prop[ 'c1' ] = DataDefinition::create( 'integer' )->setLabel( t( 'Column One' ) ) ;
        $prop[ 'c2' ] = DataDefinition::create( 'integer' )->setLabel( t( 'Column Two' ) ) ;
        return $prop ;
    }

}

The src/Plugin/Field/FieldWidget/Demo2CWidget.php file.

<?php

namespace Drupal\demo2c\Plugin\Field\FieldWidget ;

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

/**
 * A field widget with two integer columns.
 *
 * @FieldWidget(
 *   id = "demo2c_field_widget",
 *   label = @Translation( "Demo Two Column Field Widget" ),
 *   module = "demo2c",
 *   field_types = { "demo2c_field_type" }
 * )
 */
class Demo2CWidget extends WidgetBase {

    /**
     * {@inheritdoc}
     */
    public function formElement( FieldItemListInterface $items,
                                 $delta,
                                 array $element,
                                 array &$form,
                                 FormStateInterface $form_state ) {

        $element += [ '#type' => 'fieldset' ] ;

        $element[ 'c1' ] = [ '#type' => 'number',
                             '#default_value' => $items->get( $delta )->get( 'c1' )->getValue() ?? 0,
                             '#title' => $this->t( "Column One" ) ] ;
        $element[ 'c2' ] = [ '#type' => 'number',
                             '#default_value' => $items->get( $delta )->get( 'c2' )->getValue() ?? 0,
                             '#title' => $this->t( "Column Two" ) ] ;

        return $element ;
    }
}

And the src/Plugin/Field/FieldFormatter/Demo2CFormatter.php file.

<?php

namespace Drupal\demo2c\Plugin\Field\FieldFormatter ;

use Drupal\Core\Field\FormatterBase ;
use Drupal\Core\Field\FieldItemListInterface ;

/**
 * A field formatter with two integer columns.
 *
 * @FieldFormatter(
 *   id = "demo2c_field_formatter",
 *   module = "demo2c",
 *   label = @Translation( "Demo Two Column Field Formatter" ),
 *   field_types = { "demo2c_field_type" }
 * )
 */
class Demo2CFormatter extends FormatterBase {

    /**
     * {@inheritdoc}
     */
    public function viewElements( FieldItemListInterface $items, $langcade ) {
        $elements = [] ;

        foreach( $items as $delta => $item ) {
            $c1 = $item->get( 'c1' )->getValue() ;
            $c2 = $item->get( 'c2' )->getValue() ;

            $elements[ $delta ] = [ '#markup' => "Column one: $c1, column two: $c2." ] ;
        }

        return $elements ;
    }
}

At this point, I am able to manually attach the field to users, and save the settings using Drupal's regular configuration/editing interface.

However, when I add the following in demo2c.module I get the error at the top, on save.

<?php

use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;

function demo2c_entity_base_field_info( EntityTypeInterface $entity_type ) {
    if ( $entity_type->id() === 'user' ) {

        $fields[ 'my_2c' ] = BaseFieldDefinition::create( 'demo2c_field_type' )
            ->setLabel( t( 'My Demo Two Column Field' ) )
            ->setDescription( t( "Doesn't work." ) )
            ->addConstraint( 'UniqueField' )
            ->setDisplayOptions( 'form', [ 'weight' => -1 ] ) ;

        return $fields ;
    }
}

What am I missing to make this work in the hook_entity_base_field_info()?

I am able to create a module with two columns, c1 and c2 in my example, but get the dreaded

Drupal\Core\Entity\Query\QueryException: 'my_2c' not found in Drupal\Core\Entity\Query\Sql\Tables->ensureEntityTable() (line 373 of core/lib/Drupal/Core/Entity/Query/Sql/Tables.php).

when I try to add it with demo2c_entity_base_field_info().

Complete enough code follows.

My demo2c.info.yml.

name: Demo With Two Column Field Type
type: module
description: Fails with hook_entity_base_field_info().
core_version_requirement: ^11.0
package: Demo

The src/Plugin/Field/FieldType/Demo2CType.php file.

<?php

namespace Drupal\demo2c\Plugin\Field\FieldType ;

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

/**
 * A field type with two integer columns.
 *
 * @FieldType(
 *   id = "demo2c_field_type",
 *   label = @Translation( "Demo Two Column Field Type" ),
 *   module = "demo2c",
 *   description = @Translation( "Fails when added with hook_entity_base_field_info()." ),
 *   default_widget = "demo2c_field_widget",
 *   default_formatter = "demo2c_field_formatter"
 * )
 */
class Demo2CType extends FieldItemBase {

    /**
     * {@inheritdoc}
     */
    public static function schema( FieldStorageDefinitionInterface $field_definition ) {
        return [ 'columns' => [ 'c1' => [ 'type' => 'int',
                                          'size' => 'normal',
                                          'not null' => FALSE ],
                                'c2' => [ 'type' => 'int',
                                          'size' => 'normal',
                                          'not null' => FALSE ] ] ] ;
    }

    /**
     * {@inheritdoc}
     */
    public function isEmpty() {
        return $this->get( 'c1' )->getValue() === NULL
            && $this->get( 'c2' )->getValue() === NULL ;
    }

    /**
     * {@inheritdoc}
     */
    public static function propertyDefinitions( FieldStorageDefinitionInterface $field_definition ) {
        $prop[ 'c1' ] = DataDefinition::create( 'integer' )->setLabel( t( 'Column One' ) ) ;
        $prop[ 'c2' ] = DataDefinition::create( 'integer' )->setLabel( t( 'Column Two' ) ) ;
        return $prop ;
    }

}

The src/Plugin/Field/FieldWidget/Demo2CWidget.php file.

<?php

namespace Drupal\demo2c\Plugin\Field\FieldWidget ;

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

/**
 * A field widget with two integer columns.
 *
 * @FieldWidget(
 *   id = "demo2c_field_widget",
 *   label = @Translation( "Demo Two Column Field Widget" ),
 *   module = "demo2c",
 *   field_types = { "demo2c_field_type" }
 * )
 */
class Demo2CWidget extends WidgetBase {

    /**
     * {@inheritdoc}
     */
    public function formElement( FieldItemListInterface $items,
                                 $delta,
                                 array $element,
                                 array &$form,
                                 FormStateInterface $form_state ) {

        $element += [ '#type' => 'fieldset' ] ;

        $element[ 'c1' ] = [ '#type' => 'number',
                             '#default_value' => $items->get( $delta )->get( 'c1' )->getValue() ?? 0,
                             '#title' => $this->t( "Column One" ) ] ;
        $element[ 'c2' ] = [ '#type' => 'number',
                             '#default_value' => $items->get( $delta )->get( 'c2' )->getValue() ?? 0,
                             '#title' => $this->t( "Column Two" ) ] ;

        return $element ;
    }
}

And the src/Plugin/Field/FieldFormatter/Demo2CFormatter.php file.

<?php

namespace Drupal\demo2c\Plugin\Field\FieldFormatter ;

use Drupal\Core\Field\FormatterBase ;
use Drupal\Core\Field\FieldItemListInterface ;

/**
 * A field formatter with two integer columns.
 *
 * @FieldFormatter(
 *   id = "demo2c_field_formatter",
 *   module = "demo2c",
 *   label = @Translation( "Demo Two Column Field Formatter" ),
 *   field_types = { "demo2c_field_type" }
 * )
 */
class Demo2CFormatter extends FormatterBase {

    /**
     * {@inheritdoc}
     */
    public function viewElements( FieldItemListInterface $items, $langcade ) {
        $elements = [] ;

        foreach( $items as $delta => $item ) {
            $c1 = $item->get( 'c1' )->getValue() ;
            $c2 = $item->get( 'c2' )->getValue() ;

            $elements[ $delta ] = [ '#markup' => "Column one: $c1, column two: $c2." ] ;
        }

        return $elements ;
    }
}

At this point, I am able to manually attach the field to users, and save the settings using Drupal's regular configuration/editing interface.

However, when I add the following in demo2c.module I get the error at the top, on save.

<?php

use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;

function demo2c_entity_base_field_info( EntityTypeInterface $entity_type ) {
    if ( $entity_type->id() === 'user' ) {

        $fields[ 'my_2c' ] = BaseFieldDefinition::create( 'demo2c_field_type' )
            ->setLabel( t( 'My Demo Two Column Field' ) )
            ->setDescription( t( "Doesn't work." ) )
            ->addConstraint( 'UniqueField' )
            ->setDisplayOptions( 'form', [ 'weight' => -1 ] ) ;

        return $fields ;
    }
}

What am I missing to make this work in the hook_entity_base_field_info()?

Share Improve this question asked Mar 17 at 17:27 Johann OskarssonJohann Oskarsson 8367 silver badges16 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

I figured it out, at least partially. I need to implement

    /**
     * {@inheritdoc}
     */
    public static function mainPropertyName() { return NULL ; }

in the Demo2CType class. Presumably this tells Drupal there are more than one columns in the type.

And then remove the UniqueField constraint, or the form validation fails with a different error, in the demo2c.module file.

  //->addConstraint( 'UniqueField' )

本文标签: phpDrupal 11 How do I use a custom field with multiple values programmaticallyStack Overflow