1. Go to this page and download the library: Download roddy/stateforge 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/ */
namespace App\Http\Controllers;
use Roddy\StateForge\Facades\StateForge;
use App\Stores\CounterStore;
class CounterController extends Controller
{
public function show()
{
$counter = StateForge::get(CounterStore::class); // or useStore(CounterStore::class)
return response()->json([
'count' => $counter->count,
'info' => $counter->getInfo()
]);
}
public function increment()
{
$counter = StateForge::get(CounterStore::class); // or useStore(CounterStore::class)
$counter->increment();
// onUpdate() is automatically called with logging!
return response()->json([
'success' => true,
'new_count' => $counter->count
]);
}
}
// routes/web.php or routes/api.php
Route::get('/counter', [CounterController::class, 'show']);
Route::post('/counter/increment', [CounterController::class, 'increment']);
class YourStore extends BaseStore
{
// 1. Define persistence type (file, cache, session, none)
protected string $persistenceType = 'file';
// 2. Initialize your state and methods
protected function initializeState(): array { /* ... */ }
// 3. Add custom middlewares
protected function middlewares(): array { /* ... */ }
// 4. Handle state changes automatically
protected function onUpdate(array $previousState, array $newState): void { /* ... */ }
}
class UserStore extends BaseStore
{
protected string $persistenceType = 'file';
protected function initializeState(): array
{
return [
'user' => null,
'is_logged_in' => false,
// ... methods
];
}
protected function middlewares(): array
{
return [
// Custom middleware that runs on every state change
function(callable $updater, array $state) {
// Called before state update
Log::debug('Middleware: Before update');
$newState = $updater($state);
Log::debug('Middleware: After update');
return $newState;
}
];
}
protected function onUpdate(array $previousState, array $newState): void
{
// Automatic handling after every state change
if ($previousState['is_logged_in'] !== $newState['is_logged_in']) {
event(new UserLoginStatusChanged(
$newState['is_logged_in'],
$newState['user']
));
}
}
}
use Roddy\StateForge\Facades\StateForge;
use App\Stores\CounterStore;
// Get or create store (auto-discovered)
$store = StateForge::get(CounterStore::class);
// Create store with custom configuration
$store = StateForge::create(CounterStore::class, [
'persistence' => 'cache',
'cache_ttl' => 3600
]);
// Store management
StateForge::all(); // Get all stores
StateForge::exists(CounterStore::class); // Check if store exists
StateForge::reset(CounterStore::class); // Reset specific store
StateForge::reset(); // Reset all stores
StateForge::getStoreInfo(); // Get store information
StateForge::getClientId(); // Get client identifier
// Change persistence at runtime
StateForge::setPersistence(CounterStore::class, 'file');
$counter = StateForge::get(CounterStore::class); // or useStore(CounterStore::class)
// Access state properties
echo $counter->count;
echo $counter->created_at;
// Call store methods
$counter->increment(5);
$counter->decrement(2);
$counter->resetState();
// Get state
$state = $counter->getState();
// Hooks
$counter->before('method', $callback);
$counter->after('method', $callback);
// Events
$counter->on('event', $listener);
$counter->off('event', $listener);
// Lifecycle info
$persistence = $counter->getPersistenceType(); // 'file', 'cache', 'session', 'none'
$hooks = $counter->getHookInfo(); // Get hook information
$listeners = $counter->getEventListeners(); // Get event listeners
namespace App\Livewire;
use Livewire\Component;
use Roddy\StateForge\Facades\StateForge;
use App\Stores\CounterStore;
class CounterComponent extends Component
{
public $count = 0;
protected $counter;
public function mount()
{
$this->counter = StateForge::get(CounterStore::class); // or useStore(CounterStore::class)
$this->count = $this->counter->count;
// onUpdate() will handle automatic syncing
}
public function increment()
{
$this->counter->increment();
$this->count = $this->counter->count;
}
public function render()
{
return view('livewire.counter-component');
}
}
namespace App\StateForge\Middlewares;
use Roddy\StateForge\Contracts\Middleware;
class ValidationMiddleware implements Middleware
{
public function __invoke(callable $updater, array $state): array
{
$newState = $updater($state);
// Add validation logic
if (isset($newState['count']) && $newState['count'] < 0) {
throw new \InvalidArgumentException('Count cannot be negative');
}
return $newState;
}
}
class AnalyticsMiddleware implements Middleware
{
public function __invoke(callable $updater, array $state): array
{
$newState = $updater($state);
// Track state changes
if (app()->environment('production')) {
\App\Jobs\TrackStateChange::dispatch(
get_class($this),
array_keys(array_diff_assoc($newState, $state))
);
}
return $newState;
}
}
// Usage in store
protected function middlewares(): array
{
return [
\App\StateForge\Middlewares\ValidationMiddleware::class,
\App\StateForge\Middlewares\AnalyticsMiddleware::class,
];
}
// ❌ Wrong - might create new instance
$store = new CounterStore();
// ✅ Correct - use facade
$store = StateForge::get(CounterStore::class);
bash
# Clean up stores for clients not seen in 30 days (default)
php artisan stateforge:cleanup
# Clean up stores for clients not seen in 60 days
php artisan stateforge:cleanup --days=60
# Schedule cleanup (in app/Console/Kernel.php)
$schedule->command('stateforge:cleanup --days=30')->daily();
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.