becklyn/video-platforms
Symfony bundle providing helpers to parse and normalize video URLs (YouTube/Vimeo etc.), serialize/store as “platform@id” or arrays, validate via constraints, and integrate with entities and forms using a VideoUrlType.
Installation
composer require becklyn/video-platforms
Ensure your Laravel project uses Symfony components (e.g., via symfony/http-foundation or symfony/validator).
First Use Case: Parsing a Video URL
Parse a YouTube/Vimeo URL into a normalized Video object:
use Becklyn\VideoPlatforms\Video\Video;
$video = Video::unserialize('youtube@dQw4w9WgXcQ'); // Direct serialization
// OR
$video = (new \Becklyn\VideoPlatforms\Parser\VideoUrlParser())->parse('https://youtu.be/dQw4w9WgXcQ');
Key Files to Review
src/Video/Video.php (Core class for video storage/serialization).src/Form/Type/VideoUrlType.php (Form integration).src/Validation/Constraint/VideoUrl.php (Validation rules).Store video URLs as JSON in Doctrine entities (adapt for Laravel Eloquent):
use Becklyn\VideoPlatforms\Video\Video;
use Illuminate\Database\Eloquent\Model;
class VideoPost extends Model {
protected $casts = ['video' => 'array']; // Cast to array for JSON storage
public function getVideo(): ?Video {
return $this->video ? Video::createFromArray($this->video) : null;
}
public function setVideo(?Video $video): void {
$this->video = $video?->toArray();
}
}
Use VideoUrlType in Laravel Form Requests (via symfony/form or custom wrapper):
use Becklyn\VideoPlatforms\Form\Type\VideoUrlType;
use Illuminate\Http\Request;
class StorePostRequest extends FormRequest {
public function rules(): array {
return [
'video' => ['required', new \Becklyn\VideoPlatforms\Validation\Constraint\VideoUrl([
'platforms' => ['youtube', 'vimeo']
])],
];
}
}
Validate URLs in Laravel rules:
use Becklyn\VideoPlatforms\Validation\Constraint\VideoUrl;
use Illuminate\Validation\Rule;
// In a FormRequest or Controller
$validator = Validator::make($request->all(), [
'video_url' => [
'required',
function ($attribute, $value, $fail) {
$constraint = new VideoUrl(['platforms' => ['youtube']]);
if (!$constraint->validate($value, new \Symfony\Component\Validator\Context\ExecutionContext())) {
$fail('Invalid video URL.');
}
},
],
]);
Extend support for platforms like TikTok:
use Becklyn\VideoPlatforms\Parser\VideoPlatformInterface;
class TikTokPlatform implements VideoPlatformInterface {
public function getPlatform(): string { return 'tiktok'; }
public function parse(string $url): ?string { /* Logic */ }
}
// Register via service provider (Laravel)
$this->app->bind(\Becklyn\VideoPlatforms\Parser\VideoPlatformInterface::class, function () {
return collect([new TikTokPlatform()]);
});
Store/Retrieve videos as strings (e.g., in a video_url column):
$video = Video::unserialize('vimeo@123456789');
$serialized = $video->serialize(); // 'vimeo@123456789'
Platform Clashes
12345) may conflict between platforms (e.g., YouTube 12345 vs. Vimeo 12345). Always use full URLs or serialized strings (platform@id) in forms.Doctrine vs. Eloquent
protected $casts = ['video' => 'array'];
Validation Quirks
@VideoUrl constraint requires Symfony’s validator. For Laravel, use the custom rule above or wrap it in a trait:
use Becklyn\VideoPlatforms\Validation\Constraint\VideoUrl as VideoUrlConstraint;
class VideoUrlRule extends Rule {
public static function videoUrl(array $config = []) {
return function ($attribute, $value, $fail) {
$constraint = new VideoUrlConstraint($config);
if (!$constraint->validate($value, new \Symfony\Component\Validator\Context\ExecutionContext())) {
$fail('Invalid video URL.');
}
};
}
}
Deprecated Parser
VideoUrlParser was removed in v2.0. Use Video::unserialize() or platform-specific parsers directly.$video = Video::unserialize('youtube@dQw4w9WgXcQ');
dd($video->toArray()); // Debug normalized output
$parser = new \Becklyn\VideoPlatforms\Parser\VideoUrlParser();
$parser->parse('https://youtu.be/dQw4w9WgXcQ?feature=share'); // Should work
$parser->parse('vimeo.com/12345'); // May fail (use full URL)
Custom Serialization
Override Video::serialize()/unserialize() for custom formats:
class CustomVideo extends Video {
public function serialize(): string {
return base64_encode($this->getPlatform() . ':' . $this->getId());
}
public static function unserialize(string $data): self {
$parts = explode(':', base64_decode($data));
return new self($parts[0], $parts[1]);
}
}
Platform-Specific Logic
Extend VideoPlatformInterface to add metadata (e.g., thumbnails):
class YouTubePlatform implements VideoPlatformInterface {
public function getThumbnail(string $id): string {
return "https://img.youtube.com/vi/{$id}/maxresdefault.jpg";
}
}
Laravel Service Provider Bind the package’s services to Laravel’s container:
public function register() {
$this->app->singleton(\Becklyn\VideoPlatforms\Parser\VideoUrlParser::class, function ($app) {
return new \Becklyn\VideoPlatforms\Parser\VideoUrlParser(
$app->make(\Becklyn\VideoPlatforms\Parser\VideoPlatformInterface::class)
);
});
}
Video objects if parsing the same URL repeatedly:
$cacheKey = 'video:' . md5($url);
$video = Cache::remember($cacheKey, now()->addHours(1), fn() => $parser->parse($url));
platform@id) in forms/databases to skip parsing on submission.How can I help you explore Laravel packages today?