draliragab/socialize

Unified Laravel social media publishing for Facebook, Instagram, X, and LinkedIn.

Maintainers

Package info

github.com/DrAliRagab/Socialize

pkg:composer/draliragab/socialize

Statistics

Installs: 302

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v2.2.0 2026-02-27 12:40 UTC

README

Unified social publishing for Laravel.

Socialize gives you one fluent API to share content to Facebook, Instagram, X, and LinkedIn, while still letting you use provider-specific features when needed.

Why Socialize

  • One shared fluent API across providers
  • Provider-specific chaining for platform-only features
  • URL and local file media support with automatic normalization
  • Named profile support per provider (multi-account ready)
  • Strict typing, custom exceptions, and high test coverage
  • Built for modern Laravel (11/12) and PHP 8.4+

Supported Providers

  • Facebook (facebook)
  • Instagram (instagram)
  • X / Twitter (twitter or x)
  • LinkedIn (linkedin)

Requirements

  • PHP ^8.4
  • Laravel ^11.0 | ^12.0

Installation

composer require draliragab/socialize

Publish configuration:

php artisan vendor:publish --tag="socialize-config"

Quick Start

use DrAliRagab\Socialize\Facades\Socialize;

$result = Socialize::provider('facebook')
    ->message('New release is live')
    ->link('https://example.com/release')
    ->share();

$id = $result->id();
$url = $result->url();

Comment on an existing post (all providers):

$comment = Socialize::provider('facebook')
    ->commentOn($id, 'Thanks everyone!');

Share then immediately add a comment:

$comment = Socialize::provider('linkedin')
    ->message('New release is live')
    ->link('https://example.com/release')
    ->shareAndComment('Happy to answer questions below.');

Switch provider with the same shared methods:

foreach (['facebook', 'instagram', 'twitter', 'linkedin'] as $provider) {
    Socialize::provider($provider)
        ->message('Hello from Socialize')
        ->link('https://example.com')
        ->share();
}

Fluent API

Shared methods

  • message(?string $message)
  • link(?string $url, ?string $articleTitle = null)
  • imageUrl(?string $url)
  • videoUrl(?string $url)
  • media(string $source, ?string $mediaType = null)
  • mediaId(string $id)
  • mediaIds(array $ids)
  • metadata(array $metadata)
  • option(string $key, mixed $value)
  • share(): ShareResult
  • commentOn(string $postId, string $message): CommentResult
  • shareAndComment(string $message): CommentResult
  • delete(string $postId): bool

Provider-specific methods

Facebook:

  • published(bool $published = true)
  • scheduledAt(string|int|DateTimeInterface $dateTime)
  • targeting(array $targeting)

Instagram:

  • carousel(array $imageUrls)
  • altText(string $text)
  • reel()

X / Twitter:

  • replyTo(string $postId)
  • quote(string $postId)
  • poll(array $options, int $durationMinutes)

LinkedIn:

  • visibility(string $visibility)
  • distribution(string $distribution)
  • mediaUrn(string $mediaUrn)
  • poll(array $options, int $durationMinutes)

Poll notes:

  • poll() is supported for twitter and linkedin.
  • For LinkedIn, message() is used as the poll question (max 140 chars).
  • LinkedIn accepts only these poll durations (minutes): 1440, 4320, 10080, 20160.

Media Handling (URL + Local File)

Socialize keeps the API fluent and provider-agnostic:

  • If a provider expects a URL (for example Facebook/Instagram) and you pass a local file, Socialize stores a temporary public file URL, uses it, then cleans it up.
  • If a provider expects uploaded media IDs/URNs (for example X/LinkedIn) and you pass a URL, Socialize downloads and uploads it automatically.

Examples:

// Local image -> temporary URL flow for URL-based providers
Socialize::provider('facebook')
    ->media('/absolute/path/banner.jpg', 'image')
    ->message('Local image test')
    ->share();

// URL image -> provider upload flow for upload-based providers
Socialize::provider('linkedin')
    ->media('https://picsum.photos/1200/800', 'image')
    ->message('URL image test')
    ->share();

LinkedIn Link Title (Optional)

LinkedIn can require richer link content. You can pass an optional title using the second link() argument:

Socialize::provider('linkedin')
    ->message('Product update')
    ->link('https://example.com/post', 'Product update details')
    ->share();

This argument is optional and safe to keep in cross-provider fluent code.

Using Profiles

Socialize::provider('facebook', 'marketing')
    ->message('Campaign announcement')
    ->share();

