2

I'm trying to create a custom module and found out that it's causing the following error message to appear:

EntityMalformedException: Missing bundle property on entity of type node. in entity_extract_ids() (line 7721 of ~/includes/common.inc).

if (!isset($entity->{$info['entity keys']['bundle']}) || $entity->{$info['entity keys']['bundle']} === '') {
  throw new EntityMalformedException(t('Missing bundle property on entity of type @entity_type.', array('@entity_type' => $entity_type)));
}

I'm using xdebug setup with netbeans to debug the error and found out what is causing the culprit.

I found out it was a specific field I added in my module that looks like this:

$form['base']['st-volume-pricing']['add'] = array(
'#type' => 'button',
'#value' => t('Add'),
'#name' => 'add_row',
'#limit_validation_errors' => array(
  array('price'),
  array('till-amount'),
),
'#ajax' => array(
  'callback' => 'bulk_and_user_pricing_add_volume_standard_ajax_callback',
  'wrapper' => 'error-placeholder',
  'method' => 'append',
  'effect' => 'fade',
),
'#prefix' => '<td>',
'#title' => t('Click this button to add a standard volume price'),
);

My debugger basically showed the following data:

$info['entity keys']['bundle'] = "type"
$entity_type = "node"

$entity stdClass        
add string  "Add"   
add_row string  "Add"   
price   string  "123"   
till-amount string  "123"

I checked my database and couldn't find any nodes without type so that shouldn't cause any problems.

I suppose I have to define the bundle in my code somewhere but I'm not that famillair with bundles yet.

The field is added to the node edit page of a product created by the ubercart module using hook_form_FORM_ID_alter() -> hook_form_product_node_form_alter().

Does anyone have a clue as to what I should do to define the bundle?

Or in OOP terms, how can I make my field a class member of the ubercart product bundle (which is an extended class of the entity type base class)?

  • That error isn't being caused by that single form element though, is it? If you comment just that code out does the error disappear? – Clive Mar 17 '14 at 11:52
  • I think you're right about that. However this button is basically my ajax form submission button. If I were to comment it out I couldn't really test it. :/ I do know it happens either during or after form validation. Also, I've seen quite some people having trouble with this same error. And the most common answer is to disable the module with the culprit... I'm creating that module so that's not really gonne work :D – SimbaClaws Mar 17 '14 at 11:59
  • 1
    Also, as you can see the $entity stdClass has no bundle. I think that's how the problem is caused but I don't quite know how to add it the "drupal way". I don't like hacking core. – SimbaClaws Mar 17 '14 at 12:07
  • When I comment out #limit_validation_errors the error message dissapeared. Although, I do need validation so I will have to find another solution. The error appears after both price and till-amount passed their validation function. – SimbaClaws Mar 17 '14 at 12:39
  • Ubercart should be using entities properly (entities being unique, having a bundle, etc.). You should be able to find an example entity already built and use the devel module to find that entities' bundle. You may have to set it manually in your code. – nielsonm Jul 1 '14 at 19:10
1

Please check Examples, specifically entity_example module to check how to define the bundle.

So for Drupal 7 it goes like:

/**
 * Implements hook_entity_info().
 *
 * This is the fundamental description of the entity.
 *
 * It provides a single entity with a single bundle and without revision
 * support.
 */
function entity_example_entity_info() {
  $info['entity_example_basic'] = array(
    // A human readable label to identify our entity.
    'label' => t('Example Basic Entity'),

    // The controller for our Entity, extending the Drupal core controller.
    'controller class' => 'EntityExampleBasicController',

    // The table for this entity defined in hook_schema()
    'base table' => 'entity_example_basic',

    // Returns the uri elements of an entity.
    'uri callback' => 'entity_example_basic_uri',

    // IF fieldable == FALSE, we can't attach fields.
    'fieldable' => TRUE,

    // entity_keys tells the controller what database fields are used for key
    // functions. It is not required if we don't have bundles or revisions.
    // Here we do not support a revision, so that entity key is omitted.
    'entity keys' => array(
      // The 'id' (basic_id here) is the unique id.
      'id' => 'basic_id' ,
      // Bundle will be determined by the 'bundle_type' field.
      'bundle' => 'bundle_type',
    ),
    'bundle keys' => array(
      'bundle' => 'bundle_type',
    ),

    // FALSE disables caching. Caching functionality is handled by Drupal core.
    'static cache' => TRUE,

    // Bundles are alternative groups of fields or configuration
    // associated with a base entity type.
    'bundles' => array(
      'first_example_bundle' => array(
        'label' => 'First example bundle',
        // 'admin' key is used by the Field UI to provide field and
        // display UI pages.
        'admin' => array(
          'path' => 'admin/structure/entity_example_basic/manage',
          'access arguments' => array('administer entity_example_basic entities'),
        ),
      ),
    ),
    // View modes allow entities to be displayed differently based on context.
    // As a demonstration we'll support "Tweaky", but we could have and support
    // multiple display modes.
    'view modes' => array(
      'tweaky' => array(
        'label' => t('Tweaky'),
        'custom settings' => FALSE,
      ),
    ),
  );

  return $info;
}

Or for simpler example, entity.api.php from Entity module which goes like:

function entity_crud_hook_entity_info() {
  $return = array(
    'entity_test' => array(
      'label' => t('Test Entity'),
      'entity class' => 'Entity',
      'controller class' => 'EntityAPIController',
      'base table' => 'entity_test',
      'module' => 'entity_test',
      'fieldable' => TRUE,
      'entity keys' => array(
        'id' => 'pid',
        'name' => 'name',
        'bundle' => 'type',
      ),
      'bundles' => array(),
    ),
  );
  foreach (entity_test_get_types() as $name => $info) {
    $return['entity_test']['bundles'][$name] = array(
      'label' => $info['label'],
    );
  }
  return $return;
}

The error EntityMalformedException which you're having it's saying that your bundle property is malformed on save, so Drupal core can't identify what type (bundle) is that.

Troubleshooting:

  1. Check what's the value of bundle in entity keys section of array defined in entity information array via:

    drush eval 'print_r(entity_get_info("entity_type"));'
    
  2. If it's type, then that means your entity which you're trying to save, it's missing type attribute.

The common mistake is usually to load the entity via entity_load() and trying to re-save it, but remember that return value is an array of entity objects indexed by their ids.

So the simple test to verify if your entity re-saving works correctly, it would be:

drush eval '$entity = entity_load("entity_type", array(1)); entity_get_controller("entity_type")->save(reset($entity))'

where entity_type is your entity_type and 1 is your entity id.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.