Installation:
composer require awaresoft/redirect-bundle
Note: Due to symlinking requirements, follow the README's local setup guide if modifying the bundle.
Enable the Bundle:
Add to config/bundles.php:
return [
// ...
Awaresoft\RedirectBundle\AwaresoftRedirectBundle::class => ['all' => true],
];
Database Migration:
Run Doctrine migrations to create the redirect table:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
First Redirect:
Use the RedirectManager service in a controller:
use Awaresoft\RedirectBundle\Manager\RedirectManager;
class MyController extends AbstractController {
public function redirectAction(RedirectManager $redirectManager) {
$redirect = $redirectManager->createRedirect(
'/old-path',
'/new-path',
301 // HTTP status code
);
$redirectManager->save($redirect);
return $this->redirect('/new-path');
}
}
Creating Redirects:
RedirectManager to create and persist redirects.
$redirect = $redirectManager->createRedirect(
'/old-url',
'/new-url',
301,
['domain' => 'example.com'] // Optional: domain-specific redirects
);
$redirectManager->save($redirect);
make:crud or manually with forms tied to the Redirect entity.Handling Redirects:
kernel.request to auto-redirect old URLs:
use Awaresoft\RedirectBundle\Event\RedirectEvent;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
class RedirectListener {
public function onKernelRequest(RequestEvent $event) {
$dispatcher = $event->getRequest()->get('redirect_dispatcher');
$dispatcher->dispatch($event->getRequest());
}
}
Register in services.yaml:
services:
App\EventListener\RedirectListener:
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
Batch Processing:
EntityManager to bulk-insert redirects:
$redirects = [];
foreach ($oldUrls as $oldUrl) {
$redirects[] = $redirectManager->createRedirect($oldUrl, $newUrl, 301);
}
$entityManager->persist($redirects);
$entityManager->flush();
Domain-Specific Redirects:
$redirects = $redirectManager->findBy(['domain' => 'example.com']);
Symfony Forms:
Create a form type for the Redirect entity:
namespace App\Form;
use Awaresoft\RedirectBundle\Entity\Redirect;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class RedirectType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('oldPath', TextType::class)
->add('newPath', TextType::class)
->add('statusCode', IntegerType::class, ['data' => 301])
->add('domain', TextType::class, ['required' => false]);
}
}
API Endpoints: Expose redirects as JSON for frontend use:
use Symfony\Component\HttpFoundation\JsonResponse;
public function getRedirectsAction(RedirectManager $redirectManager) {
$redirects = $redirectManager->findAll();
return new JsonResponse(array_map(function($r) {
return [
'oldPath' => $r->getOldPath(),
'newPath' => $r->getNewPath(),
'statusCode' => $r->getStatusCode(),
];
}, $redirects));
}
Caching: Cache redirect lookups to reduce database hits:
# config/packages/cache.yaml
framework:
cache:
app.redirects:
provider: 'doctrine'
Then use CacheInterface in your listener:
$cache->get('redirects', function() use ($redirectManager) {
return $redirectManager->findAll();
});
Symlinking Requirements:
/src/Awaresoft or remove Composer’s autoload entry breaks the bundle.php bin/console cache:clear
after symlinking.Backward Compatibility:
git tag to version changes correctly (e.g., 1.0.1 for hotfixes).Domain Handling:
domain field may not work as expected in multi-domain setups.null for root-level redirects:
$redirectManager->createRedirect('/old', '/new', 301, ['domain' => null]);
Performance:
findBy() queries.old_path and domain columns in your migration:
// src/Migrations/VersionYYYYMMDDHHMMSS.php
public function up(Schema $schema) {
$table = $schema->getTable('redirect');
$table->addIndex(['old_path'], 'IDX_REDIRECT_OLD_PATH');
$table->addIndex(['domain'], 'IDX_REDIRECT_DOMAIN');
}
HTTP Status Codes:
302 (temporary) instead of 301 (permanent) for SEO-critical redirects.301 unless temporary redirects are explicitly needed.Missing Redirects:
RedirectListener is registered and the redirect_dispatcher service is injected.$this->logger->debug('Dispatching redirects for: ' . $request->getUri());
Symlink Issues:
composer dump-autoload after symlinking.vendor/composer/autoload_psr4.php) includes:
'Awaresoft\\' => __DIR__ . '/../src/Awaresoft',
Database Errors:
redirect table exists and matches the entity schema. Run:
php bin/console doctrine:schema:validate
Custom Redirect Logic:
RedirectManager to add validation or preprocessing:
class CustomRedirectManager extends RedirectManager {
public function createRedirect($oldPath, $newPath, $statusCode = 301, array $options = []) {
if (strpos($oldPath, 'admin/') === 0) {
throw new \RuntimeException('Cannot redirect admin paths');
}
return parent::createRedirect($oldPath, $newPath, $statusCode, $options);
}
}
Override the service in services.yaml:
services:
Awaresoft\RedirectBundle\Manager\RedirectManager: '@App\Manager\CustomRedirectManager'
Event Dispatching:
redirect.pre_save and redirect.post_save events to add custom logic:
services:
App\EventSubscriber\RedirectSubscriber:
tags:
- { name: kernel.event_subscriber }
use Awaresoft\RedirectBundle\Event\RedirectEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class RedirectSubscriber implements EventSubscriberInterface {
public static function getSubscribedEvents() {
return [
RedirectEvents::PRE_SAVE => 'onPreSave',
RedirectEvents::POST_SAVE => 'onPostSave',
];
}
public function on
How can I help you explore Laravel packages today?