1. Go to this page and download the library: Download pushinbr/pam-native-nitro 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/ */
pushinbr / pam-native-nitro example snippets
use Pam\Nitro\Attributes\Field;
use Pam\Nitro\Attributes\Children;
use Pam\Nitro\Attributes\PrimaryKey;
use Pam\Nitro\Model;
use Pam\Nitro\Relations\ChildrenRelation;
enum MessageType: int
{
case Text = 1;
case Image = 2;
}
final class Message extends Model
{
#[PrimaryKey]
#[Field]
public string $id;
#[Field(indexed: true)]
public string $chatId;
#[Field]
public string $body;
#[Field]
public MessageType $type;
#[Field(indexed: true)]
public int $createdAt;
public static function table(): string
{
return 'messages';
}
}
final class Chat extends Model
{
#[PrimaryKey]
#[Field]
public string $id;
#[Children(Message::class, foreignKey: 'chat_id')]
public ChildrenRelation $messages;
public static function table(): string
{
return 'chats';
}
}
$chat->messages->get(function (array $messages): void {
// Only this chat's rows cross the native boundary.
});
use Pam\Nitro\Batch;
use Pam\Nitro\Nitro;
Nitro::boot('zechat.db');
Nitro::prepare([Message::class], function () use ($chatId): void {
Message::query()
->where('chat_id', $chatId)
->latest()
->limit(20)
->get(function (array $messages): void {
$this->messages = array_reverse($messages);
});
});
// Many heterogeneous writes: one native call, one transaction.
Nitro::batch(function (Batch $batch) use ($chat, $messages, $draft): void {
$batch->save($chat)
->saveMany($messages)
->delete($draft)
->execute('UPDATE "chats" SET "unread" = 0 WHERE "id" = ?', [$chat->id]);
}, function (): void {
// Committed atomically.
});
// Several screens' worth of data: one native call, one result.
Nitro::fetch([
'chats' => Chat::query()->limit(50),
'messages' => Message::query()->where('chat_id', $chatId)->latest()->limit(30),
], function (array $results): void {
[$this->chats, $this->messages] = [$results['chats'], $results['messages']];
});
Nitro::saveMany($messages, function (): void {
// Thousands of upserts, one bridge call, one prepared statement,
// one native transaction.
});
Nitro::replaceMany(
Message::class,
$freshMessages,
['chat_id' => $chatId],
function (): void {
// The old chat snapshot and every new upsert commit atomically,
// even when the snapshot is larger than one bridge payload.
},
function (string $error): void {
// Native failures arrive here; nothing is thrown.
},
);
// Failures of calls made without a $failure callback.
Nitro::onFailure(fn (string $error) => error_log($error));
$message->delete();
Nitro::deleteWhere(
Message::class,
['chat_id' => $chatId, 'pending' => false],
);
use Pam\Nitro\Sync\MutationOperation;
use Pam\Nitro\Sync\SyncQueue;
enum SyncEntityKind: int
{
case Message = 1;
}
SyncQueue::enqueue(
SyncEntityKind::Message,
$message->id,
MutationOperation::Upsert,
$message->attributes(),
idempotencyKey: $clientMutationId,
);
#[Field]
public string $preview = '';
use Pam\Nitro\{Model, Nitro};
final class NitroStore
{
public const array MODELS = [ChatRecord::class, MessageRecord::class, ChatDraftRecord::class /* … */];
private static bool $ready = false;
private static bool $booting = false;
/** @var list<Closure(): int> */
private static array $pending = [];
public static function ready(Closure $operation): int
{
if (self::$ready) {
return $operation();
}
self::$pending[] = $operation;
if (!self::$booting) {
self::$booting = true;
// The offline cache is best effort: failures are logged, the server stays the source of truth.
Nitro::onFailure(static fn (string $message) => error_log('Nitro failure: '.$message));
Nitro::boot('zechat-nitro.db');
Nitro::prepare(self::MODELS, static function (): void {
self::$ready = true;
foreach (array_splice(self::$pending, 0) as $operation) {
$operation();
}
});
}
return 0;
}
}
// Inbox refresh: the user's chat list is replaced atomically (no stale rows, no empty window).
NitroStore::ready(fn () => Nitro::replaceMany(ChatRecord::class, $records, ['user_id' => $userId]));
// Opening a conversation: four side tables in ONE native call.
NitroStore::ready(fn () => Nitro::fetch([
'draft' => ChatDraftRecord::query()->where('user_id', $userId)->where('chat_id', $chatId)->limit(1),
'topics' => ChatTopicRecord::query()->where('user_id', $userId)->where('chat_id', $chatId)->orderBy('position')->limit(200),
'participants' => ChatParticipantRecord::query()->where('user_id', $userId)->where('chat_id', $chatId)->orderBy('position')->limit(1000),
], function (array $results): void {
$this->draft = $results['draft'][0] ?? null;
$this->topics = $results['topics'];
$this->participants = $results['participants'];
}));
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.