Error Handling

use DrAliRagab\Socialize\Exceptions\ApiException;

try {
    Socialize::provider('twitter')->message('Hello X')->share();
} catch (ApiException $e) {
    $provider = $e->provider()->value;
    $status = $e->status();
    $response = $e->responseBody();
}

Model Trait

Use DrAliRagab\Socialize\Concerns\CanShareSocially to share directly from Eloquent models:

use DrAliRagab\Socialize\Concerns\CanShareSocially;

class Post extends Model
{
    use CanShareSocially;
}

$post->shareToFacebook();
$post->shareTo('linkedin');

The trait maps model fields using socialize.model_columns.

Configuration

All settings live in config/socialize.php.

General environment variables

  • SOCIALIZE_DEFAULT_PROFILE (optional, default: default)
  • SOCIALIZE_HTTP_TIMEOUT (optional, default: 120)
  • SOCIALIZE_HTTP_CONNECT_TIMEOUT (optional, default: 30)
  • SOCIALIZE_HTTP_RETRIES (optional, default: 1)
  • SOCIALIZE_HTTP_RETRY_SLEEP_MS (optional, default: 150)
  • SOCIALIZE_TEMP_MEDIA_DISK (optional, default: public)
  • SOCIALIZE_TEMP_MEDIA_DIRECTORY (optional, default: socialize-temp)
  • SOCIALIZE_TEMP_MEDIA_VISIBILITY (optional, default: public)

Facebook

  • SOCIALIZE_FACEBOOK_PAGE_ID (required)
  • SOCIALIZE_FACEBOOK_ACCESS_TOKEN (required)
  • SOCIALIZE_FACEBOOK_GRAPH_VERSION (optional, default: v25.0)
  • SOCIALIZE_FACEBOOK_BASE_URL (optional)

Instagram

  • SOCIALIZE_INSTAGRAM_IG_ID (required)
  • SOCIALIZE_INSTAGRAM_ACCESS_TOKEN (required)
  • SOCIALIZE_INSTAGRAM_GRAPH_VERSION (optional, default: v25.0)
  • SOCIALIZE_INSTAGRAM_BASE_URL (optional)
  • SOCIALIZE_INSTAGRAM_PUBLISH_RETRY_ATTEMPTS (optional, default: 20)
  • SOCIALIZE_INSTAGRAM_PUBLISH_RETRY_SLEEP_SECONDS (optional, default: 3)

X / Twitter

  • SOCIALIZE_TWITTER_BEARER_TOKEN (required for runtime publishing)
  • SOCIALIZE_TWITTER_BASE_URL (optional)
  • SOCIALIZE_TWITTER_MEDIA_PROCESSING_POLL_ATTEMPTS (optional, default: 15)

Token requirements:

  • Use OAuth 2.0 User Context token, not app-only bearer token
  • Required scopes: tweet.read, tweet.write, users.read, media.write
  • Add offline.access when refresh tokens are needed

LinkedIn

  • SOCIALIZE_LINKEDIN_AUTHOR (required, URN format like urn:li:person:...)
  • SOCIALIZE_LINKEDIN_ACCESS_TOKEN (required)
  • SOCIALIZE_LINKEDIN_VERSION (optional, default: 202602, format: YYYYMM)
  • SOCIALIZE_LINKEDIN_BASE_URL (optional)

Local End-to-End Tester

You can test real provider calls without creating a full Laravel app.

  1. Copy .testing.env.example to .testing.env
  2. Fill credentials
  3. Run:
php bin/local-tester.php --help

Examples:

php bin/local-tester.php share --provider=facebook --message="Hello" --link="https://example.com"
php bin/local-tester.php comment --provider=facebook --post-id="123_456" --comment="Nice post!"
php bin/local-tester.php share-and-comment --provider=linkedin --message="Launch" --link="https://example.com" --comment="Any feedback?"
php bin/local-tester.php share --provider=instagram --video-url="https://cdn.example.com/reel.mp4" --reel
php bin/local-tester.php share --provider=twitter --message="Launch day" --media-source="/absolute/path/image.jpg" --media-type=image
php bin/local-tester.php share --provider=linkedin --message="Professional update" --link="https://example.com" --link-title="Read more"
php bin/local-tester.php delete --provider=linkedin --post-id="urn:li:share:123"

Development Quality Commands

composer analyse
composer test
composer test-coverage
composer format
composer rector
composer check

License

MIT