# Configurar el católogo en Drupal Commerce: Fields, Taxonomies, Media y Product Attributes

 Enviado por [danieluxury](/es/user/1 "Ver perfil del usuario.") el Vie, 25 Sep 2026 - 12:28

En el artículo anterior creamos la estructura básica de nuestra tienda:

```plaintext
Home Shop
   │
   ├── Used Product
   │      └── Used Variation
   │
   ├── Imported Product
   │      └── Imported Variation
   │
   └── Cake
          └── Cake Variation
```

Ahora debemos convertir estas estructuras vacías en modelos de producto realmente útiles.

Para ello utilizaremos cuatro herramientas fundamentales de Drupal:

- Fields
- Taxonomy
- Media
- Commerce Product Attributes

El objetivo de este artículo no es simplemente añadir campos.

Queremos aprender a decidir **qué tipo de estructura corresponde a cada dato**.

---

## 1. El problema que queremos resolver

Nuestra tienda familiar necesita representar productos muy diferentes.

Por ejemplo:

```plaintext
USED PRODUCT

Canon Camera usada

Category:
Photography

Condition:
Good

Visible defects:
Small scratches

Images:
3 photos

Price:
250 USD
```

También:

```plaintext
IMPORTED PRODUCT

USB-C Hub

Brand:
Baseus

Category:
Electronics

Country of origin:
China

Price:
35 USD
```

Y:

```plaintext
CAKE

Chocolate Cake

Ingredients:
Chocolate, flour, eggs...

Allergens:
Eggs, milk, gluten

Sizes:
Small
Medium
Large
```

Aunque toda esta información describe productos, no toda debería representarse mediante el mismo mecanismo.

---

## 2. Nuestra matriz de decisión

Antes de crear un field podemos utilizar esta guía:

```plaintext
¿Es simplemente un dato?
        ↓
Field

¿Es un concepto reutilizable
que clasifica productos?
        ↓
Taxonomy

¿Es un recurso multimedia
que puede reutilizarse?
        ↓
Media

¿Es una opción que selecciona
el comprador para determinar
qué Variation compra?
        ↓
Product Attribute
```

Esta matriz será nuestra referencia durante toda la configuración.

---

## 3. Fields

Un Field almacena información estructurada dentro de una entidad.

Por ejemplo:

```plaintext
Visible defects

Purchase year

Country of origin

Ingredients

Allergen information
```

Drupal permite añadir fields prácticamente a cualquier entidad fieldable.

En Commerce podemos añadirlos, entre otras, a:

```plaintext
Product

Product Variation

Order

Order Item

Product Attribute Value
```

Por eso la pregunta no es solamente:

> ¿Qué field necesito?

Sino también:

> ¿En qué entidad debe vivir?

---

## 4. Taxonomy

Taxonomy sirve para representar conceptos reutilizables y administrables.

Por ejemplo:

```plaintext
Product Category

├── Electronics
├── Photography
├── Furniture
├── Books
├── Food
└── Cakes
```

Un mismo término puede utilizarse en muchos productos.

Además podremos posteriormente:

- Filtrar por categoría
- Crear páginas de categoría
- Construir navegación
- Usar Facets
- Añadir metadata al término

Esto es muy diferente de guardar simplemente:

```plaintext
Category = "Photography"
```

en un text field.

---

## 5. Media

Drupal dispone de entidades Media para gestionar recursos reutilizables como imágenes, documentos, vídeos y otros archivos.

Para nuestro catálogo utilizaremos Media para las imágenes.

Conceptualmente:

```plaintext
Product
   │
   └── Images
          ↓
        Media
          ↓
        Image
```

Esto ofrece ventajas frente a un simple Image field cuando queremos reutilizar recursos, añadir metadata o aprovechar Media Library. Drupal Core permite que los Media Types tengan sus propios fields y que un media reference field referencie uno o varios tipos de Media.

---

## 6. Product Attributes

Los Product Attributes tienen una responsabilidad mucho más específica.

Representan características utilizadas para diferenciar Product Variations.

Por ejemplo:

```plaintext
Cake Size

├── Small
├── Medium
└── Large
```

El comprador selecciona:

```plaintext
Size:
Medium
```

y Commerce determina:

```plaintext
Product Variation

Chocolate Cake - Medium

SKU:
CAKE-CHO-M

Price:
25 USD
```

Este es el motivo por el que Size será un Commerce Product Attribute y no una Taxonomy.

---

## 7. Crear Product Category

Empezaremos con nuestras taxonomías.

Vamos a:

```plaintext
Structure
→ Taxonomy
→ Add vocabulary
```

Creamos:

```plaintext
Name:
Product Category

Machine name:
product_category
```

Después añadimos algunos términos:

```plaintext
Electronics

Photography

Furniture

Books

Food

Cakes
```

---

## 8. Podemos utilizar jerarquía

A medida que el catálogo crezca podemos evolucionar hacia:

```plaintext
Product Category

Electronics
├── Computers
├── Phones
├── Accessories
└── Photography

Home
├── Furniture
└── Kitchen

Food
└── Cakes
```

No necesitamos construir una taxonomía enorme desde el primer día.

Podemos empezar con los términos realmente necesarios.

---

## 9. Product Category será compartida

No crearemos:

```plaintext
Used Product Category

Imported Product Category

Cake Category
```

si todos pertenecen al mismo sistema de clasificación.

Utilizaremos:

```plaintext
Product Category
```

como vocabulario compartido.

Por ejemplo:

```plaintext
Canon Camera usada
→ Photography

USB-C Hub
→ Electronics

Chocolate Cake
→ Cakes
```

---

## 10. Crear Product Condition

Los productos usados necesitan representar su estado.

Creamos:

```plaintext
Vocabulary:
Product Condition

Machine name:
product_condition
```

Valores iniciales:

```plaintext
Like New

Very Good

Good

Fair

For Parts
```

Esto nos dará una lista consistente y reutilizable.

---

## 11. ¿Por qué Condition es Taxonomy?

Podríamos haber utilizado un List field.

Por ejemplo:

```plaintext
Condition

like_new | Like New
very_good | Very Good
good | Good
fair | Fair
```

También sería una solución válida.

Para nuestro ejercicio utilizaremos Taxonomy porque queremos practicar:

- Reutilización
- Filtrado
- Administración de términos
- Posible metadata futura

Esta decisión no significa que Taxonomy sea siempre superior a un List field.

La elección depende de cuánto comportamiento necesitemos alrededor del concepto.

---

## 12. Crear Product Origin

También crearemos:

```plaintext
Vocabulary:
Product Origin

Machine name:
product_origin
```

Con:

```plaintext
Used

Imported

Local Production
```

Esto nos permitirá clasificar:

```plaintext
Canon Camera
→ Used

USB-C Hub
→ Imported

Chocolate Cake
→ Local Production
```

---

## 13. Product Origin nos ayudará a revisar nuestra arquitectura

Recordemos que actualmente tenemos:

```plaintext
Used Product

Imported Product
```

como Product Types separados.

Pero ahora también tenemos:

```plaintext
Product Origin
```

Esto plantea una pregunta interesante:

> ¿Estamos duplicando una distinción que podría resolverse solamente mediante Taxonomy?

Aún no responderemos definitivamente.

Queremos observar primero qué fields necesita cada Product Type.

Si terminan teniendo prácticamente la misma estructura, podríamos simplificarlos posteriormente.

---

## 14. Añadir Category a Used Product

Vamos a:

```plaintext
Commerce
→ Configuration
→ Products
→ Product types
→ Used Product
→ Manage fields
```

Añadimos un field:

```plaintext
Label:
Category

Machine name:
field_category

Field type:
Entity reference

Reference type:
Taxonomy term

Vocabulary:
Product Category
```

Normalmente permitiremos un término principal inicialmente.

Más adelante podemos decidir si un producto puede pertenecer a múltiples categorías.

---

## 15. Reutilizar field storage cuando tenga sentido

Queremos que Imported Product y Cake utilicen también Product Category.

Drupal permite reutilizar un field existente cuando:

- El tipo de field es compatible
- La semántica es realmente la misma

Conceptualmente queremos:

```plaintext
field_category

Used Product
Imported Product
Cake
```

en lugar de crear:

```plaintext
field_used_category

field_imported_category

field_cake_category
```

sin ninguna necesidad.

---

## 16. Añadir Condition a Used Product

Ahora añadimos:

```plaintext
Label:
Condition

Machine name:
field_condition

Type:
Taxonomy term reference

Vocabulary:
Product Condition
```

Este field será obligatorio para los productos usados.

Por ejemplo:

```plaintext
Canon Camera usada

Condition:
Good
```

---

## 17. Añadir Product Origin

Podemos añadir también:

```plaintext
Origin

→ Product Origin taxonomy
```

Sin embargo aquí debemos pensar antes de configurar.

Para un Product Type llamado:

```plaintext
Used Product
```

el valor siempre será:

```plaintext
Used
```

Entonces almacenar:

```plaintext
Origin = Used
```

en cada producto puede ser redundante.

Por ahora no añadiremos Origin a Used Product.

El Product Type ya expresa esa distinción.

---

## 18. Esta decisión nos enseña algo importante

No debemos crear un field simplemente porque tenemos un vocabulario disponible.

Preguntamos:

> ¿Este dato aporta información que no conocemos ya por la estructura?

Si:

```plaintext
Product Type = Used Product
```

entonces:

```plaintext
Origin = Used
```

