Repository Pattern in XOOPS¶
2.5.x ✅ 2026 ✅
Not sure if this is the right pattern?
See Choosing a Data Access Pattern for a decision tree comparing handlers, repositories, services, and CQRS.
Works Today & Tomorrow
The Repository pattern works in both XOOPS 2.5.x and 2026. In 2.5.x, wrap your existing XoopsPersistableObjectHandler in a Repository class to get the abstraction benefits:
| Approach | XOOPS 2.5.x | XOOPS 2026 |
|---|---|---|
| Direct handler access | xoops_getModuleHandler() | Via DI container |
| Repository wrapper | ✅ Recommended | ✅ Native pattern |
| Testing with mocks | ✅ With manual DI | ✅ Container autowiring |
Start with Repository pattern today to prepare your modules for easier 2026 migration.
The Repository Pattern is a data access pattern that abstracts database operations, providing a clean interface for accessing data. It acts as a middleman between the business logic and data mapping layers.
Repository Concept¶
The Repository Pattern provides: - Abstraction of database implementation details - Easy mocking for unit testing - Centralized data access logic - Flexibility to change database without affecting business logic - Reusable data access logic across the application
When to Use Repositories¶
Use Repositories when: - Transferring data between application layers - Needing to change database implementation - Writing testable code with mocks - Abstracting data access patterns
Implementation Pattern¶
<?php
// Define repository interface
interface UserRepositoryInterface
{
public function find($id);
public function findAll($limit = null, $offset = 0);
public function findBy(array $criteria);
public function save($entity);
public function update($id, $entity);
public function delete($id);
}
// Implement repository
class UserRepository implements UserRepositoryInterface
{
private $db;
public function __construct($connection)
{
$this->db = $connection;
}
public function find($id)
{
// Implementation
}
public function save($entity)
{
// Implementation
}
}
?>
Usage in Services¶
<?php
class UserService
{
private $userRepository;
public function __construct(UserRepositoryInterface $userRepository)
{
$this->userRepository = $userRepository;
}
public function registerUser($username, $email, $password)
{
// Check if user exists
if ($this->userRepository->findByUsername($username)) {
throw new \InvalidArgumentException('Username exists');
}
// Create user
$user = new User();
$user->setUsername($username);
$user->setEmail($email);
$user->setPassword($password);
return $this->userRepository->save($user);
}
}
?>
Best Practices¶
- Use interfaces to define repository contracts
- Each repository handles one entity type
- Keep business logic in services, not repositories
- Use entity objects for data mapping
- Throw appropriate exceptions for invalid operations
Related Documentation¶
See also: - MVC-Pattern for controller integration - Service-Layer for service implementation - DTO-Pattern for data transfer objects - Testing for repository testing
Tags: #repository-pattern #data-access #design-patterns #module-development