Problem/Motivation

Drupal provides no way to model hierarchical bundle relationships, making it tedious and error prone to build many content types with significant field reuse, and making it difficult to reuse code on the business and display layers. In practice, content is often related in the way classes are related in object-oriented programming. Consider the following (contrived and over-simplified) example of a sports website with pages for teams and players.

There is a category of content types for players with similarities and differences: they both need identical name and photo fields, they both need a team reference field but each should be configured differently (e.g., a football player should only be able to reference a football team), and each needs something the other doesn't (a sport-specific statistic). Given Drupal's current content modeling tools, this would require two player content types and two team content types with ad hoc field reuse, separate templates for all of them, and no intrinsic knowledge of the fact that any of these things are variants of others.

Proposed resolution

  1. Add the concept of bundle inheritance with the ability to add default fields and settings on a parent whose children can override their settings and add other fields to them as well as have their own form display and display configurations.
  2. Add the concept of an "abstract" bundle (or an interface or a generic or what-have-you) that never has entity instances (e.g., Sports player in the example above).
  3. Add support Views filters and entity references field constraints (among other things) (e.g., such that you could filter a View to anything that "is a" Sports player and get back both Baseball players and Football players--and Soccer players would come back to, if they were added to the hierarchy later, without having to modify the View).
  4. Add the ability to determine in code an entity's place in the hierarchy (e.g., being able to ask whether a Baseball player entity "is a" Sports player).
  5. Add hooks and template suggestions that allow for code reuse at the new semantic level.

Remaining tasks

TBD

User interface changes

TBD

API changes

TBD

Data model changes

TBD

CommentFileSizeAuthor
#95 100925-class-diagram.png21 KBTravisCarden
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

catch’s picture

Title: provide the ability to derive from / extend content-types » Content-type inheritance /cloning
Project: Content Construction Kit (CCK) » Drupal core
Version: 6.x-1.x-dev » 7.x-dev
Component: content.module » node system

Moving to core.

yojoe’s picture

I badly need something like this, too.

So we're talking about
1. Generalization: A content-type can inherit fields from it's parent(s).
2. Abstraction: An abstract content-type can be designed with CCK, but no nodes of this content type can be created.
3. Overloading / Hiding of fileds inherited from parent content-types.
4. Association: This is somewhat possible with CCK's node-reference fields now. But the thing I am missing is, that you can't join different content-types using the views module on the node reference field.

So in the end, drupal should be a data server, where you first can design your application using UML, next setup the data model using CCK, so you automatically get the add/edit forms to fill your data model, and last but not least you can use the views module to create any "virtual" content type you want.

Wernight’s picture

Couldn't agree more, this is a must-have that should be explained in the current documentation. What I mean is that if it's not currently possible (as I know no way) it should state so and give as much workarounds as possible, like:
1. including other's module file and calling functions manually
2. making some kind of overload generator that would do (1) automatically
3. using the 'hook_form_alter' or some other combination of hooks

colan’s picture

It looks like someone started working on a contributed module for this. I suggested, however, that it may be better to do this as a patch to core and/or CCK.

kvantomme’s picture

contrib for D6 - core for D7, no problem there.

I've been thinking about how we can get the Biblio module to move away from custom node types towards CCK nodes in stead. Inheritance would make that possible.

mitchell’s picture

I reference this issue here: #72509: Expose a "Save content type" action.

donquixote’s picture

Flexifield allows to share some field definitions among different node types.

limex67’s picture

Desperately needed.
IMHO #2 would be best approach.

catch’s picture

Version: 7.x-dev » 8.x-dev

Not going to happen in Drupal 7.

Anonymous’s picture

There is a related module proposal on gdo, but I don't know if any work has come from it.

Content Subtypes module proposal

groovehunter’s picture

subscribing

AdrianB’s picture

Subscribing.

mandclu’s picture

Subscribe, and a +1 for good measure

jelo’s picture

Subscribing

srobert72’s picture

Any chance to find it in Drupal 6.x ?
Which contribute module could be best to offer this feature ?

Shadlington’s picture

Subscribing. This is something I really need.

scott859’s picture

subscribing

Jarada’s picture

Hi guys, just a note for anyone visiting this thread that Content Type cloning is available using the import/export tabs available on the Content Types page. Instructions for that can be found here: http://scratchpads.eu/how-do-i-exportimport-or-clone-content-type

mandclu’s picture

Is it possible that functionality comes from CTools? I don't see those tabs on my Content Types page.

colan’s picture

Title: Content-type inheritance /cloning » Content-type inheritance

Let's keep this discussion geared towards inheritance. Cloning doesn't account for the inheritance-style relationships. For example, if you clone a content type (as is now possible), adding or removing a field in a parent won't get propogated to its child. I believe that this is the type of behaviour we're most interested in.

@surge_martin: You need to have the Content Copy module enabled. It's one of the CCK submodules.

frob’s picture

This would be awesome. If content types behaved like classes with inheritance, polymorphism, and and interfaces.

Interfaces would be awesome from a development standpoint.

John Pitcairn’s picture

Subscribe. Anything in this direction would be immensely useful. What I'm wrestling with is a multisite install that should share content types, but need to be able to both update those content types globally (less work) and override them on a site-by-site basis (more flexibility).

Anonymous’s picture

I think you should be able to do that by having your content type in a feature, http://drupal.org/features

colan’s picture

Title: Content-type inheritance » Entity inheritance (for content types and anything else that's fieldable)

As this is going to be post-D7, it would make more sense to talk about subclassing entities (anything fieldable) rather than content types.

We could probably get by with adding a column somewhere for each entity, a pointer to a parent. Each class/entity would thus inherit all fields that any ancestors have. This would be a good place to start.

@linclark: I don't think Features provides inheritance. AFAIK, it provides a means by which to move content & configuation around. Please correct me if I'm wrong.

zilverdistel’s picture

subscribing

frob’s picture

@johnpitcairn & @colan,
Features could work by creating generic content types in the feature and enabling it and overriding as needed on each site of the multi-site. Alternatively you could export the content types to each of the sites. If its just one or two sites then exporting the content types would be easier, if its more like ten sites then features would be a better approach. IMHO. But this is way off topic.

Shadlington’s picture

@frob: That isn't inheritance, its just copying the content types.

John Pitcairn’s picture

@frob: inheritance means that if the content type you are inheriting from changes, then all content types inheriting from that will also pick up those changes, without any additional effort required.

frob’s picture

@johnpitcairn, I know what inheritance is. I was just trying to help you solve your issue with the tools that are available now since this is more of a Drupal 8 feature than Drupal 6/7.

rgs’s picture

Very helpful. Thank you.

mstrelan’s picture

subscribe

thsutton’s picture

Inheritance with polymorphism would be a fantastic addition to Drupal and the move to entities in D7 makes it even more attractive. I'm not sure how the entity system interacts with the database layer, but it might be nice (but not worth the refactoring it would probably require) if entities making use of inheritance could make use of database-level support (in PostgreSQL, for example) where possible.

Also, shouldn't this issue now be about the field system component rather than the node system?

colan’s picture

Component: node system » field system

Yup!

mandclu’s picture

My impression was that the original issue was about content type inheritance. As such, it strikes me as being larger in scope than just the field system. In fact, I'd suggest it would be more accurately described as a requested expansion of the content module, but I don't see that as a component option.

yched’s picture

Component: field system » base system

This is indeed not for the 'field system'. We probably lack an 'entity system' component.
For now, those issues are placed under 'base system'.

colan’s picture

From what I can tell so far, we would need the Entity API module to get this done. It's not in core; at least not yet.

mandclu’s picture

Does the Entity API module provide inheritance? It isn't clear to me from looking at the project page that it does.

colan’s picture

Oh sorry, it doesn't provide inheritance, but it does provide a way for us to add properties to entities. We could use it to add a "parent" property. IMHO, this would be a great place to start. I really wish I had time to work on this right now. :)

robcarr’s picture

OO didn't seem to feature in Dries' recent DrupalCon keynote. Content type inheritance would be a fantastic timesaver, and really simplify the structure of a lot of sites. Makes it all the more logical as all content inherits the property of 'node.'
Even if we could only implement pseudo-inheritance (with, for example, a fixed depth limit) that would be great.
But where to start...

GiorgosK’s picture

here is an experimental module that has been out for some time
might be worth taking a look
http://drupal.org/project/inherit

frob’s picture

That project seems to offer a lot of what I would like for this. But I would really like an easier way to code cck fields from scratch much like the form api.

We don't have to go head-first into full OO.

I would like it if we could create a content type definition and then extend that definition. We could even extend this further with abstract content types that are never meant for anything except other to be a foundation for other content types, the 'node' content type would be the first of these.

zilverdistel’s picture

In my opinion, now with Drupal 7, nodes are not the atoms of the system anymore. I would suggest to build further on the concepts of entities and bundles (for entity-type node, bundles are node-types). Bundle inheritance ...

John Pitcairn’s picture

#43: That's fine from a developer's point of view, as long as admins will still see simple inheritable content types. They're not really going to care so much about the details of the underlying architecture. This should "just work" for them (ie a single dropdown to choose the parent type), without exposing confusing "entity" or "bundle" implementation details at the UI.

Shadlington’s picture

It does matter from the users point of view... It means that its not just content types that would be inheritable, but anything fieldable - any entity.
Which would be a big win.

But the title of this issue has been Entity inheritance since #24 so I think everyone is on the same page anyway.

joachim’s picture

Very interesting.

Has anyone considered starting this as a contrib project for D7? That would be a good way to explore ideas.

I considered something like this would be needed for a Drupal-based CRM and it was written up as part of the architecture spec after the BoF at Copenhagen (see various posts at http://groups.drupal.org/crm-api).

The idea we sketched out for D7 was a hierarchy of templates, which then create the content types much like Features does. This sidesteps the need for OO-based content types.

Shadlington’s picture

The templates idea sounds good.
Could it be possible to, when adding a field to a template, also add the field to all content types that had been created from the template?
That'd solve one of the big use cases: making it easy to maintain a large number of quite-similar content types.
I'd certainly be happy with it in place of actual inheritance if this were the case.

joachim’s picture

> Could it be possible to, when adding a field to a template, also add the field to all content types that had been created from the template?

No reason why not -- Features adds fields to content types when you update the code for a feature from a staging site to production :)

If anyone wants to start a sandbox for this, please post the link! :D

zilverdistel’s picture

As a site admin, pushing the button "Create new content type". I'd like to see not only an input field for the name of the new content type, but also a dropdown (or something similar) to select the kind of entity relation (extends to begin with) and next to that another dropdown which enables me to select another content type (on which the relationship depends).

After submitting, all settings (at least all fields) from the content type should be present in the new content type. I should be unable to alter these fields (or maybe we can have some 'override' mechanism similar to views displays).

This is purely from a ui perspective and only for the node/content types pair (but should be the same mechanism for other entity/bundles pairs like term/vocabulary, ...). Just trying to think like a developer, which I am ;-)

Is this do-able with the templates concept described by Joachim?

claning’s picture

I get a "file not found" error from this link: http://scratchpads.eu/how-do-i-exportimport-or-clone-content-type

Adding a hyphen doesn't seem to help either: http://scratchpads.eu/how-do-i-export-import-or-clone-content-type

jspotswood’s picture

subscribing

kirkilj’s picture

subscribe

inversed’s picture

subscribe

waynedpj’s picture

subscribe

catch’s picture

Title: Entity inheritance (for content types and anything else that's fieldable) » Bundle inheritance
Component: base system » entity system
Dave Reid’s picture

Subscribing.

gunith’s picture

Subscribing

svax’s picture

Subscribing.

lemark’s picture

Subscribing.

AdrianB’s picture

lemark: You don't need to do that any more, just use the "Follow"-button.

lemark’s picture

lemark’s picture

Alpha release published: http://drupal.org/project/bundle_inherit
You are welcome to participate in providing feedback and creating future requests.

desiman’s picture

Subscribing

fago’s picture

Wouldn't it be sometimes more useful to have mixins instead of inheritance?

E.g. do a mixin for certain functionality like a node being an issue. Then, manage your fields for the mixin. Next, you could attach any number of mixins to a node on bundle basis, or even per-instance.

I think that "mixin" approach would match well to Drupal's modular approach, as any module could expose mixins that are attached to an entity once the module is active for a certain instance.

Update: Then, we could even go further and expose entity hooks based upon mixins to facilitate the creation of entity-generic features.

sun’s picture

Issue tags: +Entity system, +Bundle system
Alan D.’s picture

Love the "hierarchy of templates" idea - aka implementing a base form of object composition bypassing the nasty side-effects of true inheritance. This general idea doesn't even need to be implemented in OO and actually fits better with the general structure of Drupal imho. What are effectively existing object composition patterns in D7: Products, Webforms

As any OO designer will say; use inhertance when one class has an "is a" relationship with another, and composition when one class has a "has a" relationship with another. For those that are unfamiliar with object composition, Google will direct you to a million articles on the subject: https://www.google.com/search?q=object+composition+inheritance

For the site we are currently working on, there are about 30 content types;

  • 27 share the same base 6 fields that defines a simple page (body, featured image, images, ...)
  • 4 event based types, each with a vastly different field array. But all 4 share the same base 10 or so fields
  • 22 have resources [web links and document attachments]
  • ...

Simply by defining 3 type templates and applying these would account for nearly 85% or more of all fields used on the site. Excited by the potential of this (even if it ends up as a tightly couple inheritance model.)

dreftymac’s picture

Nice idea

thoughtcat’s picture

I Googled for "clone content type" and ended up here via three or four issues closed as duplicates. This discussion is difficult to follow but in comment 20 (which may have applied to D6) it is stated "if you clone a content type (as is now possible)..." I can't see how to do that in either D7 or D6, so is this possible or not in Drupal 7 currently, and if not, is it on the cards for a future D7 release?

Mark_L6n’s picture

Content Type Inheritance for D8 would be great!!! My 2 cents: it doesn't need to be a perfect-in-theory OO inheritance. It just needs to be something like a Theme/ sub-theme, and simply modify/add what you need that is new in the sub-theme, and inherit everything else. (This keeps things simple and consistent for developers--Themes and Content Types are 'inherited' in the same way. And hopefully easier for core developers to implement.)

In the meantime, for a situation like #66, the module Field collection looks useful. (Although I haven't personally used it.)

donquixote’s picture

If you think of views inheritance, and the interface to configure the views settings:
Every content type setting would now have an additional state "inherit". We only need to decide at which level / how fine-grained this would be.

It could be more difficult than we think.
Esp. if two settings depend on each other, and we want one to be "inherit" and the other "overridden".

Timon Davis’s picture

following

frob’s picture

Version: 8.x-dev » 9.x-dev

So, if this is still going to happen it looks like it should be moved to D9.

dreftymac’s picture

Issue summary: View changes

aka "composite node" or "composite entity" ... some people are doing this already with entity_reference https://www.drupal.org/node/1434238 ;; https://www.drupal.org/node/1434238#comment-6048174

catch’s picture

Project: Drupal core » Drupal core ideas
Version: 9.x-dev »
Component: entity system » Idea

This has both UX and framework implications, so moving it to ideas queue.

jibran’s picture

yoroy’s picture

Issue summary: View changes
Status: Active » Needs work

First stab at reworking the issue summary to use the idea template. These only need short answers but could be more specific around the problem this solves.

For a success metric, would this maybe reduce the average number of needed content types on a site?

mstrelan’s picture

It wouldn't reduce content types, it would reduce time to build content types, and maintenance of types. If there are "virtual" types it would actually increase the number of types.

It's probably more for site builders, than it is for developers.

yoroy’s picture

Issue summary: View changes

Thanks! Feel free to add this information to the issue summary itself :)

