Weave 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

Competitionbundle Laravel Package

atm/competitionbundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the bundle via Composer:

    composer require atm/competitionbundle
    

    Register the bundle in config/app.php under providers:

    Altuma\CompetitionBundle\CompetitionBundle::class,
    
  2. Publish Assets Run the following command to publish configuration and migrations:

    php artisan vendor:publish --provider="Altuma\CompetitionBundle\CompetitionBundle" --tag="config"
    php artisan vendor:publish --provider="Altuma\CompetitionBundle\CompetitionBundle" --tag="migrations"
    

    Migrate the database:

    php artisan migrate
    
  3. First Use Case: Creating a Competition Define a competition in your database via the competitions table or use the bundle’s API:

    use Altuma\CompetitionBundle\Entity\Competition;
    
    $competition = new Competition();
    $competition->setName('Summer Sale 2024');
    $competition->setStartDate(new \DateTime('2024-06-01'));
    $competition->setEndDate(new \DateTime('2024-06-30'));
    $competition->setDescription('Win discounts on all products!');
    $competition->setStatus(Competition::STATUS_ACTIVE);
    
    $em = $this->getDoctrine()->getManager();
    $em->persist($competition);
    $em->flush();
    
  4. Routing The bundle includes basic routes for listing and managing competitions. Ensure your routes.php includes:

    use Altuma\CompetitionBundle\Resources\routing\competition_routing;
    competition_routing($router);
    

Implementation Patterns

Core Workflows

  1. Competition Management

    • CRUD Operations: Use the bundle’s repository (Altuma\CompetitionBundle\Repository\CompetitionRepository) for database interactions.
      $competitions = $competitionRepo->findBy(['status' => Competition::STATUS_ACTIVE]);
      
    • Status Transitions: Handle state changes (e.g., STATUS_DRAFT → STATUS_ACTIVE) with validation:
      if ($competition->getStatus() === Competition::STATUS_DRAFT) {
          $competition->setStatus(Competition::STATUS_ACTIVE);
          $competition->setStartDate(new \DateTime());
      }
      
  2. Participation Logic

    • User Participation: Extend the Participation entity or create a custom service to track user entries:
      $participation = new \Altuma\CompetitionBundle\Entity\Participation();
      $participation->setCompetition($competition);
      $participation->setUser($this->getUser());
      $participation->setEntryData(['product_id' => 123]);
      $em->persist($participation);
      
    • Entry Validation: Override the isValid() method in a custom Participation class to enforce rules (e.g., one entry per user).
  3. Event-Driven Competitions

    • Listeners: Subscribe to competition events (e.g., competition.activated) to trigger side effects:
      // In a service or controller
      $event = new CompetitionActivatedEvent($competition);
      $this->get('event_dispatcher')->dispatch(
          'competition.activated',
          $event
      );
      
    • Common Events:
      • competition.created
      • competition.updated
      • competition.deactivated
      • participation.submitted
  4. Integration with Frontend

    • API Endpoints: Use Symfony’s serializers to expose competition data:
      use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
      
      $normalizer = new ObjectNormalizer();
      $competitionData = $normalizer->normalize($competition);
      
    • Twig Templates: Access competitions in templates via the competition service:
      {% for competition in competitions %}
          <div class="competition-card">
              <h3>{{ competition.name }}</h3>
              <p>Ends: {{ competition.endDate|date('M d, Y') }}</p>
          </div>
      {% endfor %}
      
  5. Scheduling

    • Automated Status Updates: Use Laravel’s task scheduling to handle date-based transitions:
      // In app/Console/Kernel.php
      $schedule->call(function () {
          $now = new \DateTime();
          $competitionRepo->updateStatusesByDate($now);
      })->daily();
      

Gotchas and Tips

Common Pitfalls

  1. Database Schema Assumptions

    • The bundle expects specific columns (e.g., start_date, end_date). Custom migrations may conflict if not aligned.
    • Fix: Override migrations or use doctrine extensions to add custom fields.
  2. Status Transitions Without Validation

    • Directly setting status without checking current state can lead to invalid transitions (e.g., STATUS_ACTIVE → STATUS_DRAFT).
    • Fix: Use a state machine pattern or validation rules:
      if (!$competition->canTransitionTo($newStatus)) {
          throw new \RuntimeException('Invalid transition');
      }
      
  3. Participation Duplicates

    • Users may submit multiple entries if not properly validated.
    • Fix: Add a unique constraint on (competition_id, user_id) or use a service to deduplicate:
      $existing = $participationRepo->findOneBy([
          'competition' => $competition,
          'user' => $user,
      ]);
      if ($existing) {
          throw new \RuntimeException('Already participated');
      }
      
  4. Time Zone Handling

    • Dates in the competitions table are stored as UTC. Ensure frontend/backend time zones are consistent.
    • Fix: Use Carbon for conversions:
      $localEndDate = $competition->getEndDate()->setTimezone(new \DateTimeZone('America/New_York'));
      
  5. Event Dispatching Order

    • Events may fire in unexpected orders (e.g., updated before created).
    • Fix: Dispatch events at the end of the transaction or use event priorities.

Debugging Tips

  1. Log Competition Events Add a subscriber to log events for debugging:

    use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    
    class CompetitionLoggingSubscriber implements EventSubscriberInterface
    {
        public static function getSubscribedEvents()
        {
            return [
                'competition.activated' => 'logEvent',
            ];
        }
    
        public function logEvent($event)
        {
            \Log::info('Competition activated', ['competition' => $event->getCompetition()]);
        }
    }
    
  2. Check Repository Methods The bundle’s repository may not cover all use cases. Extend it:

    class CustomCompetitionRepository extends ServiceEntityRepository
    {
        public function findActiveWithParticipants()
        {
            return $this->createQueryBuilder('c')
                ->leftJoin('c.participations', 'p')
                ->where('c.status = :status')
                ->setParameter('status', Competition::STATUS_ACTIVE)
                ->getQuery()
                ->getResult();
        }
    }
    
  3. Configuration Overrides Override bundle config in config/packages/altuma_competition.yaml:

    altuma_competition:
        default_status: STATUS_DRAFT  # Override default
        participation_limit: 100      # Per competition
    

Extension Points

  1. Custom Participation Rules Extend the Participation entity or create a trait:

    namespace App\Entity;
    
    use Altuma\CompetitionBundle\Entity\Participation as BaseParticipation;
    use Doctrine\ORM\Mapping as ORM;
    
    #[ORM\Entity]
    class Participation extends BaseParticipation
    {
        public function isValid(): bool
        {
            if (!$this->getUser()->hasPromoCode()) {
                return false;
            }
            return parent::isValid();
        }
    }
    
  2. Dynamic Competition Fields Use doctrine extensions or a json column to store dynamic data:

    $competition->setMetadata(['max_entries' => 50, 'prize' => '10% off']);
    
  3. Third-Party Integrations

    • Mailchimp: Sync participants via the participation.submitted event.
    • Stripe: Charge entry fees by listening to participation.validated.
    $event->getParticipation()->setPaymentStatus('paid');
    \Stripe\Charge::create([...]);
    
  4. Testing Use the bundle’s entities in PHPUnit tests:

    public function testCompetitionCreation()
    {
        $competition = new Competition();
        $competition
    
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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel