1. Go to this page and download the library: Download webrium/foxql 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/ */
DB::addConnection([...], 'main');
DB::addConnection([...], 'analytics');
DB::use('analytics'); // subsequent calls use this connection
DB::use('main'); // switch back
DB::connection('analytics'); // get the raw Connection instance
// Get all rows — returns a Collection of stdClass objects
$users = DB::table('users')->get();
foreach ($users as $user) {
echo $user->name;
}
// Get the first matching row — returns stdClass or false if nothing matches
$user = DB::table('users')->where('email', '[email protected]')->first();
if ($user) {
echo $user->name;
}
// Get a single column value from the first matching row
$email = DB::table('users')->where('id', 5)->value('email');
// Get a flat array of values from a single column
$names = DB::table('users')->pluck('name');
// → ['Alice', 'Bob', 'Carol']
// Get an array keyed by another column — useful for dropdowns
$nameById = DB::table('users')->pluck('name', 'id');
// → [1 => 'Alice', 2 => 'Bob']
// Find a row by its primary key
$user = DB::table('users')->find(5);
// Select only certain columns
$users = DB::table('users')->select('id', 'name', 'email')->get();
// Select a raw expression
$stats = DB::table('orders')
->selectRaw('COUNT(*) as total, SUM(amount) as revenue')
->where('status', 'paid')
->first();
// Remove duplicate rows
$countries = DB::table('users')->distinct()->pluck('country');
// Process 200 rows at a time
DB::table('users')->orderBy('id')->chunk(200, function ($users) {
foreach ($users as $user) {
// process each user
}
// Return false from the callback to stop chunking early
});
// Simpler iteration with each()
DB::table('users')->orderBy('id')->each(function ($user) {
// called once per row
});
->where('active', 1) // WHERE active = 1
->where('age', '>', 18) // WHERE age > 18
->where('role', '!=', 'banned') // WHERE role != 'banned'
->orWhere('role', 'admin') // OR role = 'admin'
->whereNot('status', 'deleted') // WHERE status != 'deleted'
->whereNull('deleted_at') // only rows where deleted_at IS NULL
->whereNotNull('verified_at') // only rows where verified_at is set
->whereRaw('YEAR(created_at) = ? AND MONTH(created_at) = ?', [2024, 3])
->whereDate('created_at', '=', '2024-01-15') // full date match
->whereYear('created_at', '=', 2024)
->whereMonth('created_at', '=', 1)
->whereDay('created_at', '=', 15)
->whereTime('created_at', '>', '08:00:00')
->whereColumn('updated_at', '>', 'created_at')
// WHERE (role = 'admin' OR role = 'mod') AND active = 1
DB::table('users')
->where(function ($q) {
$q->where('role', 'admin')->orWhere('role', 'mod');
})
->where('active', 1)
->get();
// WHERE EXISTS (SELECT 1 FROM orders WHERE orders.user_id = users.id)
->whereExists(function ($q) {
$q->table('orders')->whereColumn('user_id', 'users.id');
})
->is('active', 1) // same as where('active', 1)
->true('active') // same as where('active', 1)
->false('active') // same as where('active', 0)
->null('deleted_at') // same as whereNull('deleted_at')
->notNull('email') // same as whereNotNull('email')
->in('id', [1,2,3]) // same as whereIn('id', [...])
->notIn('id', [4,5]) // same as whereNotIn('id', [...])
->like('name', '%ali%') // WHERE name LIKE '%ali%'
->and('age', '>', 18) // same as where()
->or('role', 'admin') // same as orWhere()
// INNER JOIN — only rows that have a match in both tables
DB::table('users')
->join('orders', 'orders.user_id', '=', 'users.id')
->select('users.name', 'orders.total', 'orders.status')
->get();
// LEFT JOIN — all users, even those with no orders
DB::table('users')
->leftJoin('orders', 'orders.user_id', '=', 'users.id')
->select('users.name', 'orders.total')
->get();
->rightJoin('table', 'a', '=', 'b')
->crossJoin('tags')
// Join against a subquery
->joinSub($subQuery, 'alias', 'alias.user_id', '=', 'users.id')
// Sort results
->orderBy('name') // ASC by default
->orderBy('created_at', 'desc')
->orderByDesc('score') // shorthand for desc
->latest() // ORDER BY created_at DESC
->oldest() // ORDER BY created_at ASC
->inRandomOrder() // ORDER BY RAND() — useful for random picks
// Sort by multiple columns
->orderBy('role')->orderBy('name', 'desc')
// Group results and filter groups
->groupBy('country')
->having('total_users', '>', 100)
->havingRaw('COUNT(*) > 100')
// Limit the number of results
->limit(10)
->offset(20)
->take(10)->skip(20) // aliases — take and skip are identical to limit and offset
// Insert a single row
DB::table('users')->insert([
'name' => 'Ali',
'email' => '[email protected]',
]);
// Insert and get the auto-increment ID back
$id = DB::table('users')->insertGetId([
'name' => 'Ali',
'email' => '[email protected]',
]);
// Insert multiple rows in one query
DB::table('users')->insertBatch([
['name' => 'Ali', 'email' => '[email protected]'],
['name' => 'Sara', 'email' => '[email protected]'],
['name' => 'Reza', 'email' => '[email protected]'],
]);
// Update matching rows — returns the number of affected rows
$affected = DB::table('users')
->where('id', 1)
->update(['name' => 'New Name', 'updated_at' => date('Y-m-d H:i:s')]);
// Increment or decrement a numeric column
DB::table('users')->where('id', 1)->increment('login_count');
DB::table('users')->where('id', 1)->increment('score', 10);
DB::table('users')->where('id', 1)->decrement('credits', 5);
// You can also update other columns at the same time
DB::table('users')->where('id', 1)->increment('score', 10, [
'last_activity' => date('Y-m-d H:i:s'),
]);
// Update if found, insert if not
DB::table('settings')->updateOrInsert(
['key' => 'theme'], // lookup condition
['value' => 'dark'] // value to set
);
// Delete matching rows
DB::table('users')->where('id', $id)->delete();
// Delete with multiple conditions
DB::table('sessions')
->where('user_id', $userId)
->where('created_at', 'delete();
// Remove all rows from the table
DB::table('cache')->truncate();
// Use in an API response
return [
'meta' => [
'total' => $result->total,
'current_page' => $result->current_page,
'last_page' => $result->last_page,
],
'data' => $result->data->toArray(),
];
// Select — returns array of stdClass
$rows = DB::select('SELECT * FROM users WHERE active = ? AND age > ?', [1, 18]);
// Select a single row
$user = DB::selectOne('SELECT * FROM users WHERE id = ?', [$id]);
// Insert
DB::insert('INSERT INTO logs (level, message) VALUES (?, ?)', ['info', 'User logged in']);
// Insert and get the new ID
$id = DB::insertGetId('INSERT INTO users (name) VALUES (?)', ['Ali']);
// Update
$affected = DB::update('UPDATE users SET active = ? WHERE last_login < ?', [0, '2023-01-01']);
// Delete
$deleted = DB::delete('DELETE FROM logs WHERE created_at < ?', ['2023-01-01']);
// Any statement (DDL, etc.)
DB::statement('ALTER TABLE users ADD COLUMN bio TEXT NULL');
// Raw expression inside a query
$stats = DB::table('products')
->select(DB::raw('category_id, COUNT(*) as count, AVG(price) as avg_price'))
->groupBy('category_id')
->having(DB::raw('COUNT(*)'), '>', 5)
->get();
DB::beginTransaction();
try {
// ... your operations ...
DB::commit();
} catch (\Throwable $e) {
DB::rollBack();
throw $e;
}
DB::inTransaction(); // bool — check if currently inside a transaction
// See the SQL and bindings without executing
$sql = DB::table('users')->where('active', 1)->orderBy('name')->toSql();
$bindings = DB::table('users')->where('active', 1)->orderBy('name')->getBindings();
// Dump SQL and bindings to output, then continue execution
DB::table('users')->where('active', 1)->dump()->get();
// Dump SQL and bindings to output, then stop (useful during development)
DB::table('users')->where('active', 1)->dd();
use Foxdb\Eloquent\Model;
class User extends Model
{
// The database table. If not set, FoxDB auto-derives it:
// User → users, UserProfile → user_profiles (snake_case + plural s)
protected string $table = 'users';
// The primary key column. Defaults to 'id'.
protected string $primaryKey = 'id';
// Columns that may be set via create() or fill().
// Only columns listed here can be mass-assigned.
protected array $fillable = ['name', 'email', 'age', 'is_active'];
// Alternatively, use $guarded to blocklist instead of allowlist.
// An empty guarded array means everything is allowed.
// protected array $guarded = [];
// Columns excluded from toArray() and toJson() output.
// Use this for passwords, tokens, and other sensitive fields.
protected array $hidden = ['password', 'remember_token'];
// Set to false if the table does not have created_at / updated_at columns.
protected bool $timestamps = true;
// Automatically cast column values to PHP types on read.
protected array $casts = [
'is_active' => 'bool',
'age' => 'int',
'score' => 'float',
'settings' => 'array', // stored as JSON, returned as array
'born_at' => 'datetime', // returned as a DateTime object
];
// Use a specific named connection instead of the default.
protected ?string $connection = null;
}
// $fillable = ['name', 'email'] — 'role' is blocked
User::create(['name' => 'Ali', 'email' => '[email protected]', 'role' => 'admin']);
// role is silently ignored
// If you need to bypass the guard (e.g. in a seeder), use forceFill()
$user = new User();
$user->forceFill(['name' => 'Ali', 'role' => 'admin'])->save();
// create() fills, saves, and returns the new model
$user = User::create(['name' => 'Ali', 'email' => '[email protected]', 'age' => 25]);
echo $user->id; // the auto-increment ID from the database
echo $user->created_at; // set automatically
// Alternatively, use new + save()
$user = new User();
$user->name = 'Ali';
$user->email = '[email protected]';
$user->save();
// All rows — returns a Collection
$users = User::all();
// By primary key
$user = User::find(1); // returns User or null
$user = User::findOrFail(1); // returns User or throws ModelNotFoundException
// First matching row
$user = User::where('email', '[email protected]')->first();
$user = User::firstWhere('email', '[email protected]'); // shorthand
// You can chain any Builder method
$admins = User::where('role', 'admin')
->where('active', 1)
->orderBy('name')
->get();
// Aggregates
$count = User::where('active', 1)->count();
$avg = User::avg('score');
// Check existence
$exists = User::exists(['email' => '[email protected]']); // bool
// Change attributes and call save() — only the changed columns are written
$user = User::findOrFail(1);
$user->name = 'New Name';
$user->save();
// Mass update via query — affects all matching rows
User::where('active', 0)->update(['score' => 0]);
// Delete a single model instance
$user = User::findOrFail(1);
$user->delete();
// Delete all rows matching a condition
User::where('created_at', 'delete();
// fresh() returns a new instance fetched from the DB, leaving the original untouched
$fresh = $user->fresh();
// refresh() updates the current instance in place
$user->refresh();
$user = User::find(1); // loaded: name = 'Ali'
$user->isDirty(); // false — nothing has changed yet
$user->name = 'New Name';
$user->isDirty(); // true
$user->isDirty('name'); // true
$user->isDirty('email'); // false — email was not changed
$user->getDirty(); // ['name' => 'New Name']
$user->save(); // UPDATE users SET name = ? WHERE id = ?
// email is NOT
class User extends Model
{
protected array $casts = [
'is_active' => 'bool',
'age' => 'int',
'score' => 'float',
'settings' => 'array',
'born_at' => 'datetime',
];
}
$user = User::find(1);
$user->is_active; // true or false, not "1" or "0"
$user->age; // 25 (int), not "25" (string)
$user->settings; // ['theme' => 'dark', 'lang' => 'fa'] — decoded from JSON
$user->born_at; // DateTime object — can call ->format(), ->diff(), etc.
// Casts work in reverse on write — the array is JSON-encoded before saving
$user->settings = ['theme' => 'light'];
$user->save(); // stores '{"theme":"light"}' in the database
use Foxdb\Eloquent\Concerns\HasSoftDeletes;
class Post extends Model
{
use HasSoftDeletes;
}
$post = Post::find(1);
$post->delete(); // sets deleted_at — the row stays in the database
Post::find(1); // returns null — soft-deleted rows are excluded by default
Post::count(); // does NOT count soft-deleted rows
$post->trashed(); // true — check if this instance has been soft-deleted
// Include soft-deleted rows in a query
$all = Post::withTrashed()->get();
$all = Post::withTrashed()->find(1); // returns the soft-deleted post
// Query only the soft-deleted rows
$deleted = Post::onlyTrashed()->get();
// Restore a soft-deleted record
Post::withTrashed()->find(1)->restore(); // clears deleted_at
class BaseModel extends Model
{
use HasSoftDeletes;
}
class Post extends BaseModel
{
protected string $table = 'posts';
}
// The scope is applied correctly — Post inherits from BaseModel
Post::find(1); // still excludes soft-deleted rows
class User extends Model
{
public function posts(): HasMany
{
// hasMany(related model, foreign key on related table, local key)
return $this->hasMany(Post::class, 'user_id', 'id');
}
}
public function profile(): HasOne
{
return $this->hasOne(Profile::class, 'user_id', 'id');
}
class Post extends Model
{
public function author(): BelongsTo
{
// belongsTo(related model, foreign key on THIS table, owner key on related table)
return $this->belongsTo(User::class, 'user_id', 'id');
}
}
public function roles(): BelongsToMany
{
// belongsToMany(related, pivot table, FK for this model, FK for related model)
return $this->belongsToMany(Role::class, 'user_role', 'user_id', 'role_id');
}
public function comments(): HasManyThrough
{
return $this->hasManyThrough(
Comment::class, // the final model you want
Post::class, // the intermediate model
'user_id', // FK on posts pointing to users
'post_id', // FK on comments pointing to posts
'id', // local key on users
'id', // local key on posts
);
}
$user = User::find(1);
$posts = $user->posts; // runs a query, returns Collection
$posts = $user->posts; // uses the cached result — no second query
$author = $post->author; // User|null
$profile = $user->profile; // Profile|null
// Add a role to a user
$user->roles()->attach(3);
$user->roles()->attach([3, 5, 7]);
// Add with data on the pivot row
$user->roles()->attach(3, ['granted_at' => date('Y-m-d')]);
// Remove a role
$user->roles()->detach(3);
$user->roles()->detach(); // remove all
// Sync — attach the given IDs and detach everything else
$user->roles()->sync([3, 5]);
// Include pivot columns when loading the relation
$roles = $user->roles()->withPivot('granted_at', 'expires_at')->get();
echo $roles->first()->pivot->granted_at;
// Set the foreign key by passing the related model (does not save automatically)
$post->author()->associate($user);
$post->save();
// Clear the foreign key
$post->author()->dissociate();
$post->save();
// Without eager loading — runs 1 + N queries
$users = User::all();
foreach ($users as $user) {
echo $user->posts->count(); // query per user!
}
// With eager loading — runs exactly 2 queries
$users = User::with('posts')->get();
foreach ($users as $user) {
echo $user->posts->count(); // no query — already loaded
}
$data = User::with('posts')->get()->toArray();
// $data[0]['posts'] → array of post arrays
class User extends Model
{
// Scope to filter only active users
public function scopeActive(Builder $q): Builder
{
return $q->where('is_active', 1);
}
// Scope with a parameter
public function scopeRole(Builder $q, string $role): Builder
{
return $q->where('role', $role);
}
// Scope for recent records
public function scopeRecent(Builder $q, int $days = 7): Builder
{
return $q->where('created_at', '>=', date('Y-m-d', strtotime("-{$days} days")));
}
}
// Use the scope — drop the 'scope' prefix and call as static
User::active()->get();
User::role('admin')->get();
User::recent(30)->get();
// Scopes are fully chainable with each other and with other Builder methods
User::active()
->role('mod')
->recent()
->orderBy('name')
->paginate(20, $page);
$user = User::with('posts')->find(1);
$arr = $user->toArray(); // ['id' => 1, 'name' => 'Ali', 'posts' => [...], ...]
$json = $user->toJson(); // same data as a JSON string
$json = (string) $user; // identical to toJson()
json_encode($user); // also works — Model implements JsonSerializable
$users = User::with('posts')->get();
$arr = $users->toArray(); // array of arrays — correct
$json = json_encode($users); // correct
// Use in an API response
return ['ok' => true, 'users' => $users->toArray()];
$users = User::all(); // Collection
// Basic access
$users->count();
$users->isEmpty();
$users->isNotEmpty();
$users->first();
$users->first(fn($u) => $u->role === 'admin'); // first matching
$users->last();
$users->get(2); // item at index 2, null if missing
$users->contains('role', 'admin');
$users->contains(fn($u) => $u->age > 18);
// Iteration — works like a normal array
foreach ($users as $user) {
echo $user->name;
}
$users[0]; // ArrayAccess read
// Filtering and transformation
$active = $users->filter(fn($u) => $u->active);
$inactive = $users->reject(fn($u) => $u->active); // inverse of filter
$names = $users->map(fn($u) => (object)['name' => strtoupper($u->name)]);
$users->each(fn($u, $index) => processUser($u));
// Return false from the callback to stop early
// Sorting
$byName = $users->sortBy('name');
$byScore = $users->sortByDesc('score');
// Slicing
$first5 = $users->take(5);
$after10 = $users->skip(10);
$unique = $users->unique('email'); // first occurrence wins
$reversed = $users->reverse();
$merged = $users->merge($otherCollection);
// Split into chunks — returns an array of Collections
$chunks = $users->chunk(100);
// Extracting data
$names = $users->pluck('name'); // ['Ali', 'Sara', ...]
$nameById = $users->pluck('name', 'id'); // [1 => 'Ali', 2 => 'Sara']
$byId = $users->keyBy('id'); // plain array keyed by id
$grouped = $users->groupBy('role'); // plain array grouped by role value
// Aggregates — operate on a column across all items
$total = $users->sum('score');
$average = $users->avg('score');
$lowest = $users->min('score');
$highest = $users->max('score');
// Serialization
$arr = $users->toArray(); // array of arrays — uses Model::toArray() per item
$json = $users->toJson();
$json = json_encode($users); // identical
(string) $users; // pretty-printed JSON
Schema::table('users', function (Blueprint $table) {
// Add a new column (nullable so existing rows are not affected)
$table->integer('score')->nullable()->after('email')->change();
// Rename a column
$table->renameColumn('bio', 'about');
// Remove columns
$table->dropColumn('old_field');
$table->dropColumn(['field_a', 'field_b']);
// Remove indexes and constraints
$table->dropIndex('idx_name');
$table->dropUnique('idx_email');
$table->dropForeign('fk_category_id');
});
Schema::drop('users'); // drop the table (fails if it doesn't exist)
Schema::dropIfExists('users'); // safe version — no error if missing
Schema::rename('old_table', 'new_table');
Schema::hasTable('users'); // bool — check if table exists
Schema::hasColumn('users', 'email'); // bool — check if column exists
Schema::getColumnNames('users'); // array — all column names
use Foxdb\Migrations\Migration;
use Foxdb\Schema;
use Foxdb\Schema\Blueprint;
class CreateUsersTable extends Migration
{
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->boolean('is_active')->default(true);
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('users');
}
}
use Foxdb\Migrations\Migrator;
// Point the Migrator at the folder containing your migration files
$migrator = new Migrator('/path/to/migrations');
// Run all migrations that have not been run yet
$migrator->run();
// Run at most 3 pending migrations
$migrator->run(3);
// Roll back the last batch of migrations
$migrator->rollback();
// Roll back the last 2 batches
$migrator->rollback(2);
// Roll back everything — brings the database back to a blank state
$migrator->reset();
// Reset and then run everything — useful for refreshing a dev database
$migrator->refresh();
// Check what has and hasn't been run yet
$migrator->status(); // array of migration status
// Check if anything is pending
if ($migrator->hasPendingMigrations()) {
echo "Database is not up to date.";
}
// Enable logging before running your queries
DB::enableQueryLog();
$users = User::where('active', 1)->with('posts')->get();
$count = DB::table('orders')->where('status', 'paid')->count();
// Retrieve the log
$log = DB::getQueryLog(); // array of QueryLogEntry objects
foreach ($log as $entry) {
echo $entry->sql; // SELECT * FROM `users` WHERE `active` = ?
echo $entry->time; // execution time in milliseconds
var_dump($entry->bindings);
}
// Shortcuts
DB::getLastQuery(); // the most recent QueryLogEntry
DB::getQueryCount(); // total number of queries run
DB::getTotalQueryTime(); // sum of all execution times in ms
DB::getSlowQueries(50.0); // all queries that took more than 50ms
DB::disableQueryLog();
DB::flushQueryLog(); // clear the log without disabling it
DB::beforeQuery(function (string $sql, array $bindings) {
// Called just before each query is executed
$this->logger->debug('Running query', ['sql' => $sql]);
});
DB::afterQuery(function (string $sql, array $bindings, float $timeMs) {
// Called after each query completes
if ($timeMs > 100) {
$this->logger->warning('Slow query detected', ['sql' => $sql, 'time' => $timeMs]);
}
});
use Foxdb\Exceptions\QueryException;
use Foxdb\Exceptions\DatabaseException;
use Foxdb\Exceptions\ModelNotFoundException;
// findOrFail() throws ModelNotFoundException when no row matches
try {
$user = User::findOrFail(999);
} catch (ModelNotFoundException $e) {
// return a 404 response
}
// QueryException wraps any PDO error — gives you the SQL and bindings
try {
DB::table('users')->where('nonexistent_column', 1)->get();
} catch (QueryException $e) {
echo $e->getSql(); // the compiled SQL
echo $e->getErrorCode(); // the database error code
echo $e->getFormattedMessage(); // full formatted error string
var_dump($e->getParams()); // the bindings array
}
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.