puede ser duplicación.

Esto refuerza la necesidad de revisar más adelante si realmente queremos Product Types separados por origen.

---

## 19. Añadir Visible Defects

Para Used Product necesitamos información específica del artículo.

Añadimos:

```plaintext
Label:
Visible Defects

Machine name:
field_visible_defects

Field type:
Text (long)
```

Por ejemplo:

```plaintext
Small scratches on the body.
Lens cap has minor wear.
```

Este dato no necesita Taxonomy.

Cada producto puede tener una descripción diferente.

---

## 20. Añadir Purchase Year

Podemos querer registrar aproximadamente cuándo se adquirió originalmente.

Podríamos crear:

```plaintext
Label:
Purchase Year

Machine name:
field_purchase_year
```

Para una implementación sencilla podemos utilizar un Integer field.

Ejemplo:

```plaintext
2021
```

No necesitamos una Taxonomy:

```plaintext
2020
2021
2022
2023
...
```

porque estamos almacenando un valor, no un concepto reutilizable.

---

## 21. Imágenes del producto

Ahora necesitamos fotografías.

Podríamos utilizar directamente un Image field.

Pero para nuestra tienda utilizaremos Media.

Queremos:

```plaintext
Product

Images
   ↓
Media references
```

Esto nos permitirá utilizar Media Library y reutilizar imágenes si alguna vez lo necesitamos.

---

## 22. Revisar el Media Type Image

Una instalación Drupal normalmente dispone de un Media Type:

```plaintext
Image
```

Podemos revisarlo en:

```plaintext
Structure
→ Media types
→ Image
```

Conceptualmente contiene:

```plaintext
Media
   │
   ├── Name
   ├── Image file
   └── Metadata
```

Drupal Core permite añadir además fields personalizados a Media Types.

---

## 23. Añadir Images a Used Product

En Manage fields añadimos:

```plaintext
Label:
Images

Machine name:
field_images

Field type:
Media reference

Allowed media type:
Image

Cardinality:
Unlimited
```

Queremos poder tener:

```plaintext
Canon Camera usada

Images

├── front
├── back
├── side
└── defect detail
```

---

## 24. Configurar Media Library

En:

```plaintext
Manage form display
```

podemos seleccionar el widget:

```plaintext
Media Library
```

Esto proporciona una mejor experiencia editorial:

```plaintext
Add media
   ↓
Select existing image
or
Upload new image
```

En lugar de tratar cada archivo como un simple upload aislado.

---

## 25. Añadir Images a otros Product Types

Queremos reutilizar el mismo concepto:

```plaintext
field_images
```

en:

```plaintext
Used Product

Imported Product

Cake
```

Todos representan:

> Imágenes generales del producto.

Por tanto tiene sentido compartir la misma estructura.

---

## 26. Modelo actual de Used Product

Hasta ahora tenemos:

```plaintext
USED PRODUCT

Product

├── Title
├── Description
├── Category
├── Condition
├── Images
├── Visible Defects
└── Purchase Year

Variation

├── SKU
└── Price
```

Este modelo ya nos permite crear un artículo usado bastante completo.

---

## 27. Configurar Imported Product

Ahora vamos a:

```plaintext
Imported Product
→ Manage fields
```

Reutilizamos:

```plaintext
Category

Images
```

Y añadiremos algunos fields específicos.

---

## 28. Brand

Un producto importado puede tener:

```plaintext
Brand:
Baseus
```

Podríamos utilizar:

```plaintext
Text field
```

pero si queremos construir un catálogo serio probablemente Brand es un concepto reutilizable.

Por ejemplo:

```plaintext
Brand

├── Anker
├── Baseus
├── Xiaomi
├── Ugreen
└── Generic
```

Por tanto crearemos una nueva Taxonomy.

---

## 29. Crear Product Brand

Creamos:

```plaintext
Vocabulary:
Product Brand

Machine name:
product_brand
```

Y algunos términos:

```plaintext
Anker

Baseus

Xiaomi

Ugreen

Generic
```

Después añadimos a Imported Product:

```plaintext
Brand

→ Taxonomy term reference
→ Product Brand
```

---

## 30. Brand como Taxonomy nos permitirá evolucionar

Más adelante podemos añadir fields al término Brand.

Por ejemplo:

```plaintext
Brand

Baseus

├── Logo
├── Website
├── Description
└── Country
```

Entonces una página de marca podría mostrar:

```plaintext
Baseus

Logo

Description

Products from this brand
```

Este es un buen ejemplo de cuándo Taxonomy aporta más valor que un simple text field.

---

## 31. Country of Origin

Queremos almacenar:

```plaintext
Country of Origin:
China
```

Aquí tenemos varias opciones.

Podríamos usar:

- Text
- List
- Country field
- Taxonomy

