Repositories
| Find by id | |
| Find by criteria | |
| Custom methods | |
| Inject repositories |
Find by id
Every entity has a repository: a small helper that loads rows of one table into objects. The simplest call is find with the primary key value.
The call returns the object when the row exists and null when nothing matches, so check the result before use. Controllers often turn the null case into a 404 page.
$product = $repository->find(1); if ($product === null) { throw $this->createNotFoundException("Product 1 is missing"); }
Find by criteria
Real pages need filters: active products first, newest items first, ten rows per page. The findBy helper takes criteria, order, and limit in that order.
The findOneBy twin takes criteria only and returns a single object or null. The findAll helper loads the whole table and suits small reference lists.
$cheap = $repository->findBy(["isActive" => true], ["price" => "ASC"], 10); $one = $repository->findOneBy(["slug" => "symfony-intro"]); $all = $repository->findAll();
Custom methods
Built-in helpers cover common cases, but business rules deserve clear names. A findActive method says what the query means and hides the criteria array from controllers.
Add the method to the repository class next to the generated code. It can reuse findBy inside, so the new query stays short and easy to test.
class ProductRepository extends ServiceEntityRepository { public function findActive(int $limit): array { return $this->findBy(["isActive" => true], ["price" => "ASC"], $limit); } }
Inject repositories
Repositories are services, so you never build them by hand. Type-hint the repository in the controller constructor and Symfony passes the right object automatically.
Store it in a property and call it from any action. The same style works for every entity in the project.
public function __construct(private ProductRepository $products) { } $list = $this->products->findAll();
Next: Relations
Article author: Arthur Isaev