Skip to content
intermediate Phase 36 · Service Contracts

Data Interfaces

Get/set methods, immutable vs mutable interfaces, extension attributes, and data interface patterns.

45m
0 problems
Topic Progress 0%

Data Interface Patterns

Data interfaces follow specific patterns for consistency.

Standard data interface:

<?php
namespace Vendor\Module\Api\Data;

interface EntityInterface
{
    // Constants for field names
    const ID = 'id';
    const NAME = 'name';
    const STATUS = 'status';
    const CREATED_AT = 'created_at';
    
    // ID getter (always nullable)
    public function getId(): ?int;
    
    // String getters/setters
    public function getName(): string;
    public function setName(string $name): self;
    
    // Integer getters/setters
    public function getStatus(): int;
    public function setStatus(int $status): self;
    
    // Date getters/setters
    public function getCreatedAt(): ?string;
    public function setCreatedAt(string $createdAt): self;
}

Field type mapping:

PHP type → Interface return type
string → string
int → int
float → float
bool → bool
null → ?type
array → array
DateTime → ?string (ISO 8601)

Method naming:

Field: name → getName() / setName()
Field: is_active → getIsActive() / setIsActive()
Field: sku → getSku() / setSku()

Mutable vs Immutable Interfaces

Mutable interfaces allow modification; immutable interfaces return new instances.

Mutable interface (standard in Magento):

interface PostInterface
{
    public function getTitle(): string;
    public function setTitle(string $title): self;
}

// Usage: modifies same object
$post->setTitle('New Title'); // Returns same $post
$post->setTitle('Another Title'); // Same object modified

Immutable pattern:

interface ImmutablePostInterface
{
    public function getTitle(): string;
    // No setter - create new instance instead
}

// Usage: create new instance
$newPost = $post->withTitle('New Title'); // Returns new object

Magento convention:

  • Most data interfaces are mutable
  • Return self for fluent chaining
  • Setters modify and return same object

Why mutable is preferred:

// Fluent chaining with mutable interface
$post->setTitle('Title')
    ->setContent('Content')
    ->setStatus(1);

// Object is modified in place
// Single instance, less memory

Extension Attributes

Extension attributes add custom data without changing core interfaces.

Extension interface:

<?php
namespace Vendor\Module\Api\Data;

interface PostExtensionAttributesInterface
{
    // Custom string attribute
    public function getAuthorName(): ?string;
    public function setAuthorName(string $authorName): self;
    
    // Custom array attribute
    public function getTags(): ?array;
    public function setTags(array $tags): self;
    
    // Custom object attribute
    public function getCategory(): ?\Vendor\Module\Api\Data\CategoryInterface;
    public function setCategory(
        \Vendor\Module\Api\Data\CategoryInterface $category
    ): self;
}

Implementing extension attributes:

<?php
namespace Vendor\Module\Model\Data;

class PostExtensionAttributes implements \Vendor\Module\Api\Data\PostExtensionAttributesInterface
{
    private ?string $authorName = null;
    private ?array $tags = null;
    private ?\Vendor\Module\Api\Data\CategoryInterface $category = null;
    
    public function getAuthorName(): ?string
    {
        return $this->authorName;
    }
    
    public function setAuthorName(string $authorName): self
    {
        $this->authorName = $authorName;
        return $this;
    }
    
    public function getTags(): ?array
    {
        return $this->tags;
    }
    
    public function setTags(array $tags): self
    {
        $this->tags = $tags;
        return $this;
    }
}

Populating extension attributes:

// In repository get() method
public function get($id): PostInterface
{
    $post = $this->loadPost($id);
    
    $ext = $post->getExtensionAttributes() ?? $this->extFactory->create();
    
    // Populate from related data
    $author = $this->authorRepo->get($post->getAuthorId());
    $ext->setAuthorName($author->getName());
    
    $post->setExtensionAttributes($ext);
    return $post;
}

Data Interface Conventions

Magento conventions for data interface design.

1. Constant naming:

interface PostInterface
{
    const ID = 'id';           // snake_case
    const TITLE = 'title';     // Matches DB column
    const IS_ACTIVE = 'is_active';
    const CREATED_AT = 'created_at';
}

2. Method signatures:

interface PostInterface
{
    // ID is always nullable
    public function getId(): ?int;
    
    // Required fields return non-nullable
    public function getTitle(): string;
    
    // Optional fields return nullable
    public function getUrlKey(): ?string;
    
    // Setters return self
    public function setTitle(string $title): self;
    
    // Boolean fields use is_ prefix
    public function getIsActive(): bool;
    public function setIsActive(bool $isActive): self;
}

3. Field types:

Entity ID → ?int (nullable)
String → string
Integer → int
Float → float
Boolean → bool
Date → ?string (ISO 8601)
Array → array
Object → ?InterfaceName

4. Documentation:

/**
 * Post data interface
 *
 * @api
 * @since 1.0.0
 */
interface PostInterface
{
    /**
     * Get post title
     *
     * @return string
     */
    public function getTitle(): string;
    
    /**
     * Set post title
     *
     * @param string $title
     * @return self
     */
    public function setTitle(string $title): self;
}

Quiz

1. What should getId() return in a data interface?

Question 1 options

2. What should setters return in Magento data interfaces?

Question 2 options

3. How are extension attributes different from regular attributes?

Question 3 options

4. What naming convention is used for boolean getters?

Question 4 options

Flashcards

Question

What should getId() return?

Answer

?int (nullable, new entities may not have ID)

Question

What do setters return?

Answer

self (for fluent chaining)

Question

How are extension attributes implemented?

Answer

Separate PostExtensionAttributesInterface

Question

What is the boolean getter convention?

Answer

getIsActive() for is_active field

Question

Where are field name constants defined?

Answer

In the data interface itself (const TITLE = 'title')

Revision Notes

Key Takeaways

  • 1. Data interfaces define get/set methods for entity data
  • 2. getId() returns ?int; setters return self for chaining
  • 3. Extension attributes use separate interfaces
  • 4. Constants define field names matching database columns
  • 5. Boolean fields use is_ prefix in getter names
  • 6. @api annotation marks stable interface

Interview Tips

  • Explain the difference between mutable and immutable interfaces
  • Describe how extension attributes work
  • Know Magento naming conventions for interfaces
  • Discuss why getId() is nullable

Cheat Sheet

Data Interfaces Cheat Sheet

Pattern:

interface EntityInterface
{
    const FIELD = 'field_name';
    
    public function getId(): ?int;
    public function getField(): string;
    public function setField(string $field): self;
}

Rules:

  • getId(): ?int (nullable)
  • Setters return self
  • Constants for field names
  • Boolean: getIsActive()
  • @api annotation

Extension attributes:

  • Separate interface
  • PostExtensionAttributesInterface
  • Populate in repository get()