I'm not clear yet on what the actual hierarchy idea is though. Similar to all those OOP "mammal" tutorials where you can derive a dog and a cat from the same "master" content type?

mstrelan’s picture

It's been six years since I was interested in this and I haven't been following. Yeah it's like the mammal example. I think at the time I was working on museum websites and was wanting a base "artefact" type with common fields, and then specific subtypes that would provide additional fields.

amateescu’s picture

The issue linked by @jibran in #75 is essentially what this proposal was all about. We even have a module in D7 for it: https://www.drupal.org/project/entity_bundle_plugin

jibran’s picture

Title: Bundle inheritance » Allow entity bundles to be defined as plugins
Issue tags: +Plugin system

I think in core media module could really benefit from this. Right now, we create media bundles and the assign it the media plugin. This would automatically create the media bundles from media plugins.

joachim’s picture

> Bundle inheritance » Allow entity bundles to be defined as plugins

Hasn't this title change completely changed what this issue is about?

(And isn't there already an issue for bundles getting their behaviour from plugins?)

amateescu’s picture

Title: Allow entity bundles to be defined as plugins » Allow entity bundles to be defined as classed objects

This title should be better :)

joachim’s picture

Still changes it -- it's gone from an abstract idea about bundle inheritance to an implementation detail.

> Allow you to extend existing types by adding, overloading, hiding fields. Also, it would be nice to have virtual content types, which can only be extended, not instantiated.