Para un país, deberíamos preferir un tipo de dato estructurado antes que texto libre cuando esté disponible.

No queremos terminar con:

```plaintext
China

PR China

People's Republic of China

CN
```

representando el mismo país.

---

## 32. Supplier

Podríamos querer registrar quién nos suministra el producto.

Por ejemplo:

```plaintext
Supplier:
Example Imports Inc.
```

Sin embargo, Supplier es información administrativa interna.

No necesariamente queremos mostrarla públicamente.

Podemos crear:

```plaintext
field_supplier
```

más adelante cuando tengamos claro si será:

- Texto
- Taxonomy
- Custom Entity
- Referencia a otro sistema

Por ahora no la añadiremos.

No modelaremos datos sin necesidad concreta.

---

## 33. Modelo actual de Imported Product

```plaintext
IMPORTED PRODUCT

Product

├── Title
├── Description
├── Category
├── Brand
├── Images
└── Country of Origin

Variation

├── SKU
└── Price
```

Más adelante Variation puede incorporar:

```plaintext
Stock

Weight

Dimensions

Attributes
```

cuando estudiemos Inventory y Shipping.

---

## 34. Configurar Cake

Ahora llegamos al Product Type más interesante.

Queremos:

```plaintext
Chocolate Cake

Description

Images

Ingredients

Allergens

Variations:

Small
Medium
Large
```

Empezaremos con los fields del Product.

---

## 35. Category

Reutilizamos:

```plaintext
field_category
```

y seleccionaremos:

```plaintext
Cakes
```

Esto permitirá integrar Cakes dentro del catálogo general.

---

## 36. Images

Reutilizamos:

```plaintext
field_images
```

con Media Library.

Por ejemplo:

```plaintext
Chocolate Cake

Images:

├── whole cake
├── slice
└── decoration detail
```

---

## 37. Ingredients

Para nuestro ejemplo inicial crearemos:

```plaintext
Label:
Ingredients

Machine name:
field_ingredients

Type:
Text (long)
```

Por ejemplo:

```plaintext
Flour, cocoa, eggs, sugar,
butter and chocolate.
```

Más adelante podríamos descubrir que necesitamos estructurar los ingredientes de una forma mucho más avanzada.

Pero todavía no existe ese requisito.

---

## 38. Allergens

Podríamos escribir:

```plaintext
Contains eggs, milk and gluten.
```

como texto.

Pero Allergens tienen potencial de ser conceptos reutilizables y filtrables.

Por ejemplo:

```plaintext
Allergens

├── Gluten
├── Milk
├── Eggs
├── Nuts
├── Peanuts
└── Soy
```

Esto sugiere utilizar Taxonomy.

---

## 39. Crear Allergen

Creamos:

```plaintext
Vocabulary:
Allergen

Machine name:
allergen
```

Valores iniciales:

```plaintext
Gluten

Milk

Eggs

Nuts

Peanuts

Soy
```

Después añadimos al Cake:

```plaintext
Allergens

→ Taxonomy reference
→ Multiple values
```

Por ejemplo:

```plaintext
Chocolate Cake

Allergens:

Gluten
Milk
Eggs
```

---

## 40. Ingredients y Allergens muestran dos modelos diferentes

Tenemos:

```plaintext
Ingredients
        ↓
Text

Allergens
        ↓
Taxonomy
```

¿Por qué?

Porque en nuestra implementación:

```plaintext
Ingredients
= descripción específica

Allergens
= conjunto controlado
  de conceptos reutilizables
```

Si en el futuro necesitamos gestionar nutrición, recetas o inventario de ingredientes, probablemente deberíamos revisar este modelo.

---

## 41. Ahora necesitamos Cake Size

El tamaño no es solamente información descriptiva.

El comprador debe seleccionar:

```plaintext
Small

Medium

Large
```

y cada opción puede tener:

```plaintext
Different SKU

Different Price

Possibly different weight
```

Por tanto Cake Size es un Product Attribute.

---

## 42. Crear Product Attribute

Vamos a:

```plaintext
Commerce
→ Product attributes
```

o directamente:

```plaintext
/admin/commerce/product-attributes
```

Seleccionamos:

```plaintext
Add product attribute
```

y creamos:

```plaintext
Label:
Cake Size

Machine name:
cake_size
```

Drupal Commerce permite definir Product Attributes libremente según las opciones reales de nuestros productos.

---

## 43. Attribute Element Type

El Product Attribute define también cómo pueden presentarse inicialmente sus valores al comprador.

Podemos encontrar opciones como:

```plaintext
Select list

Radio buttons

Rendered attribute
```

Para Cake Size podemos comenzar con:

```plaintext
Radio buttons
```

porque tenemos solamente tres opciones fáciles de entender.

Conceptualmente:

```plaintext
Size

( ) Small

( ) Medium

( ) Large
```

---

## 44. Crear Attribute Values

Dentro de Cake Size añadimos:

```plaintext
Small

Medium

Large
```

Y definimos su orden:

```plaintext
Small
  ↓
Medium
  ↓
Large
```

Los Product Attribute Values son entidades de contenido asociadas al Product Attribute correspondiente.

---

## 45. Product Attribute y Taxonomy se parecen estructuralmente

Existe una similitud interesante:

```plaintext
Taxonomy

Vocabulary
   ↓
Terms
```

y:

```plaintext
Commerce Attribute

Product Attribute
   ↓
Attribute Values
```

Por ejemplo:

```plaintext
Vocabulary:
Product Condition

Terms:
Good
Fair
...
```

frente a:

```plaintext
Product Attribute:
Cake Size

Values:
Small
Medium
Large
```

Pero sus responsabilidades son diferentes.

---

## 46. Taxonomy frente a Product Attribute

Podemos compararlos:

```plaintext
PRODUCT CONDITION

Used for:
Classification

Customer chooses variation?
No

Changes SKU?
No

Changes price?
No

        ↓

Taxonomy
```

Mientras:

```plaintext
CAKE SIZE

Used for:
Purchasable choice

Customer chooses variation?
Yes

Changes SKU?
Yes

Changes price?
Yes

        ↓

Product Attribute
```

Esta es una de las distinciones más importantes del modelado de Commerce.

---

## 47. Añadir Cake Size a Cake Variation

Crear el Attribute no es suficiente.

Debemos decir qué Variation Type lo utiliza.

Vamos a:

```plaintext
Commerce
→ Configuration
→ Products
→ Product variation types
→ Cake Variation
→ Edit
```

En la sección de Attributes deberíamos encontrar:

```plaintext
Cake Size
```

Lo activamos.

La documentación oficial describe precisamente este proceso: al seleccionar un Attribute en el Variation Type, Commerce crea los entity reference fields necesarios para relacionar Variations con Attribute Values.

---

## 48. Qué acaba de ocurrir

Antes teníamos:

```plaintext
CAKE VARIATION

SKU

Title

Price
```

Después de activar Cake Size tenemos:

```plaintext
CAKE VARIATION

SKU

Title

Price

Cake Size
```

Conceptualmente Commerce ha creado una relación:

```plaintext
Product Variation
      │
      └── Cake Size
              ↓
      Attribute Value
```

---

## 49. El field del Attribute vive en Variation

Esto es importante.

No estamos añadiendo:

```plaintext
Cake Size
```

al Product.

Lo añadimos a:

```plaintext
Cake Variation
```

porque:

```plaintext
Chocolate Cake
        ↓
Product

Chocolate Cake - Small
        ↓
Variation
```

Size describe qué unidad comprable estamos seleccionando.

---

## 50. El Attribute será obligatorio por defecto

Normalmente, cuando añadimos un Product Attribute a un Variation Type, el field generado será obligatorio.

Esto tiene sentido:

```plaintext
Cake Variation

Size:
?
```

no sería una Variation completamente definida en nuestro modelo.

Queremos:

```plaintext
Small

Medium

Large
```

Commerce permite convertir un Attribute en opcional modificando posteriormente los settings del field si el negocio lo necesita.

---

## 51. Añadir campos a Attribute Values

Una característica especialmente poderosa es que los Attribute Values también son fieldable entities.

Por ejemplo, podríamos enriquecer Cake Size.

```plaintext
Small

Approximate servings:
6

Medium

Approximate servings:
10

Large

Approximate servings:
16
```

Podríamos añadir un field:

```plaintext
Approximate Servings
```

al Attribute Value.

Drupal Commerce permite añadir fields a los valores del Attribute como a otras entidades fieldable.

---

## 52. ¿Deberíamos hacerlo?

Debemos preguntarnos primero:

> ¿Las porciones dependen solamente del tamaño?

Si:

```plaintext
Small
always approximately 6 portions

Medium
always approximately 10

Large
always approximately 16
```

entonces el Attribute Value puede ser un buen lugar.

Pero si depende también del tipo de pastel:

```plaintext
Chocolate Cake Medium
10 portions

Tall Wedding Cake Medium
20 portions
```

entonces no pertenece al Attribute Value global.

Puede pertenecer a la Variation.

---

## 53. Esta decisión muestra la importancia del alcance del dato

Podemos utilizar la pregunta:

> ¿En qué nivel sigue siendo este dato verdadero?

Por ejemplo:

```plaintext
Size name:
Medium

True globally
        ↓
Attribute Value

Price:
25 USD

Only true for a specific cake variation
        ↓
Variation
```

Esta forma de pensar evita duplicación y errores.

---

## 54. Nuestro Cake ahora tiene esta arquitectura

