Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Deadlink Bundle Laravel Package

astina/deadlink-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install via Composer (note: use a stable version if available, not dev-master):
    composer require astina/deadlink-bundle:1.2.1
    
  2. Enable the Bundle in config/bundles.php (Symfony 4+) or AppKernel.php (Symfony 2/3):
    return [
        // ...
        Astina\Bundle\DeadlinkBundle\AstinaDeadlinkBundle::class => ['all' => true],
    ];
    
  3. Run the Check Command (immediate first use case):
    php bin/console astina:deadlink:check
    
    Verify the command executes without errors and logs output (if LoggingListener is configured).

First Use Case: Checking Doctrine Entities

  1. Configure a DoctrineLinkSource in config/services.yaml:
    services:
        App\Deadlink\MyEntityLinkSource:
            class: Astina\Bundle\DeadlinkBundle\Doctrine\DoctrineLinkSource
            arguments:
                - '@doctrine'
                - 'App\Entity\Post'  # Your entity class
                - ['content', 'metaDescription']  # Fields containing URLs
                - []  # Optional: Criteria to filter entities (e.g., `{'published': true}`)
            tags:
                - { name: astina_deadlink.link_source }
    
  2. Run the Check:
    php bin/console astina:deadlink:check
    
    Broken links in Post entities will trigger the astina_deadlink.broken_links event.

Implementation Patterns

Core Workflow: Event-Driven Link Validation

  1. Define Link Sources:

    • Extend LinkSourceInterface for custom sources (e.g., scraping HTML, checking API responses).
    • Example: A CmsPageLinkSource to validate links in a CMS.
    class CmsPageLinkSource implements LinkSourceInterface {
        public function getLinks() {
            // Fetch links from your CMS (e.g., database, API).
            return ['https://example.com/page1', 'https://example.com/page2'];
        }
    }
    
    • Tag the service:
      tags:
          - { name: astina_deadlink.link_source }
      
  2. Handle Broken Links:

    • Subscribe to astina_deadlink.broken_links:
      class DeadlinkNotifier {
          public function onBrokenLinks(BrokenLinksEvent $event) {
              $brokenLinks = $event->getBrokenLinks();
              // Send email, update database, etc.
          }
      }
      
      services:
          App\Deadlink\DeadlinkNotifier:
              tags:
                  - { name: kernel.event_listener, event: astina_deadlink.broken_links, method: onBrokenLinks }
      
  3. Schedule Checks:

    • Use Symfony’s CronBundle or a CI/CD pipeline to run astina:deadlink:check periodically (e.g., nightly).

Integration Tips

  1. Doctrine Integration:

    • Use DoctrineLinkSource for entities with URL fields. Filter entities with DQL criteria:
      arguments:
          - '@doctrine'
          - 'App\Entity\Product'
          - ['url', 'thumbnail']
          - [{ 'active': true }]  # Only check active products
      
  2. Custom Link Extraction:

    • Override getLinks() to parse URLs from non-Doctrine sources (e.g., files, APIs):
      public function getLinks() {
          $html = file_get_contents('https://example.com');
          preg_match_all('/https?://[^\s]+/i', $html, $matches);
          return $matches[0];
      }
      
  3. Logging Configuration:

    • Customize log levels in config/packages/monolog.yaml:
      handlers:
          deadlink:
              type: stream
              path: "%kernel.logs_dir%/deadlinks.log"
              level: critical  # or error, warning
      
    • Ensure LoggingListener is enabled (see README).
  4. Testing:

    • Mock LinkSourceInterface in PHPUnit to test event listeners:
      $linkSource = $this->createMock(LinkSourceInterface::class);
      $linkSource->method('getLinks')->willReturn(['http://broken-link.test']);
      $container->set('my_link_source', $linkSource);
      

Gotchas and Tips

