Symfony repository - a little practice

Một vài practices và conventions có thể giúp cho việc sử dụng repository của bạn dễ thở hơn ;)

1. Define repository as service

1
2
3
4
app.repository.user:
class: Doctrine\ORM\EntityRepository
factory: ['@doctrine.orm.entity_manager', getRepository]
arguments: [AppBundle\Entity\User]

Sử dụng:

1
2
3
4
5
// old
$repository = $this->getDoctrine()->getRepository('AppBundle:User');

// new
$repository = $this->get('app.repository.user');

Việc khai báo repository thành service có các lợi điểm:

  • Dễ dàng inject vào các service khác (thể hiện rõ ràng service depends những cháu nào)
  • Khi thay đổi repository class chỉ việc thay đổi một chỗ ở service.yml

2. Put save method to repository

1
2
3
4
5
6
7
8
class ProfileRepository extends EntityRepository
{
public function save(Profile $profile)
{
$this->_em->persist($profile);
$this->_em->flush();
}
}

Sử dụng sẽ gọn gàng hơn:

1
2
3
4
5
6
7
8
9
10
$profile = new Profile();

// old
$em = $this->getDoctrine()->getManager();
$em->persist($profile);
$em->flush();

// new
$repository = $this->get('app.repository.profile');
$repository->save($profile);

Ngoài ra có thêm 1 lợi điểm nữa là có thể tương tác với entity trước khi save vào db, ví dụ thay đổi giá trị updatedAt = new \DateTime()

3. Document var

Khi sử dụng method custom của repository, nên có document var cho repository. Lợi điểm là:

  • Dễ tìm được những nơi nào sử dụng method này (Find Usage)
  • Dễ tìm tới nơi define method (Go to Declaration)
1
2
3
4
5
6
7
// don't need declare document var because this repository use find method (base method)
$repository = $this->get('app.repository.order');
$order = $repository->find($id);

/** @var PostRepository $repository */
$repository = $this->get('app.repository.post');
$post = $repository->findByCategoryAndAuthor($category, $author);

4. Method Custom Naming

Chúng ta nên có những quy chuẩn để việc sử dụng các method custom được dễ dàng hơn

  • findBy...: trả về array các object mục tiêu (vs UserRepository trả về array object User) hoặc array rỗng
  • find...: trả về object mục tiêu hoặc null
  • get...: trả về các kết quả không phải là object mục tiêu. Vd: trong UserRepository có method getIds sẽ trả về array các id của User. Với loại này, cần lưu ý:
    • throw Exception mái thoải
    • nên có document dữ liệu sample trả về
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* @return array ['mbchest', 'mbheight']
*/
public function getIdsByGenderAndType(string $gender, string $type): array
{
$alias = 'm';
$result = $this->createQueryBuilder($alias)
->select($alias.'.id')
->where($alias.'.gender = :gender')
->andWhere($alias.'.type = :type')
->setParameters([
'gender' => $gender,
'type' => $type
])
->getQuery()->getResult();

$ids = array_column($result, 'id');

return $ids;
}

Feedback is welcome ;)