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?
2. What should setters return in Magento data interfaces?
3. How are extension attributes different from regular attributes?
4. What naming convention is used for boolean getters?
Flashcards
Question
What should getId() return?
Click to reveal answer
Answer
?int (nullable, new entities may not have ID)
Question
What do setters return?
Click to reveal answer
Answer
self (for fluent chaining)
Question
How are extension attributes implemented?
Click to reveal answer
Answer
Separate PostExtensionAttributesInterface
Question
What is the boolean getter convention?
Click to reveal answer
Answer
getIsActive() for is_active field
Question
Where are field name constants defined?
Click to reveal answer
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()