evheniy/robots-txt-bundle
Symfony2 bundle that generates robots.txt from config.yml entries, including sitemap lines, and dumps it via app/console robots.txt:dump. Supports separate per-environment rules so dev can Disallow: / while prod lists a sitemap.
composer require evheniy/robots-txt-bundle will only resolve cleanly on a Symfony 2.x app with a compatible PHP (5.5–7.x) constraint. In a modern app, expect to install it with --ignore-platform-reqs at best, or to fork it. Check composer show evheniy/robots-txt-bundle before committing.app/AppKernel.php:
new Evheniy\RobotsTxtBundle\RobotsTxtBundle(),
DependencyInjection/Configuration.php — the authoritative list of config keys (user agent, disallow/allow paths, sitemap, host, crawl-delay, etc.). This is where the package's actual API lives.Resources/config/routing.yml (and services.yml) — tells you whether the bundle exposes a /robots.txt route or a service you call from your own controller.README.md "Usage" — examples are sparse, so the DI config tree is your real documentation.# app/config/config.yml (default = locked down)
robots_txt:
user_agent: '*'
disallow: ['/']
# app/config/config_prod.yml
robots_txt:
user_agent: '*'
disallow: ['/admin', '/login', '/search']
sitemap: 'https://example.com/sitemap.xml'
Clear the cache (app/console cache:clear --env=prod) and hit /robots.txt in a browser to confirm the output before touching production.config.yml and open up only in config_prod.yml. This removes an entire class of "staging got indexed" incidents without code changes.web/robots.txt exists, the web server will usually win — delete it or you will spend an afternoon debugging "why isn't my config applied?"Disallow).sitemap: https://example.com/sitemap.xml, never /sitemap.xml. Some crawlers tolerate relative URLs; many don't./robots.txt and asserts 200 plus a marker string (e.g. your sitemap URL) catches route regressions that unit tests miss:
$client = static::createClient();
$crawler = $client->request('GET', '/robots.txt');
$this->assertSame(200, $client->getResponse()->getStatusCode());
$this->assertContains('Sitemap: https://example.com/sitemap.xml', $client->getResponse()->getContent());
Cache-Control: max-age=3600) rather than rebuilding it per request.services.yaml conventions.composer.json and document the decision so a composer update doesn't silently drop the bundle.Configuration.php for the exact keys. A typo in the tree may be rejected by Symfony's config validator (good) or, worse, silently ignored if the tree is loosely defined.Disallow: vs Disallow: /. An empty Disallow allows everything; Disallow: / blocks everything. This is the classic staging-leak mistake — assert your test environment output explicitly.Disallow is advisory. Admin paths must still be behind auth; robots rules only reduce crawl noise and accidental indexing.curl -I https://example.com/robots.txt that Content-Type is text/plain and the body matches your config (a stale web/robots.txt will show Last-Modified from deploy, not request time).vendor/ — a fresh composer install will erase it.cache:clear the correct env → verify route exists (app/console debug:router | grep robots) → curl -I and curl the URL → if output is stale, check for a physical file and any reverse-proxy/CDN cache in front of the app.How can I help you explore Laravel packages today?