7

I've been trying to figure out this problem of allowing the user to dynamically create project request forms (add his own fields including drop downs, multiselects, etc...). The user needs a way to create multiple project request types (bundles, perhaps?), for different business units. I figured the entity / bundle relationship would be perfect for this. So here is my idea:

Use the Schema API to define my base table "project". Use the Entity API hook_entity_info() to tell Drupal about my new entity, pointing it to the "project" table. Now in this hook I can define bundles - which is great. But I need for the user to be able to create a bundle. Where is the entity_create_bundle($entity_type, $bundle) call?

Example:

Entity TYPE: Project (with common fields defined in DB, and it is fieldable)

Bundle: IT Project, HR Project - which share the common fields from Project

A project_type table will store additional grouping I need (project requests for business units).

Now I've been reading Drupal 7 Module Development which has been great, and in chapter 6 they define an entity "artwork" that has a couple of bundles, "sculpture" and "painting". The way they describe the steps, is as if they are building an admin interface to create additional artwork types, but this is not true (from what I can tell). After finishing the chapter, I can only create entities of type "painting" or "sculpture".

How can I allow users to create bundles of the "project" entity type?

Am I missing something or is the functionality not there [yet]?

  • Have you looked into webform module? Im not comfortable with the idea of entity (bundle) creation... but if you are sure about this one, have a look into drupal.org/project/entityform ! – jumper Feb 24 '12 at 2:05
  • At first I thought this had nothing to do with what I wanted, but they have essentially done what I need. In the code, it looks like they use hook_entity_info_alter() to modify the "entityform_type's". When is hook_entity_info_alter() called exactly? Only once upon installation, or whenever? – Jack Feb 24 '12 at 2:27
  • 1
    I did not mean that this module is going to do exactly what I need, but they create the same types of tables I do (entityform and entityform_type), to allow additional "bundles" or types to be created. I'm just wondering how hook_entity_info_alter() is called. – Jack Feb 24 '12 at 2:35
  • hook_entity_info() and it's alter will be called on cache clear. So if you do add an alter in a module, all you need to do for it to take effect is clear the cache. – Letharion Feb 24 '12 at 11:30
14

Examining the default Node bundles

The Node module does not create the "Article" and "Basic page" Bundles itself. After some digging I found the definitions for these bundles in the standard install profile's install file.

/profiles/standard/standard.install

  // Insert default pre-defined node types into the database. For a complete
  // list of available node type attributes, refer to the node type API
  // documentation at: http://api.drupal.org/api/HEAD/function/hook_node_info.
  $types = array(
    array(
      'type' => 'page',
      'name' => st('Basic page'),
      'base' => 'node_content',
      'description' => st("Use <em>basic pages</em> for your static content, such as an 'About us' page."),
      'custom' => 1,
      'modified' => 1,
      'locked' => 0,
    ),
    array(
      'type' => 'article',
      'name' => st('Article'),
      'base' => 'node_content',
      'description' => st('Use <em>articles</em> for time-sensitive content like news, press releases or blog posts.'),
      'custom' => 1,
      'modified' => 1,
      'locked' => 0,
    ),
  );

  foreach ($types as $type) {
    $type = node_type_set_defaults($type);
    node_type_save($type);
    node_add_body_field($type);
  }

  // clear the site cache

A few notes about this code

  1. It doesn't use Entity API
  2. st() function should only be used during a Drupal installation process
  3. Node contains a lot of non Field API fields that it handles in node_type_save
  4. Node calls field_attach_create_bundle to tell Field modules about the new bundle

Creating a bundle with the Entity API

I'm not sure how you've defined your entities, but if you've used Entity API then your bundle-creation code might look something like this:

$bundle = new stdClass();
$bundle->type = 'project_hr';
$bundle->label = t('HR Project');
$bundle->is_new = true;
$bundle->description = t("A super cool project");

$controller = new ProjectTypeController('project_type'); //assuming you defined this extension of EntityAPIController
$controller->save($bundle);

A note about Entities

  • An entity type is an abstract base class
  • A bundle is an extended entity type class
  • A field is a class member, property, variable or field instance
  • An entity is an object or instance of a base or extended class

More about entities

  • Heh - thanks for this ... it's been almost a year now since my Computer Science Capstone class which is when I needed this - BUT I ended up doing something similar to your solution :). – Jack Jan 29 '13 at 3:53
  • 4
    Ya i know i'm lurkin' on an old question, but I found it asking Google the same one myself. I answered it more for my own benefit (and other like-minded Googlers) than yours :) – tmsimont Jan 29 '13 at 16:25
3

I spent quite a while trying to figure this out. I am working on a project based on Model module (https://drupal.org/project/model). In my install script I wanted to create bundles. The code sample for the Entity API example in the "Examining the default Node bundles" answer is close but not quite right (well it wasn't for me).

The following snippet should work:

$bundles = field_info_bundles('project_type');

if (empty($bundles['project_hr'])) {
    $controller = new ProjectTypeController('project_type'); //assuming you defined this extension of EntityAPIController

    $params = array();
    $params['type'] = 'project_hr';
    $params['label'] = t('HR Project');
    $params['is_new'] = TRUE;
    $params['description'] = t('A super cool project.');

    $bundle = $controller->create($params);
    $controller->save($bundle);
}

The field_info_bundles checks to see if the bundle exists (so you don't try and create it twice). This gets info for the bundles created for the project_type entity.

If the bundle does not exist then you can then go ahead and create the bundle.

First up, you create a controller, then you create a parameters array with the options for the bundle that you want to create. You then use the controller to create a bundle object (this creates a PHP object with all the "standard" entity fields and methods, and then adds your parameters to the object. Then you use the controller to save the bundle. This last part persists the bundle in the database.

I hope this helps.

2

I'm trying to do something like that, and it looks like the Node module contains already the code, as when you create a new type of content, it creates a new bundle for the node entity, and adds the "body" field to it by default (using the field API). All these operations and forms (table of bundles, CRUD of bundles and etc) is made by hand.

Thanks to the Drupal developers, you can copy the code contained in the Node module.

I think later I can publish my work as drupal module for visual creation of entities and it's hierarchy of bundles.

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.