```plaintext
CAKE PRODUCT

├── Title
├── Description
├── Category
├── Images
├── Ingredients
└── Allergens

CAKE VARIATION

├── SKU
├── Price
└── Cake Size
       │
       ├── Small
       ├── Medium
       └── Large
```

Ahora ya tenemos todo lo necesario para crear:

```plaintext
Chocolate Cake

├── Small
│   SKU: CAKE-CHO-S
│   Price: 15 USD
│
├── Medium
│   SKU: CAKE-CHO-M
│   Price: 25 USD
│
└── Large
    SKU: CAKE-CHO-L
    Price: 40 USD
```

---

## 55. ¿Y el sabor?

Recordemos que decidimos:

```plaintext
Chocolate Cake

Vanilla Cake

Carrot Cake
```

serán Products diferentes.

Por tanto no creamos:

```plaintext
Flavor Attribute
```

todavía.

Nuestro modelo será:

```plaintext
Chocolate Cake
├── Small
├── Medium
└── Large

Vanilla Cake
├── Small
├── Medium
└── Large
```

Esto permite que cada receta tenga:

- Descripción propia
- Imágenes propias
- Ingredientes propios
- Alérgenos propios

---

## 56. ¿Cuándo cambiaríamos a Flavor Attribute?

Podría tener sentido si el negocio evoluciona hacia:

```plaintext
Product:
Birthday Cake

Attributes:

Flavor
├── Chocolate
├── Vanilla
└── Strawberry

Size
├── Small
├── Medium
└── Large
```

Y si todas esas combinaciones representan Variations del mismo producto conceptual.

La arquitectura debe seguir al negocio.

---

## 57. ¿Y la decoración personalizada?

Supongamos que el cliente puede escribir:

```plaintext
"Feliz cumpleaños María"
```

en el pastel.

No debemos crear un Attribute:

```plaintext
Decoration Text
```

porque no conocemos los posibles valores previamente.

Tampoco queremos generar Variations infinitas.

Ese dato pertenece a la compra concreta.

```plaintext
Order Item

Custom Cake Message:
"Feliz cumpleaños María"
```

Lo implementaremos más adelante mediante un Order Item field y el Add to Cart form.

---

## 58. Attribute Values deben ser conocidos previamente

Los Product Attributes funcionan especialmente bien cuando tenemos un conjunto conocido de opciones.

Por ejemplo:

```plaintext
Size

Small
Medium
Large
```

O:

```plaintext
Color

Black
White
Blue
```

La documentación de Commerce distingue este patrón de los productos configurables donde el comprador introduce datos únicos durante la compra.

---

## 59. Configurar Form Displays

Después de añadir nuestros fields debemos revisar:

```plaintext
Manage form display
```

para cada Product Type.

Queremos que el formulario administrativo tenga un orden lógico.

Por ejemplo:

```plaintext
USED PRODUCT

Title

Description

Images

Category

Condition

Purchase Year

Visible Defects

Variation Information
```

La interfaz administrativa forma parte de la calidad de nuestra arquitectura.

---

## 60. Form Display para Imported Product

Podríamos ordenar:

```plaintext
Title

Description

Images

Category

Brand

Country of Origin

Variation Information
```

Esto permite que el editor complete la información siguiendo una secuencia natural.

---

## 61. Form Display para Cake

Podemos utilizar:

```plaintext
Title

Description

Images

Category

Ingredients

Allergens

Variations
```

Las Variations pueden administrarse separadamente porque Cake permite múltiples Variations.

---

## 62. Configurar Manage Display

También debemos revisar:

```plaintext
Manage display
```

Por ejemplo, en Used Product podríamos mostrar:

```plaintext
Title

Images

Price

Condition

Description

Visible Defects
```

y ocultar información puramente administrativa.

Recordemos que Product y Variation pueden renderizarse conjuntamente mediante Variation field injection cuando está habilitada.

---

## 63. No todo field administrativo debe mostrarse

Por ejemplo:

```plaintext
Purchase Year
```

podría ser información interna.

O quizás queramos mostrarla.

Lo importante es separar:

```plaintext
Data exists
        ↓
Field

Data is visible
        ↓
Display configuration
```

No necesitamos eliminar el field simplemente porque no queramos mostrarlo públicamente.

---

## 64. Crear campos reutilizables conscientemente

Nuestra arquitectura comienza a tener fields compartidos:

```plaintext
field_category

Used Product
Imported Product
Cake

field_images

Used Product
Imported Product
Cake
```

y fields específicos:

```plaintext
field_condition
→ Used Product

field_visible_defects
→ Used Product

field_brand
→ Imported Product

field_ingredients
→ Cake

field_allergens
→ Cake
```

Esto es una estructura mucho más limpia que crear fields duplicados para cada bundle.

---

