PHP code example of joshcirre / duo

1. Go to this page and download the library: Download joshcirre/duo library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

joshcirre / duo example snippets


use JoshCirre\Duo\Syncable;

class Todo extends Model
{
    use Syncable;

    protected $fillable = ['title', 'description', 'completed'];
}

// Option 1: Using $fillable (explicit allow list)
protected $fillable = ['title', 'description', 'completed'];

// Option 2: Using $guarded (explicit deny list)
protected $guarded = ['id']; // Everything except 'id' is fillable

class Todo extends Model
{
    use Syncable;

    // ✅ CORRECT: user_id is NOT in $fillable (security)
    protected $fillable = ['title', 'description', 'completed'];

    // ✅ Add user relationship - Duo auto-assigns user_id during sync
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}


use Livewire\Volt\Component;
use App\Models\Todo;
use JoshCirre\Duo\WithDuo;

new class extends Component {
    use WithDuo;  // ✨ This is all you need!

    public string $newTodoTitle = '';

    public function addTodo()
    {
        Todo::create(['title' => $this->newTodoTitle]);
        $this->reset('newTodoTitle');
    }

    public function toggleTodo($id)
    {
        $todo = Todo::findOrFail($id);
        $todo->update(['completed' => !$todo->completed]);
    }

    public function deleteTodo($id)
    {
        Todo::findOrFail($id)->delete();
    }

    public function with()
    {
        return ['todos' => Todo::latest()->get()];
    }
}; 



namespace App\Livewire;

use Livewire\Component;
use App\Models\Todo;
use JoshCirre\Duo\WithDuo;

class TodoList extends Component
{
    use WithDuo;  // ✨ Add this trait

    public string $newTodoTitle = '';

    public function addTodo()
    {
        Todo::create(['title' => $this->newTodoTitle]);
        $this->reset('newTodoTitle');
    }

    public function render()
    {
        return view('livewire.todo-list', [
            'todos' => Todo::latest()->get(),
        ]);
    }
}

'sync_status' => [
    'show_delay' => env('DUO_SYNC_STATUS_DELAY', 1000),
    'show_success' => env('DUO_SYNC_STATUS_SUCCESS', false),
    'success_duration' => env('DUO_SYNC_STATUS_SUCCESS_DURATION', 2000),
],

return [
    'database_name' => env('DUO_DATABASE_NAME', 'duo_cache'),
    'sync_strategy' => env('DUO_SYNC_STRATEGY', 'write-behind'),
    'sync_interval' => env('DUO_SYNC_INTERVAL', 5000), // milliseconds
    'max_retry_attempts' => env('DUO_MAX_RETRY_ATTEMPTS', 3),
    'cache_ttl' => env('DUO_CACHE_TTL', null), // seconds, null = no expiration
    'debug' => env('DUO_DEBUG', false),
    'auto_discover' => env('DUO_AUTO_DISCOVER', true),
];


use Livewire\Volt\Component;
use JoshCirre\Duo\{WithDuo, DuoConfig};

new class extends Component {
    use WithDuo;

    // Type-safe configuration with IDE autocomplete!
    protected function duoConfig(): DuoConfig
    {
        return DuoConfig::make(
            syncInterval: 3000,
            timestampRefreshInterval: 5000,
            debug: true
        );
    }

    // ... rest of your component
}



namespace App\Livewire;

use Livewire\Component;
use JoshCirre\Duo\{WithDuo, DuoConfig};

class TodoList extends Component
{
    use WithDuo;

    protected function duoConfig(): DuoConfig
    {
        return DuoConfig::make(
            timestampRefreshInterval: 30000,
            maxRetryAttempts: 5
        );
    }

    // ... rest of your component
}

protected function duoConfig(): DuoConfig
{
    return DuoConfig::make(
        syncInterval: 3000,              // Sync every 3 seconds
        timestampRefreshInterval: 5000,  // Refresh timestamps every 5 seconds
        maxRetryAttempts: 5,             // Retry failed syncs 5 times
        debug: true                      // Enable debug logging
    );
}

use Livewire\Attributes\On;

#[On('duo-synced')]
public function handleSyncComplete()
{
    // Refresh data, show notification, etc.
    $this->dispatch('notify', message: 'Changes synced!');
}

   use JoshCirre\Duo\WithDuo;

   class MyComponent extends Component {
       use WithDuo;  // Make sure this is here
   }
   
bash
# Terminal 1: Vite
npm run dev

# Terminal 2: Laravel
php artisan serve
bash
# Publish configuration file
php artisan vendor:publish --tag=duo-config

# Publish Blade components (sync-status, debug panel)
php artisan vendor:publish --tag=duo-views

# Publish JavaScript assets (advanced users only)
php artisan vendor:publish --tag=duo-assets

# Publish everything
php artisan vendor:publish --provider="JoshCirre\Duo\DuoServiceProvider"
javascript
duo({
    // Manifest path (default: 'resources/js/duo/manifest.json')
    manifestPath: 'resources/js/duo/manifest.json',

    // Watch for file changes (default: true)
    watch: true,

    // Auto-generate manifest (default: true)
    autoGenerate: true,

    // Files to watch for changes (default: ['app/Models/**/*.php'])
    patterns: [
        'app/Models/**/*.php',
        'resources/views/livewire/**/*.php',  // Include Volt components
        'app/Livewire/**/*.php',              // Include class-based components
    ],

    // Entry file for auto-injection (default: 'resources/js/app.js')
    entry: 'resources/js/app.js',

    // Auto-inject initialization code (default: true)
    autoInject: true,

    // Custom artisan command (default: 'php artisan duo:generate')
    command: 'php artisan duo:generate',
})
bash
php artisan vendor:publish --tag=duo-config
bash
php artisan vendor:publish --tag=duo-views
bash
resources/views/vendor/duo/components/sync-status.blade.php
bash
resources/views/vendor/duo/components/debug.blade.php

Component duoConfig() > Global config/duo.php > Hardcoded defaults
javascript
duo({
    patterns: [
        'app/Models/**/*.php',           // Watch models
        'resources/views/livewire/**/*.php', // Watch Volt components
        'app/Livewire/**/*.php',         // Watch class-based components
    ],
    watch: true,    // Regenerate on file changes (dev only)
    autoGenerate: true,  // Auto-run duo:generate
})
bash
php artisan duo:discover
bash
php artisan duo:generate
bash
# Generate with custom path
php artisan duo:generate --path=resources/js/duo

# Force regeneration
php artisan duo:generate --force
bash
   php artisan optimize:clear
   composer dump-autoload
   
bash
   php artisan duo:generate
   npm run build