Also, I don't see how having bundle classes will cover all the above in the summary.

amateescu’s picture

Title: Allow entity bundles to be defined as classed objects » Bundle inheritance

Ok then.

frob’s picture

Issue summary: View changes

Oh good, that is the change that I was going to make. It is important to this issue that to not get bogged down in implementation. I expect there will be many issues necessary to make this change. I think the IS and title now fully explain the idea, though clarification might be needed for users that don't understand OOP speak. Maybe add some examples and use-cases. I made a couple changes that would make this useful to devs as-well-as site builders.

yoroy’s picture

For the "what is the problem" answer I added the bit that was already there in the original report. To me it does not yet clearly explain the problem/opportunity. A description that does not rely on OOP speak and an example or two would definitely help.

schifazl’s picture

Let me give you an example from a web application that I've built.
I'm working on an electronic school register. One of the things that I have to track are student's absences. We have four types of absences (here I've slightly simplified them, some fields are hidden/calculated and not related to the inheritance problem), each with some fields (in bold the common ones):

  • Absence
    This one is a "normal" absence. A student is absent one (or more) school hours.
    1. Academic year
    2. Term
    3. Date
    4. Student
    5. School hours
    6. Justified (yes/no)
    7. Comment
  • Early exit/Late access
    Used when a student has to leave school before the end of the school day (e.g. he must go to a medical examination) or if he comes later to school (the two content types have the same fields, but the logic is different). BTW yes, here I could have created one single content type and add two radiobuttons to choose for the Early exit or the Late access, but I've preferred to keep them separated.
    1. Academic year
    2. Term
    3. Date
    4. Student
    5. Exit/Arrival time
    6. Justified (yes/no)
    7. Comment
  • Lateness
    Different than the Late access content type, here we only look how many minutes a student is late for a single lecture. It's treated differently than the Late access from the administrative point of view
    1. Academic year
    2. Term
    3. Date
    4. Student
    5. School hour
    6. Minutes (how many minutes the student was late during the specified school hour)
    7. Justified (yes/no)
    8. Comment

When designing this, I had to create four full content types, and add all these fields (and more) to them, but six fields are common for everyone.

How inheritance could help my work? By creating an AbstractAbsence class with the six common fields I could shorten my work, avoid redundance (if I have to add a common field I would have to add it four times. And what if I forget to add it to a content type? Or if I forget to add a content type check in my logic? Things go south...), group common logic, have cleaner code.

Another example which doesn't need abstract content types/classes: normal Lectures (a teacher teaches an argument to his students) and "Remedial lectures" (some students might need additional explanations, so they ask for an extra lecture). The two content types have 14 common fields, but the Remedial lecture has an additional field: an Entity reference to the students which are present. By not having the possibility to just inherit the fields and logic from the Lecture entity type, I had to add all the 14 fields to the Remedial lecture and then the extra one. Yes, it was an implementation nightmare, as forgetting one field out of 14 was quite easy.

I hope that my examples are conveying the idea!

colan’s picture

I'm wondering if we could use #267855: Provide an entity hierarchy API for this.

frob’s picture

@colan: #267855: Provide an entity hierarchy API That issue is more about the structure of the site or the sitemap/menu/routing system. This is more of a hierarchy of fields/functionality.

colan’s picture

Status: Needs work » Needs review

@frob: The idea is to build an API that can be used by all entities. If bundles are technically entities, then we should be able to use the API to keep track of the hierarchy here. So for example, if Animals is a parent bundle, and Cats is to inherit from it, then we can use the API to specify that the parent of Cats is Animals. Because that relationship exists through the API, we'd know that Cats also inherits the same fields as Animals.

What I'm not sure about it how bundles were implemented in D8. Are they actually entities themselves? I somehow doubt it, but if it's not too much work to make it so, and there's a hierarchy API for entities, it might make it easier to implement this. Yes, I know that's a lot of ifs. :)