Pitfalls

  1. Outdated Dependencies:

  2. Event Dispatching Issues:

    • If BrokenLinksEvent isn’t triggered, verify:
      • The astina_deadlink.link_source tag is correctly applied to your service.
      • The LinkSourceInterface implementation returns valid URLs (no empty strings or malformed links).
      • The DeadlinkFinder service is autowired (it’s registered automatically by the bundle).
  3. Performance:

    • Checking large datasets (e.g., thousands of Doctrine entities) may time out. Add batch processing:
      // In your LinkSourceInterface implementation
      public function getLinks() {
          $em = $this->doctrine->getManager();
          $query = $em->createQuery('SELECT e FROM App\Entity\Post e WHERE e.published = :published')
              ->setParameter('published', true)
              ->setMaxResults(100); // Limit per batch
          // ...
      }
      
  4. HTTP Client Limitations:

    • The bundle uses Symfony’s HttpClient (if available). For complex checks (e.g., redirects, auth), extend DeadlinkFinder or use a custom LinkValidatorInterface.

Debugging Tips

  1. Check Command Output:

    • Run with -v for verbose mode:
      php bin/console astina:deadlink:check -v
      
    • Look for errors in var/log/dev.log (Symfony 2/3) or var/log/debug.log (Symfony 4+).
  2. Validate URLs Manually:

    • Test URLs with curl or Postman to confirm they’re truly broken before debugging the bundle.
  3. Service Dumping:

    • Dump registered services to verify tags:
      php bin/console debug:container | grep -i deadlink
      

Extension Points

  1. Custom Link Validators:

    • Implement Astina\Bundle\DeadlinkBundle\Link\LinkValidatorInterface to add logic (e.g., check HTTP status codes, headers):
      class CustomValidator implements LinkValidatorInterface {
          public function isBroken($url) {
              $response = file_get_contents($url);
              return $response === false;
          }
      }
      
    • Bind it to the DeadlinkFinder service via dependency injection.
  2. Async Processing:

    • Dispatch broken links to a message queue (e.g., Symfony Messenger) instead of triggering events synchronously:
      use Symfony\Component\Messenger\MessageBusInterface;
      
      class AsyncDeadlinkListener {
          public function __construct(private MessageBusInterface $bus) {}
      
          public function onBrokenLinks(BrokenLinksEvent $event) {
              $this->bus->dispatch(new BrokenLinkMessage($event->getBrokenLinks()));
          }
      }
      
  3. GUI Dashboard:

    • Build a Twig template to display broken links from the BrokenLinksEvent data:
      {% for link in app.container.get('event_dispatcher').getListeners('astina_deadlink.broken_links')[0].getBrokenLinks() %}
          <li>{{ link.url }} (Status: {{ link.status }})</li>
      {% endfor %}
      

Configuration Quirks

  1. Service Overrides:

    • Override the default DeadlinkFinder or LoggingListener in config/services.yaml:
      services:
          Astina\Bundle\DeadlinkBundle\Event\LoggingListener:
              arguments:
                  - '@logger'
                  - 'error'  # Change log level
      
  2. Environment-Specific Checks:

    • Disable checks in config/packages/dev/astina_deadlink.yaml:
      astina_deadlink:
          enabled: false  # Skip in dev environment
      
    • Note: The bundle lacks built-in config keys; this requires patching or extending the bundle.
  3. Doctrine Criteria:

    • Use DQL expressions for complex filtering:
      arguments:
          - '@doctrine'
          - 'App\Entity\Article'
          - ['body']
          - [{ 'datePublished': { '>=': '2023-01-01' } }]  # Only recent
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
calmfox/watch-sylius
damienfern/grpc-symfony-bundle
atoolo/index-bundle
atoolo/genai-bundle
coprotoai/laravel-ticket
davidjln/llm-carbon-bundle
cryonighter/valid-request-bundle
coolms/taxonomy-bundle
coolms/field-bundle
articulate-orm/symfony
aaix/laravel-tall-architect
ephoto/akeneo-connector
emmanuelballery/eb-plantumlbundle
emielburgman/symfony-visitor-beacon
emielburgman/symfony-visit-storage
emielburgman/symfony-security-headers
emielburgman/symfony-log-viewer
emarref/xdebug-bundle
emarref/pubnub-bundle
elriseio/finance-money-bundle