## 65. Field Storage frente a Field Instance

Drupal separa conceptualmente:

```plaintext
Field Storage
        ↓
qué tipo de dato existe

Field Configuration
        ↓
cómo se utiliza en este bundle
```

Por eso un mismo field storage puede utilizarse en diferentes Product Types cuando su semántica es compatible.

Al exportar configuración veremos esta diferencia reflejada en YAML.

---

## 66. Exportar configuración

Una vez terminada esta etapa:

```plaintext
drush cex -y
```

Después:

```plaintext
git status
```

y:

```plaintext
git diff --stat
```

Ahora deberíamos observar muchos más cambios que en el artículo anterior.

---

## 67. Configuración de Taxonomy

Podemos encontrar archivos relacionados con:

```plaintext
taxonomy.vocabulary.product_category.yml

taxonomy.vocabulary.product_condition.yml

taxonomy.vocabulary.product_brand.yml

taxonomy.vocabulary.allergen.yml
```

Los términos concretos normalmente son contenido y no deben confundirse con la definición del Vocabulary.

De nuevo:

```plaintext
Vocabulary
= configuration

Terms
= content
```

---

## 68. Configuración de Fields

También veremos archivos como:

```plaintext
field.storage.commerce_product.field_category.yml

field.field.commerce_product.used_product.field_category.yml
```

Conceptualmente:

```plaintext
field.storage
        ↓
define el storage

field.field
        ↓
conecta el field
a un bundle concreto
```

Los nombres exactos dependerán de los machine names elegidos.

---

## 69. Configuración de Media References

Para Images veremos configuración relacionada con:

```plaintext
field.storage.commerce_product.field_images.yml
```

y las instancias correspondientes en nuestros Product Types.

También aparecerán cambios en:

```plaintext
core.entity_form_display

core.entity_view_display
```

si configuramos widgets y formatters.

---

## 70. Configuración del Product Attribute

Después de crear:

```plaintext
Cake Size
```

deberíamos encontrar configuración de Commerce relacionada con el Product Attribute.

También veremos el field que Commerce crea para:

```plaintext
Cake Variation
        ↓
Cake Size
```

El machine name seguirá normalmente el patrón:

```plaintext
attribute_cake_size
```

porque los Attributes se implementan mediante entity reference fields sobre Product Variations.

---

## 71. Los Attribute Values no son configuración

Existe una distinción interesante.

El Product Attribute:

```plaintext
Cake Size
```

es configuración.

Pero sus valores:

```plaintext
Small

Medium

Large
```

son entidades de contenido.

La documentación oficial describe Product Attribute como configuration entity y Product Attribute Value como content entity.

Esto es importante para deployment.

---

## 72. Una consecuencia práctica

Podemos exportar:

```plaintext
Cake Size
        ↓
Config
```

pero no debemos asumir que:

```plaintext
Small

Medium

Large
```

aparecerán automáticamente como configuration YAML.

En un proyecto real debemos decidir cómo desplegaremos datos iniciales necesarios para el funcionamiento del sitio.

Podemos utilizar mecanismos como:

- Default content
- Migrations
- Update hooks
- Custom deployment logic

dependiendo del proyecto.

---

## 73. Esto también aplica a Taxonomy Terms

Exportamos:

```plaintext
Product Condition vocabulary
```

pero términos como:

```plaintext
Good

Fair

Like New
```

son contenido.

Si estos valores son obligatorios para que la aplicación funcione, debemos incluirlos en nuestra estrategia de instalación o deployment.

---

## 74. Este detalle es importante para proyectos reproducibles

Queremos poder instalar nuestro proyecto desde cero mediante algo similar a:

```plaintext
composer install

drush site:install

drush cim

...
```

Pero si la configuración espera:

```plaintext
Cake Size
        ↓
Small / Medium / Large
```

y esos valores no existen, nuestra instalación estará estructuralmente correcta pero funcionalmente incompleta.

Por tanto debemos distinguir:

```plaintext
Configuration dependencies

vs

Required initial content
```

---

## 75. Modelo completo después de este artículo

```plaintext
HOME SHOP
   │
   ├── USED PRODUCT
   │      │
   │      ├── Category → Taxonomy
   │      ├── Condition → Taxonomy
   │      ├── Images → Media
   │      ├── Purchase Year → Field
   │      ├── Visible Defects → Field
   │      │
   │      └── USED VARIATION
   │             ├── SKU
   │             └── Price
   │
   ├── IMPORTED PRODUCT
   │      │
   │      ├── Category → Taxonomy
   │      ├── Brand → Taxonomy
   │      ├── Images → Media
   │      ├── Country of Origin → Field
   │      │
   │      └── IMPORTED VARIATION
   │             ├── SKU
   │             └── Price
   │
   └── CAKE
          │
          ├── Category → Taxonomy
          ├── Images → Media
          ├── Ingredients → Field
          ├── Allergens → Taxonomy
          │
          └── CAKE VARIATION
                 │
                 ├── SKU
                 ├── Price
                 │
                 └── Cake Size
                        │
                        ├── Small
                        ├── Medium
                        └── Large
```