The issue description looks good to me so changing status.

colan’s picture

Status: Needs review » Needs work

Let's add something like #88 there as well so we have a concrete example.

webchick’s picture

Sounds like this idea is very popular! :)

Sounds like we need someone to finish up the issue summary with the details in #88, and then a round of review/RTBC on then idea. This would then escalate to the product managers to sign-off, and next step would be getting an implementation plan together.

John Pitcairn’s picture

For the example in #88 I'd be inclined to do it via composition/reference rather than inheritance, using paragraphs module to add the sets of non-shared fields on the fly.

We've been taking this approach to keep the number of "page" content types down to one or two for a site, and it works pretty well.

TravisCarden’s picture

Title: Bundle inheritance » Add "OO" bundle inheritance features
Issue summary: View changes
FileSize
21 KB

I've taken a stab at updating the issue summary.

TravisCarden’s picture

Status: Needs work » Needs review

Mmm. Since it's an "idea", maybe I should mark it "Needs review".

TravisCarden’s picture

Issue summary: View changes
colan’s picture

Nice! I'm still wondering if it makes sense for this to be dependent on #267855: Provide an entity hierarchy API.

sebkamil’s picture

In regards to #94, I've been using Paragraphs extensively for this and it works pretty well. There are a couple issues though.

To account for subtypes that don't have any fields (i.e. no Paragraph), to the best of my knowledge, I need to keep a taxonomy (or something) field on the base type to distinguish which subtype an instance represents.

Also, since Paragraphs are a separate entity, more technical implementations (e.g. deriving fields in custom code) are inherently more complex than having one entity (e.g. one node).

effulgentsia’s picture

I like the idea presented in this issue's summary. One thing that I think would be useful to add to the summary is a comparison of how the proposed resolution is either similar or different than what is provided by the contrib Entity API module via #2817751: Create an API for bundle plugins.

For example, I think a main difference is that this issue proposes the ability to define the abstract bundles (e.g., Sports Player) and add fields (e.g., Name) to them via the UI, just as is done for "regular" bundles today. Whereas I think #2817751: Create an API for bundle plugins requires the field definitions of the abstract (plugin-class-defined) bundles to be added via code. That's a big difference since it's the difference of whether the intended audience of the feature is a site builder or a developer.

I don't know if other parts of the proposed resolution are already handled by #2817751: Create an API for bundle plugins or not.

That's not to say that we should start focusing on the implementation of this issue yet, since it's still in the Idea component. But I think in terms of fleshing out the idea, it would help to reference what, if any, existing contrib solutions solve some of the desired capabilities being proposed here, and what is being proposed here that has no existing contrib solution?

frob’s picture

This isn't an inheritance implementation, as in, this doesn't allow for a parent->child relationship of entities or bundles. However, the Field Tools module is a contrib module which comes to mind functionality about this functionality.

Field Tools provides a UI for copying field settings and display settings from one bundle to another.

The Field Group module also allows the copying of field group structures from one bundle/display to another. Which is also similar in functionality.

None of these enforce changes from the originally copied bundle onto the destination bundle. But both of these modules are used heavily by the Site Builders I work with (not that this is an endorsement of field_group/field_tools UX).

AaronMcHale’s picture

tim.plunkett’s picture

That issue landed, is there more to be done here or can this be closed?

AaronMcHale’s picture

That issue landed, is there more to be done here or can this be closed?

This issue is still valid, for example #2570593: Allow entities to be subclassed using "bundle classes" does not provide a way for bundle classes to declare their own set of fields, that still has to be done on the primary entity class (or in the UI, or equivalent).