Installation
composer require bsadnu/grand-id-bundle
Ensure GrandIDBundle is enabled in config/bundles.php:
return [
// ...
GrandID\Bundle\GrandIDBundle::class => ['all' => true],
];
Configuration
Add your Grand ID credentials to config/packages/grand_id.yaml:
grand_id:
client_id: '%env(GRAND_ID_CLIENT_ID)%'
client_secret: '%env(GRAND_ID_CLIENT_SECRET)%'
api_url: 'https://api.grandid.com'
First Use Case: Authentication
Inject the GrandIDService into a controller and initiate a login:
use GrandID\Bundle\GrandIDBundle\Service\GrandIDService;
class AuthController extends Controller
{
public function login(GrandIDService $grandID): Response
{
$authUrl = $grandID->getAuthUrl('http://your-callback-url.com');
return redirect($authUrl);
}
}
Database Migration
Run migrations to create the required grand_id_sessions table:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
handleCallback() method to process Grand ID responses:
public function callback(GrandIDService $grandID, Request $request): Response
{
$session = $grandID->handleCallback($request);
// Store session data in your user system
return $this->redirectToRoute('home');
}
refreshToken():
$grandID->refreshToken($sessionId);
$mockSession = $grandID->createMockSession([
'user_id' => 'test123',
'email' => 'user@example.com',
]);
$session = $grandID->getSessionById($sessionId);
$userData = $grandID->getUserData($accessToken);
grand_id.session.created) in config/services.yaml:
services:
App\EventListener\GrandIDListener:
tags:
- { name: 'kernel.event_listener', event: 'grand_id.session.created', method: 'onSessionCreated' }
Service Container Binding
Bind the Symfony service to Laravel’s container in AppServiceProvider:
public function register()
{
$this->app->singleton('grandID', function ($app) {
return $this->app->make('grand_id.service');
});
}
Request Handling
Use Laravel’s Request facade with Symfony’s GrandIDService:
use Illuminate\Support\Facades\Request;
public function callback(GrandIDService $grandID): Response
{
$session = $grandID->handleCallback(Request::capture());
// ...
}
Database Integration
Extend the GrandIDSession entity to add Laravel-specific fields (e.g., user_id):
// src/Entity/GrandIDSession.php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use GrandID\Bundle\GrandIDBundle\Entity\GrandIDSession as BaseGrandIDSession;
#[ORM\Entity]
class GrandIDSession extends BaseGrandIDSession
{
#[ORM\Column(type: 'integer', nullable: true)]
private ?int $userId = null;
}
Mocking in Tests Use the mock system for unit tests:
public function testGrandIDLogin()
{
$grandID = $this->app->make('grandID');
$mockSession = $grandID->createMockSession(['email' => 'test@example.com']);
$this->assertEquals('test@example.com', $grandID->getSessionById($mockSession->getId())->getEmail());
}
Deprecated API
/auth, /user) against Grand ID’s latest docs.GrandIDService class.Database Schema Mismatch
grand_id_sessions table assumes specific fields (e.g., session_id, access_token). Custom fields may break functionality.GrandIDSession entity (as shown above) and update migrations:
php bin/console doctrine:schema:update --force
Token Expiry Handling
grand_id.token.expired or manually check token validity:
if ($grandID->isTokenExpired($session)) {
$grandID->refreshToken($session->getId());
}
Symfony-Specific Assumptions
HttpFoundation and EventDispatcher. In Laravel, wrap interactions in try-catch blocks for Request or Response objects:
try {
$authUrl = $grandID->getAuthUrl('http://callback.url');
} catch (\InvalidArgumentException $e) {
return response()->json(['error' => 'Invalid callback URL'], 400);
}
Enable Debug Mode
Set GRAND_ID_DEBUG=true in .env to log API requests/responses:
# config/packages/grand_id.yaml
grand_id:
debug: '%env(bool:GRAND_ID_DEBUG)%'
Mock Debugging Verify mock sessions are stored correctly:
php bin/console doctrine:query:sql "SELECT * FROM grand_id_sessions"
API Response Validation Grand ID may return non-200 responses. Validate responses in a custom service layer:
public function getUserData(string $token): array
{
$response = $this->grandID->getUserData($token);
if ($response['status'] !== 200) {
throw new \RuntimeException('Grand ID API error: ' . $response['body']);
}
return json_decode($response['body'], true);
}
Custom Session Storage
Override the GrandIDSessionManager to use Laravel’s cache or session driver:
// src/Service/CustomGrandIDSessionManager.php
namespace App\Service;
use GrandID\Bundle\GrandIDBundle\Service\GrandIDSessionManager;
use Illuminate\Support\Facades\Cache;
class CustomGrandIDSessionManager extends GrandIDSessionManager
{
public function saveSession($session)
{
Cache::put("grand_id_{$session->getId()}", $session, now()->addHours(1));
}
public function findSessionById($id)
{
return Cache::get("grand_id_{$id}");
}
}
Event Customization
Extend the GrandIDEvents class to add Laravel-specific events:
// src/Event/GrandIDLaravelEvents.php
namespace App\Event;
use Symfony\Contracts\EventDispatcher\Event;
final class GrandIDLaravelEvents
{
public const USER_LOGIN = 'grand_id.user.login';
}
API Client Wrapper
Replace the underlying HTTP client (e.g., Symfony’s HttpClient) with Guzzle for Laravel:
// src/Service/CustomGrandIDService.php
use GuzzleHttp\Client;
class CustomGrandIDService extends GrandIDService
{
protected function createClient()
{
return new Client([
'base_uri' => $this->getApiUrl(),
'headers' => [
'Accept' => 'application/json',
],
]);
}
}
GRAND_ID_CLIENT_ID and GRAND_ID_CLIENT_SECRET are set in .env:
GRAND_ID_CLIENT_ID=your_client_id_here
GRAND_ID_CLIENT_SECRET=your_secret_here
How can I help you explore Laravel packages today?