# Symfony Cheat Sheet ## Cache Clearing To clear the Symfony cache, use one of the following commands: - Clear the entire cache: ```sh php bin/console cache:clear ``` - Clear all cache pools: ```sh php bin/console cache:pool:clear cache.global_clearer ``` - Clear a specific cache pool: ```sh php bin/console cache:pool:clear ``` ## Getting Routes To list all registered routes along with their paths, controllers, and other details, run: ```sh php bin/console debug:router ``` ## VarDump Server Debugging with the Symfony VarDump server: 1. **Install the package (for development only):** ```sh composer require --dev symfony/var-dumper ``` 2. **Start the VarDump server:** ```sh php bin/console server:dump ``` 3. **More information:** [Symfony VarDumper Docs](https://symfony.com/doc/current/components/var_dumper.html) ## Running the Messenger (Queue Background Worker) Consume messages from a queue with: ```sh php bin/console messenger:consume -vv ``` For example, consuming the `async` queue: ```sh php bin/console messenger:consume async -vv ``` ## Testing a Queue To ensure that a queue is working properly: 1. **Send a test message to the queue:** ```sh php bin/console messenger:dispatch 'App\Message\YourTestMessage' ``` 2. **Consume the message manually:** ```sh php bin/console messenger:consume async -vv ``` 3. **Check the transport status:** ```sh php bin/console messenger:stats ``` This will display the number of messages in each transport. If the message is processed correctly, then probably queue is working as expected. ## QueryBuilder Things Absolutely! Here's a solid list of tips for using Doctrine's `QueryBuilder` in Symfony efficiently and cleanly: --- ### 🚀 **Basic Usage Tips** 1. **Always alias your root entity** Use something short like `'c'` for `Customer`, `'u'` for `User`, etc. It makes your DQL much cleaner: ```php $qb = $this->createQueryBuilder('c'); ``` 2. **Use `setParameters()` for safety** Always bind values with parameters to prevent SQL injection and benefit from Doctrine's type handling: ```php $qb->where('c.status = :status') ->setParameter('status', 'active'); ``` 3. **Use `leftJoin()` when the relation might be missing** Prevents breaking the query if the join isn't always there: ```php $qb->leftJoin('c.orders', 'o'); ``` 4. **Avoid heavy logic in SELECT unless needed** Things like `CONCAT(...)` or complex functions should only go in if you're **actually returning** that field. Keep it simple unless it's for a computed column. --- ### 🧠 **Structural & Clean Code Tips** 5. **Build your columns in an array map** Here is an example using CONCAT in MySQL ```php $columns = [ 'fullName' => "CONCAT(c.firstName, ' ', c.lastName)", ]; ``` 6. **Split logic into reusable Criteria** Use Doctrine's `Criteria` or just conditionally chain to the builder: ```php if ($isArchived) { $qb->andWhere('c.archived = :archived') ->setParameter('archived', true); } ``` 7. **Use `Expr()` for advanced logic** It gives you a fluent way to build conditions: ```php $expr = $qb->expr(); $qb->andWhere($expr->orX( $expr->isNull('c.deletedAt'), $expr->eq('c.active', true) )); ``` --- ### ⚙️ **Performance Tips** 8. **Use `select()` early and only fetch what you need** Especially for large data sets — always prefer: ```php $qb->select('c.email', 'c.createdAt'); ``` over `select('c')` if you're not hydrating full entities. 9. **Paginate using `setFirstResult()` and `setMaxResults()`** You're already doing this, and it’s the best way for paginated APIs. 10. **Avoid N+1 problems** Use joins + select properly to eager load what you need: ```php $qb->leftJoin('c.orders', 'o') ->addSelect('o'); ``` --- ### 💡 **Debugging Tips** 11. **Use `getQuery()->getSQL()` to see raw SQL** Great for debugging what’s actually sent to DB: ```php dd($qb->getQuery()->getSQL()); ``` 12. **Use Doctrine Profiler in Symfony Web Debug Toolbar** It shows you all queries being executed per request, great to spot performance issues. --- ### 🧩 **Integration Tips** 13. **Integrate with custom `BaseQueryBuilder` for filtering/searching** Like you're doing — if you build reusable methods like `.buildFilters()`, keep the logic in one place and pass only what you need. 14. **Don’t use `->getResult()` unless you need entities** If you're using `SELECT partial` or scalar columns, use: ```php ->getArrayResult() ``` 15. **Hydrate wisely** Choose between `getResult()`, `getArrayResult()`, `getOneOrNullResult()` depending on the use case. --- If you’re doing complex search/filter/export logic (like your email-only mode), make sure your query is always *expressive* but still *performant*. You're on the right track with the column map and filtering logic. --- Generating fixtures Got it — you want: ✅ A **PHP script** (not Node) ✅ That **generates INSERT SQLs** for your `reservations` table ✅ With **experienceName**, **dateTime**, **netAmountPaidCents** randomized a bit ✅ No UI/form, just **generate the SQL lines** (you’ll paste/run them yourself) ✅ Ideally you want it to fit **Symfony standards** if possible (fixtures) --- ## Interesting PHP Pro tricks ### 🧪 Pro Tip: How to test what PHP "sees" when using Json_decode()? You can debug with: ```php var_dump(json_decode($jsonString, true)); // associative var_dump(json_decode($jsonString)); // objects ``` Or even this to visualize encoding: ```php $data = json_decode($jsonString, true); echo json_encode($data, JSON_PRETTY_PRINT); ``` --- ### TL;DR: PHP doesn't "know" these were objects originally. It just infers from: - Numeric arrays ➡️ encode as JSON arrays - Associative arrays ➡️ encode as JSON objects ## DDD things ### Controller design and return type Your method's return type should stay JsonResponse, because even though the method can throw exceptions internally, you catch those exceptions inside the method and convert them into JSON error responses. In PHP and Symfony controller methods: If your method handles exceptions internally and always returns a response, then the return type should be the actual return type (JsonResponse here). If your method would let exceptions bubble up (not catch them) and not return a value, you could consider : never or no explicit return type, but that’s rare in controllers. Since you catch exceptions inside and return a JSON error, your method always returns a JsonResponse.