---

## 76. Nuestra matriz final

Podemos clasificar cada decisión tomada:

```plaintext
Product Category
→ Taxonomy

Product Condition
→ Taxonomy

Brand
→ Taxonomy

Allergen
→ Taxonomy

Images
→ Media

Visible Defects
→ Text Field

Purchase Year
→ Integer Field

Country of Origin
→ Structured Field

Ingredients
→ Text Field

Cake Size
→ Commerce Product Attribute
```

Cada herramienta tiene una responsabilidad distinta.

---

## 77. Regla para Taxonomy

```plaintext
¿Es un concepto reutilizable
para clasificar entidades?

        ↓

Taxonomy
```

Ejemplos:

```plaintext
Category

Brand

Condition

Allergen
```

---

## 78. Regla para Field

```plaintext
¿Es simplemente información
estructurada de una entidad?

        ↓

Field
```

Ejemplos:

```plaintext
Purchase Year

Visible Defects

Ingredients
```

---

## 79. Regla para Media

```plaintext
¿Es un recurso multimedia
que queremos administrar
como entidad reutilizable?

        ↓

Media
```

Ejemplo:

```plaintext
Product Images
```

---

## 80. Regla para Product Attribute

```plaintext
¿El comprador selecciona
esta propiedad para determinar
qué Variation está comprando?

        ↓

Product Attribute
```

Ejemplo:

```plaintext
Cake Size
```

La documentación oficial propone una regla muy similar: cuando una característica está asociada a una combinación específica de SKU/precio y debe aparecer como opción para seleccionar una Variation, encaja naturalmente como Product Attribute.

---

## 81. Checklist de esta etapa

### Taxonomies

- Product Category
- Product Condition
- Product Brand
- Allergen

### Used Product

- Category
- Condition
- Images
- Visible Defects
- Purchase Year

### Imported Product

- Category
- Brand
- Images
- Country of Origin

### Cake

- Category
- Images
- Ingredients
- Allergens

### Product Attributes

- Cake Size
- Small
- Medium
- Large

### Variation Types

- Cake Size añadido a Cake Variation

### Display

- Form displays revisados
- View displays revisados
- Media Library configurada para Images

### Configuration

- Config export ejecutado
- Field storage revisado
- Field instances revisadas
- Attribute configuration revisada

---

## 82. Lo que todavía no hemos hecho

Aunque nuestro modelo ya tiene mucha estructura, todavía no hemos creado productos reales.

Tampoco hemos configurado:

```plaintext
Inventory

Shipping weight

Dimensions

Stock

Checkout

Payment

Shipping

Taxes

Promotions
```

Seguiremos añadiendo cada concepto cuando tengamos una necesidad concreta.

---

## Conclusión

En este artículo hemos convertido nuestros Product Types iniciales en un catálogo estructurado utilizando las herramientas apropiadas de Drupal.

La lección más importante no es cómo añadir un field.

Es aprender a escoger la estructura correcta.

```plaintext
Field
= dato de una entidad

Taxonomy
= clasificación reutilizable

Media
= recurso multimedia reutilizable

Product Attribute
= opción que determina
  una Product Variation
```

También hemos visto una distinción fundamental para proyectos Drupal reproducibles:

```plaintext
Vocabulary
= Configuration

Taxonomy Term
= Content

Product Attribute
= Configuration

Product Attribute Value
= Content
```

Por tanto, un proyecto profesional no debe pensar solamente en:

```plaintext
drush cex
```

sino también en cómo proporcionar el contenido inicial imprescindible para que la configuración funcione.

En el siguiente artículo utilizaremos finalmente esta arquitectura para **crear nuestros primeros productos reales**.

Crearemos paso a paso:

```plaintext
Canon Camera usada
        ↓
Single Variation
        ↓
250 USD

USB-C Hub importado
        ↓
Single Variation
        ↓
35 USD

Chocolate Cake
        ↓
Multiple Variations
        ↓
Small / Medium / Large
```

Además estudiaremos cómo Commerce genera las Variations, cómo se utilizan SKU y Price, cómo funciona el selector de Attributes y qué ocurre internamente cuando visualizamos un Product.

##  Course navigation: Drupal Commerce

Chapter 11 of 11

- [ ← Anterior Crear una tienda Drupal Commerce desde cero: instalación y configuración inicial ](/es/crear-una-tienda-drupal-commerce-desde-cero-instalacion-y-configuracion-inicial)

 [↑ Course index](/es/node/43)