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

Achievement Bundle Laravel Package

cunningsoft/achievement-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require cunningsoft/achievement-bundle:~0.2
    

    Register the bundle in config/bundles.php (Symfony 4+) or AppKernel.php (Symfony 2/3):

    Cunningsoft\AchievementBundle\CunningsoftAchievementBundle::class => ['all' => true],
    
  2. User Entity: Implement AchievementUserInterface in your User entity:

    use Cunningsoft\AchievementBundle\Entity\UserInterface;
    use Doctrine\Common\Collections\ArrayCollection;
    use Doctrine\ORM\Mapping as ORM;
    
    class User implements UserInterface
    {
        /**
         * @ORM\OneToMany(targetEntity="Cunningsoft\AchievementBundle\Entity\Achievement", mappedBy="user")
         */
        private $achievements;
    
        public function __construct()
        {
            $this->achievements = new ArrayCollection();
        }
    
        // ... (implement UserInterface methods)
    }
    
  3. First Use Case: Create an achievement via CLI or controller:

    $achievement = new Achievement();
    $achievement->setName('First Login')
                ->setDescription('Complete your first login')
                ->setPoints(10)
                ->setUser($user);
    $em->persist($achievement);
    $em->flush();
    

Implementation Patterns

Core Workflows

  1. Triggering Achievements: Use the AchievementManager service to check/unlock achievements:

    $manager = $this->container->get('cunningsoft_achievement.manager');
    $achievement = $manager->unlockAchievement('first_login', $user);
    
  2. Dynamic Conditions: Extend AchievementCondition for custom logic (e.g., "User completes 5 orders"):

    class OrderCountCondition extends AchievementCondition
    {
        public function isMet(UserInterface $user)
        {
            return $user->getOrderCount() >= 5;
        }
    }
    
  3. Event-Based Unlocks: Listen to Symfony events (e.g., kernel.request) to auto-unlock achievements:

    # services.yaml
    services:
        App\EventListener\AchievementListener:
            tags:
                - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
    
  4. Batch Processing: Use AchievementBatchProcessor for bulk operations (e.g., retroactive unlocks):

    $processor = new AchievementBatchProcessor($em);
    $processor->processAchievements($user, ['first_login', 'level_1']);
    

Integration Tips

  • Twig Integration: Display achievements in templates:

    {% for achievement in user.achievements %}
        <div class="achievement">
            <h3>{{ achievement.name }}</h3>
            <p>{{ achievement.description }}</p>
            {% if not achievement.isUnlocked() %}
                <span class="locked">[Locked]</span>
            {% endif %}
        </div>
    {% endfor %}
    
  • API Responses: Serialize achievements for APIs:

    $serializer = $this->container->get('serializer');
    $achievements = $serializer->serialize($user->getAchievements(), 'json');
    
  • Admin Panel: Create a CRUD interface for managing achievements (e.g., using EasyAdmin or SonataAdmin).


Gotchas and Tips

Pitfalls

  1. Entity Mapping:

    • Forgetting to implement UserInterface methods (e.g., getAchievements()) will cause runtime errors.
    • Ensure Achievement entity is properly mapped in your User entity’s OneToMany relation.
  2. Condition Logic:

    • Custom conditions must return true/false strictly; edge cases (e.g., null user data) may break unlocks.
    • Cache condition results if performance is critical (e.g., @Cache in Symfony).
  3. Database Schema:

    • The bundle assumes Achievement has fields like insertDate, points, etc. Override the entity if needed:
      use Cunningsoft\AchievementBundle\Entity\Achievement as BaseAchievement;
      
      class Achievement extends BaseAchievement
      {
          // Add custom fields here
      }
      
  4. Symfony 4+ Compatibility:

    • The bundle is Symfony 2/3-focused. For Symfony 4+, use autowiring or manually define services:
      services:
          Cunningsoft\AchievementBundle\Manager\AchievementManager: ~
      

Debugging

  • Unlocked Achievements: Check the database directly or dump the UserInterface object:

    dump($user->getAchievements()->filter(fn($a) => $a->isUnlocked()));
    
  • Condition Failures: Log condition results for debugging:

    class DebugCondition extends AchievementCondition
    {
        public function isMet(UserInterface $user)
        {
            $result = parent::isMet($user);
            $this->logger->debug(sprintf(
                'Condition "%s" for user %d: %s',
                $this->getName(),
                $user->getId(),
                $result ? 'MET' : 'FAILED'
            ));
            return $result;
        }
    }
    

Extension Points

  1. Custom Achievement Types: Extend Achievement to add metadata (e.g., ImageAchievement):

    class ImageAchievement extends Achievement
    {
        private $imageUrl;
    
        // Getters/setters
    }
    
  2. Event Dispatching: Trigger custom events when achievements are unlocked:

    $event = new AchievementUnlockedEvent($achievement, $user);
    $this->eventDispatcher->dispatch($event, 'achievement.unlocked');
    
  3. Validation: Add constraints to achievements (e.g., Points must be positive):

    use Symfony\Component\Validator\Constraints as Assert;
    
    class Achievement
    {
        /**
         * @Assert\Positive
         */
        private $points;
    }
    
  4. Localization: Override achievement names/descriptions per locale:

    $achievement->setName('First Login', 'en');
    $achievement->setName('Première connexion', 'fr');
    
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui