Biplob Hossain

Repository-Based Service in Concrete CMS

February 1, 2025 | by biplob.ice

Repository-Based Service in Concrete CMS

In Concrete CMS, using repositories for data access is a best practice when working with Doctrine ORM. This approach keeps the service layer clean and focused on business logic while the repository handles database queries.

Step 1: Create the Entity (Database Table)

Concrete CMS uses Doctrine entities for database mapping. Let’s define a UserProfile entity.

File: packages/my_package/src/Entity/UserProfile.php

namespace MyPackage\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="MyPackage\Repository\UserProfileRepository")
 * @ORM\Table(name="UserProfiles")
 */
class UserProfile {
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue
     */
    protected $id;

    /** @ORM\Column(type="string") */
    protected $name;

    /** @ORM\Column(type="string", unique=true) */
    protected $email;

    // Getters and setters...
    public function getId(): int { return $this->id; }
    public function getName(): string { return $this->name; }
    public function setName(string $name): void { $this->name = $name; }
    public function getEmail(): string { return $this->email; }
    public function setEmail(string $email): void { $this->email = $email; }
}

✅ This creates a table UserProfiles with columns id, name, and email.

Step 2: Create the Repository (Handles Database Queries)

A repository acts as an abstraction layer between Doctrine and your service class.

File: packages/my_package/src/Repository/UserProfileRepository.php

namespace MyPackage\Repository;

use Doctrine\ORM\EntityRepository;
use MyPackage\Entity\UserProfile;

class UserProfileRepository extends EntityRepository {
    public function findByEmail(string $email): ?UserProfile {
        return $this->findOneBy(['email' => $email]);
    }

    public function save(UserProfile $user): void {
        $this->_em->persist($user);
        $this->_em->flush();
    }
}

✅ The repository provides methods to fetch and save user profiles.

Step 3: Create the Service (Uses Repository for Business Logic)

The service interacts with UserProfileRepository to perform actions.

File: packages/my_package/src/Service/UserProfileService.php

namespace MyPackage\Service;

use Doctrine\ORM\EntityManagerInterface;
use MyPackage\Entity\UserProfile;
use MyPackage\Repository\UserProfileRepository;

class UserProfileService {
    protected $repository;

    public function __construct(EntityManagerInterface $em) {
        $this->repository = $em->getRepository(UserProfile::class);
    }

    public function getUserByEmail(string $email): ?UserProfile {
        return $this->repository->findByEmail($email);
    }

    public function createUser(string $name, string $email): UserProfile {
        $user = new UserProfile();
        $user->setName($name);
        $user->setEmail($email);

        $this->repository->save($user);
        return $user;
    }
}

✅ The service class handles business logic like creating users or fetching by email.

Step 4: Register the Service in the Service Provider

Now, we need to register UserProfileService in Concrete CMS.

File: packages/my_package/src/ServiceProvider.php

namespace MyPackage;

use Concrete\Core\Foundation\Service\Provider as ServiceProvider;
use MyPackage\Service\UserProfileService;
use Concrete\Core\Support\Facade\Application;
use Doctrine\ORM\EntityManagerInterface;

class MyServiceProvider extends ServiceProvider {
    public function register() {
        $this->app->singleton(UserProfileService::class, function($app) {
            return new UserProfileService($app->make(EntityManagerInterface::class));
        });
    }
}

✅ This registers UserProfileService in Concrete CMS’s DI container.

Step 5: Use the Service in a Controller

Now, let’s use the service in a controller to manage users.

File: packages/my_package/controllers/single_page/dashboard/user_profiles.php

namespace Concrete\Package\MyPackage\Controller\SinglePage\Dashboard;

use Concrete\Core\Page\Controller\DashboardPageController;
use Concrete\Core\Support\Facade\Application;
use MyPackage\Service\UserProfileService;

class UserProfiles extends DashboardPageController {
    public function view() {
        $app = Application::getFacadeApplication();
        $userProfileService = $app->make(UserProfileService::class);

        // Create a new user
        $newUser = $userProfileService->createUser('John Doe', 'john@example.com');

        // Fetch a user by email
        $existingUser = $userProfileService->getUserByEmail('john@example.com');

        if ($existingUser) {
            echo "User found: " . $existingUser->getName();
        } else {
            echo "User not found.";
        }
    }
}

✅ The controller uses the UserProfileService to create and fetch user profiles.

Recap

  • Entity → Represents the database table (UserProfile).
  • Repository → Handles database operations (UserProfileRepository).
  • Service → Contains business logic (UserProfileService).
  • Service Provider → Registers the service in Concrete CMS.

This keeps the MVC structure clean and maintainable. 🚀

RELATED POSTS

View all

view all