DB

object

%DB

/phlo/resources/DB/DB.phlo
version 1.0
creator q-ai.nl
summary Database engine class
type abstract class
package database
frontend false
backend true
requires php-ext:pdo
tags database pdo sql
prop

%DB -> PDO

line 11
如果未为数据库操作定义PDO连接器,则此函数会触发错误。
error('No PDO connector defined')
prop

%DB -> fieldQuotes

line 12
检索指定数据库字段的字段引用,以便正确格式化SQL查询。
bt
method

%DB -> load (string $table, string $columns = '*', string $where = void, string $joins = void, string $group = void, string $limit = void, string $order = void, ...$args)

line 14
从指定的数据库表中加载数据,允许选择列、过滤条件、连接、分组、排序和限制结果的可选项。
$table = strpos($table, space) || strpos($table, dot) ? $table : "$this->fieldQuotes$table$this->fieldQuotes"
!$where && $args && $where = loop(array_keys($args), fn($column) => "$table.$column=?", ' AND ')
$joins && $joins = " $joins"
$where && $where = " WHERE $where"
$group && $group = " GROUP BY $group"
$order && $order = " ORDER BY $order"
$limit && $limit = " LIMIT $limit"
$query = "SELECT $columns FROM $table$joins$where$group$order$limit"
return $this->query($query, ...array_values($args))
method

%DB -> query ($query, ...$args)

line 26
使用PDO执行数据库查询,根据参数的存在直接或使用预处理语句。 如果启用调试,它还提供调试信息,包括查询类型和受影响的行数。
try {
	if (!$args) $stmt = $this->PDO->query($query)
	else {
		$stmt = $this->PDO->prepare($query)
		$stmt->execute($args)
	}
	if (debug){
		$match = regex('/\b(UPDATE|INSERT INTO|DELETE FROM|FROM)\b\s+([`"\[]?\w+[`"\]]?)/i', strtr($query, [$this->fieldQuotes => void]))
		$where = strtr(regex('/\bWHERE (\b.+)/is', $query)[1] ?? void, [' ORDER BY' => void])
		$match && debug("Q: $match[1] $match[2]".strtr(rtrim(" $where "), [dq => void])." (".$stmt->rowCount().")")
	}
}
catch (\PDOException $e){
	error('Database error'.colon.lf.$query.lf.lf.$e->getMessage())
}
return $stmt
method

%DB -> column (...$args)

line 45
使用提供的参数从数据库查询的结果集中获取单列数据。
$this->load(...$args)->fetchAll(\PDO::FETCH_COLUMN)
method

%DB -> item (...$args)

line 46
使用提供的参数从数据库中获取单列,如果未找到值,则返回null。
$this->load(...$args)->fetch(\PDO::FETCH_COLUMN) ?: null
method

%DB -> pair (...$args)

line 47
使用提供的参数从数据库中获取所有行作为键值对数组。
$this->load(...$args)->fetchAll(\PDO::FETCH_KEY_PAIR)
method

%DB -> group (...$args)

line 48
从数据库中获取所有记录,按指定的列或列进行分组,并将结果作为指定类的对象数组返回。
$this->load(...$args)->fetchAll(\PDO::FETCH_GROUP|\PDO::FETCH_CLASS, obj::class)
method

%DB -> records (...$args)

line 49
从数据库中以指定类的对象形式获取所有记录,使用提供的参数进行查询。
$this->load(...$args)->fetchAll(\PDO::FETCH_CLASS|\PDO::FETCH_UNIQUE, obj::class)
method

%DB -> rows (...$args)

line 50
使用提供的参数从数据库中获取所有行作为指定类的实例。
$this->load(...$args)->fetchAll(\PDO::FETCH_CLASS, obj::class)
method

%DB -> record (...$args)

line 51
从数据库中获取指定类的单个记录作为对象,如果未找到记录,则返回null。
$this->load(...$args)->fetchObject(obj::class) ?: null
method

%DB -> create (string $table, ...$data)

line 53
将新记录插入到指定的数据库表中,并提供数据,选项上可以忽略重复条目。
if ($ignore = $data['ignore'] ?? false) unset($data['ignore'])
$columns = $this->fieldQuotes.implode($this->fieldQuotes.comma.$this->fieldQuotes, array_keys($data)).$this->fieldQuotes
$values = implode(comma, array_fill(0, count($data), qm))
$query = "INSERT".($ignore ? ' IGNORE' : void)." INTO $table ($columns) VALUES ($values)"
$this->query($query, ...array_values(loop($data, fn($value) => is_a($value, obj::class) ? $value->id : $value)))
return $this->PDO->lastInsertId() ?: ($data['id'] ?? null)
method

%DB -> change (string $table, string $where, ...$data)

line 62
根据给定的条件和数据更新指定数据库表中的记录。
$whereCount = substr_count($where, qm)
$updates = isset($data['updates']) ? $data['updates'] : void
unset($data['updates'])
$updates .= (($wheres = array_slice(array_keys($data), $whereCount)) && $updates ? comma : void).loop($wheres, fn($key) => $key.'=?', comma)
$query = "UPDATE $table SET $updates WHERE $where"
$args = array_values([...array_slice($data, $whereCount), ...array_slice($data, 0, $whereCount)])
return $this->query($query, ...$args)->rowCount()
method

%DB -> delete (string $table, string $where, ...$args)

line 72
根据给定条件从指定表中删除行。它返回受影响的行数。
$this->query("DELETE FROM $table WHERE $where", ...$args)->rowCount()
method

%DB -> begin

line 73
使用PDO开始一个新的数据库事务。
$this->PDO->beginTransaction()
method

%DB -> commit

line 74
提交数据库中的当前事务,使事务期间所做的所有更改永久生效。
$this->PDO->commit()
method

%DB -> rollback

line 75
如果当前事务处于活动状态,则回滚该事务,撤销在事务期间所做的任何更改。
$this->PDO->inTransaction() && $this->PDO->rollBack()
method

%DB -> transaction ($callback)

line 77
通过开始事务、运行提供的回调并在成功时提交事务来执行数据库事务;否则,在发生错误时回滚事务。
$this->begin
try {
	$result = $callback()
	$this->commit
	return $result
} catch (\Throwable $e){
	$this->rollback
	throw $e
}
object

%JSONDB

/phlo/resources/DB/JSONDB.phlo
version 1.2
creator q-ai.nl
summary JSON file database driver. One JSONDB instance = one JSON file = one model table. No joins, no transactions, no schema introspection.
extends DB
package database
frontend false
backend true
requires @DB @JSON_result
tags json database file storage
static

JSONDB :: __handle

line 11
JSONDB::$__handle 是对用于访问由 $file 路径指定的 JSON 数据库的内部文件句柄的引用。
"JSONDB/$file"
method

%JSONDB -> __construct (private string $file)

line 12
构造函数初始化一个JSONDB实例,并确保指定文件的目录存在,如有必要则创建该目录。
$dir = dirname($this->file)
is_dir($dir) || mkdir($dir, 0755, true) || error("JSONDB: cannot create dir $dir")
prop

%JSONDB -> PDO

line 16
此函数触发错误,指示JSONDB驱动程序与PDO不兼容。
error('JSONDB driver does not use PDO')
prop

%JSONDB -> fieldQuotes

line 17
检索JSONDB资源中指定字段的引用。
''
prop

%JSONDB -> lastInsertedId

line 18
返回JSONDB中最后插入记录的ID。
null
method

%JSONDB -> objRead

line 20
读取一个 JSON 文件并将其内容作为关联数组返回。如果文件不存在或为空,则返回一个空数组。
file_exists($this->file) ? json_decode(file_get_contents($this->file), true) ?: [] : []
method

%JSONDB -> objWrite (array $data)

line 21
将提供的数组数据写入 JSON 文件,以美观的格式编码,同时确保不转义 Unicode 字符。
file_put_contents($this->file, json_encode(array_values($data), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), LOCK_EX)
method

%JSONDB -> objNextId (array $data)

line 22
通过查找给定数据数组中当前最大ID并加一,返回新对象的下一个可用ID,或者在数组为空时返回1。
$data ? (int)max(array_column($data, 'id')) + 1 : 1
method

%JSONDB -> objFilter (array $data, string $where = void, ...$args)

line 24
根据 'where' 子句中指定的条件过滤数据数组,仅返回匹配的行。
if (!$where) return $data
$filtered = []
foreach ($data AS $row){
	$match = true
	$parts = preg_split('/\s+AND\s+/i', $where)
	$argIndex = 0
	foreach ($parts AS $part){
		if (preg_match('/^[`"]?(\w+)[`"]?\s*=\s*\?$/', trim($part), $m)){
			$column = $m[1]
			$value = $args[$argIndex++] ?? null
			if (($row[$column] ?? null) != $value) $match = false
		}
		elseif (preg_match('/^[`"]?(\w+)[`"]?\s+IN\s*\((.+)\)$/i', trim($part), $m)){
			$column = $m[1]
			$ids = array_map(fn($v) => trim($v, "\"' "), explode(',', $m[2]))
			if (!in_array($row[$column] ?? null, $ids)) $match = false
		}
	}
	$match && $filtered[] = $row
}
return $filtered
method

%JSONDB -> objSelect (string $where = void, string $limit = void, string $order = void, ...$args)

line 48
根据指定条件从JSON数据库中筛选和检索对象,支持可选的排序和结果限制。
$data = $this->objFilter($this->objRead(), $where, ...array_values($args))
if ($order){
	$desc = str_contains($order, 'DESC')
	$col = trim(preg_replace('/\s+(ASC|DESC)/i', '', $order), '` ')
	usort($data, fn($a, $b) => $desc ? ($b[$col] ?? 0) <=> ($a[$col] ?? 0) : ($a[$col] ?? 0) <=> ($b[$col] ?? 0))
}
$limit && $data = array_slice($data, 0, (int)$limit)
return $data
method

%JSONDB -> create (string $table, ...$data)

line 59
在指定的JSON数据库表中创建一个新条目,如果未提供ID,则分配一个ID,并可选择根据ID忽略重复项。
if ($ignore = $data['ignore'] ?? false) unset($data['ignore'])
$all = $this->objRead()
$data['id'] ??= $this->objNextId($all)
foreach ($data AS $key => $value) is_a($value, 'obj') && $data[$key] = $value->id
if ($ignore){
	foreach ($all AS $row) if (($row['id'] ?? null) == $data['id']) return $data['id']
}
$all[] = $data
$this->objWrite($all)
$this->lastInsertedId = $data['id']
return $data['id']
method

%JSONDB -> change (string $table, string $where, ...$data)

line 73
更新符合给定条件的指定表中的行,用新数据替换,并返回更改的行数。
$all = $this->objRead()
$whereCount = substr_count($where, '?')
$whereArgs = array_slice(array_values($data), 0, $whereCount)
$updates = array_slice($data, $whereCount, null, true)
$changed = 0
foreach ($all AS &$row){
	if ($this->objFilter([$row], $where, ...$whereArgs)){
		foreach ($updates AS $key => $value) $row[$key] = $value
		$changed++
	}
}
unset($row)
$this->objWrite($all)
return $changed
method

%JSONDB -> delete (string $table, string $where, ...$args)

line 90
从指定的JSON数据库表中删除符合给定条件的记录。
$all = $this->objRead()
$matching = $this->objFilter($all, $where, ...$args)
$matchIds = array_column($matching, 'id')
$remaining = array_values(array_filter($all, fn($row) => !in_array($row['id'] ?? null, $matchIds)))
$this->objWrite($remaining)
return count($matching)
method

%JSONDB -> load (string $table, string $columns = '*', string $where = void, string $joins = void, string $group = void, string $limit = void, string $order = void, ...$args)

line 99
从指定的JSONDB表中加载数据,允许选择列、使用条件过滤、与其他表连接、分组、限制结果和排序的可选项。
!$where && $args && $where = loop(array_keys($args), fn($column) => "$column=?", ' AND ')
$data = $this->objSelect($where, $limit, $order, ...array_values($args))
return %JSON_result($data)
method

%JSONDB -> query ($query, ...$args)

line 104
对JSONDB执行查询,但不支持原始SQL查询。
error('JSONDB driver does not support raw SQL queries')
method

%JSONDB -> begin

line 106
在 JSONDB 中开始一个事务,允许原子性地执行多个操作。
null
method

%JSONDB -> commit

line 107
将当前事务提交到JSONDB,保存事务期间所做的所有更改。
null
method

%JSONDB -> rollback

line 108
撤销JSONDB中的最后一个事务,将数据库恢复到之前的状态。
null
object

%JSON_result

/phlo/resources/DB/JSON.result.phlo
version 1.0
creator q-ai.nl
summary Minimal PDOStatement-like wrapper for JSONDB result arrays
package database
frontend false
backend true
tags json database result
static

JSON_result :: __handle

line 9
此属性用于访问 JSON_result 对象的内部句柄。
null
prop

%JSON_result -> data

line 10
访问 `JSON_result` 对象的 `$data` 属性,该属性包含来自 JSON 响应的解析数据。
[]
method

%JSON_result -> __construct (array $data)

line 11
使用提供的数据数组初始化 JSON_result 对象。
$this->data = $data
method

%JSON_result -> fetchAll ($mode = 2)

line 13
根据指定模式从JSON资源中获取所有结果,允许不同格式,如单列、键值对或对象。
if ($mode === \PDO::FETCH_COLUMN) return loop($this->data, fn($row) => reset((array)$row))
if ($mode === \PDO::FETCH_KEY_PAIR){
	$out = []
	foreach ($this->data AS $row){
		$vals = array_values((array)$row)
		$out[$vals[0] ?? null] = $vals[1] ?? null
	}
	return $out
}
if (($mode & (\PDO::FETCH_CLASS | \PDO::FETCH_UNIQUE)) === (\PDO::FETCH_CLASS | \PDO::FETCH_UNIQUE)){
	$out = []
	foreach ($this->data AS $row){
		$o = new obj
		foreach ((array)$row AS $k => $v) $o->$k = $v
		$out[$row['id'] ?? count($out)] = $o
	}
	return $out
}
if (($mode & \PDO::FETCH_CLASS) === \PDO::FETCH_CLASS){
	$out = []
	foreach ($this->data AS $row){
		$o = new obj
		foreach ((array)$row AS $k => $v) $o->$k = $v
		$out[] = $o
	}
	return $out
}
return $this->data
method

%JSON_result -> fetchObject ($class = 'obj')

line 44
从JSON结果数据中获取指定类的单个对象,将对象的属性映射到数据第一行的值。
if (!$this->data) return null
$row = reset($this->data)
$o = new $class
foreach ((array)$row AS $k => $v) $o->$k = $v
return $o
method

%JSON_result -> fetch ($mode = 2)

line 52
从JSON数据中获取结果行,根据提供的模式返回整个行或特定列。
if (!$this->data) return null
$row = reset($this->data)
if ($mode === \PDO::FETCH_COLUMN) return reset((array)$row)
return $row
method

%JSON_result -> fetchColumn ($col = 0)

line 59
从 JSON 结果集中第一行中获取单列,返回指定列索引的值,如果未找到则返回 false。
if (!$this->data) return false
$row = reset($this->data)
$vals = array_values((array)$row)
return $vals[$col] ?? false
method

%JSON_result -> rowCount

line 66
返回 JSON 结果集中的行数。
count($this->data)
object

%migrate

/phlo/resources/DB/migrate.phlo
version 1.0
creator q-ai.nl
summary Database migration runner
package database
frontend false
backend true
requires @DB
tags database migrate migrations sql schema
static

migrate :: setup ($db = null)

line 10
通过创建一个 `migrations` 表来设置数据库(如果尚不存在),该表跟踪迁移记录。
$db ??= %MySQL
$db->query("CREATE TABLE IF NOT EXISTS `migrations` (`id` int unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `batch` int unsigned NOT NULL, `applied_at` int unsigned NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY (`name`))")
static

migrate :: applied ($db = null)

line 15
从MySQL数据库的'migrations'表中检索已应用迁移的名称,按ID升序排列。
$db ??= %MySQL
return $db->column(table: 'migrations', columns: 'name', order: 'id ASC')
static

migrate :: run (string $path, $db = null)

line 20
通过执行指定目录中的SQL文件来运行数据库迁移,并在'migrations'表中跟踪已应用的迁移。
$db ??= %MySQL
static::setup($db)
$applied = static::applied($db)
$files = glob($path.'/*.sql')
sort($files)
$batch = $applied ? ($db->item(table: 'migrations', columns: 'MAX(batch)') + 1) : 1
$count = 0
foreach ($files AS $file){
	$name = basename($file, '.sql')
	if (in_array($name, $applied)) continue
	$sql = file_get_contents($file)
	foreach (array_filter(array_map('trim', explode(';', $sql))) AS $statement) $db->query($statement)
	$db->create('migrations', name: $name, batch: $batch, applied_at: time())
	$count++
}
return $count
static

migrate :: rollback ($db = null)

line 39
通过从数据库中的'migrations'表中删除相应的条目来回滚最后一批迁移。
$db ??= %MySQL
$batch = $db->item(table: 'migrations', columns: 'MAX(batch)')
if (!$batch) return 0
$names = $db->query('SELECT name FROM migrations WHERE batch=?', $batch)->fetchAll(\PDO::FETCH_COLUMN)
$db->delete('migrations', 'batch=?', $batch)
return count($names)
object

%model

/phlo/resources/DB/model.phlo
version 1.1
creator q-ai.nl
summary Phlo ORM class with unified columns and schema
type abstract class
package database
frontend false
backend true
requires @DB @MySQL apcu? audit?
tags orm model database records schema
static

model :: DB

line 11
访问模型的数据库连接,如果未明确设置,则默认为 %MySQL。
%app->DB ?? %MySQL
static

model :: objRecords

line 12
访问模型的记录,作为对象数组。
[]
static

model :: objLoaded

line 13
指示对象是否已在模型中加载。
[]
static

model :: objCache

line 14
model::$objCache 属性保存模型对象的缓存,通过减少重复获取相同数据的需要来提高性能。
false
static

model :: objRecordLimit

line 15
设置模型可以检索的最大记录数。
10000
static

model :: objSoftDelete

line 16
model::$objSoftDelete 属性指示模型实例是否启用了软删除,如果未启用,则返回 false。
false
static

model :: objAudit

line 17
`model::$objAudit` 属性用于访问与模型相关联的审计对象,从而允许跟踪更改和修改。
false
static

model :: objValidate

line 18
model::$objValidate 属性指示对象验证是否启用或禁用,如果验证未激活,则返回 false。
false
static

model :: objLastErrors

line 19
访问模型实例记录的最后错误,返回错误消息的数组。
[]
static

model :: idColumn

line 20
model::$idColumn 属性指定模型中使用的标识符列的名称,默认为 'id'。
'id'
static

model :: idType

line 21
将模型的标识符的数据类型定义为整数。
'int'
static

model :: canView

line 23
此属性指示当前用户是否有权限查看模型。
true
static

model :: canCreate

line 24
model::$canCreate 属性指示是否可以创建模型的新实例。
true
static

model :: canChange

line 25
该属性指示模型是否可以更改,如果允许更改则返回true。
true
static

model :: canDelete

line 26
model::$canDelete 属性指示模型实例是否可以被删除。
true
static

model :: state

line 28
`model::$state` 属性保存模型实例的内部状态,包括元数据、记录、加载状态和已删除记录的包含情况。
%req->model ??= obj(meta: [], records: [], loaded: [], includeDeleted: [])
static

model :: columns

line 29
检索模型中定义的列,或者从static::$columns属性中获取,或者在存在时调用schema方法。
if (isset(static::$columns)) return static::$columns
if (!method_exists(static::class, 'schema')) return static::$table.'.*'
$state = static::state()
$key = spl_object_id(static::DB()).':'.static::DB()->fieldQuotes.':'.static::$table
return $state->meta[static::class]['columns'][$key] ??= static::_columns()
static

model :: _columns

line 36
检索模型关联数据库表的列名,并使用字段引号格式化。
$fq = static::DB()->fieldQuotes
$list = array_merge(...array_values(array_filter(loop(static::fields(), fn($field) => loop($field->objColumns, fn($col) => static::$table."$fq.$fq".$col)))))
return $fq.implode("$fq,$fq", $list).$fq
static

model :: fields

line 41
返回模型架构中定义的字段,如果不存在架构则返回空数组。如果架构可用,则从模型状态元数据中检索字段。
if (!method_exists(static::class, 'schema')) return static::$fields ?? []
$state = static::state()
return $state->meta[static::class]['fields'] ??= static::_fields()
static

model :: _fields

line 46
该属性检索模型架构中定义的字段,同时检查保留的列名以防止冲突。
$reserved = ['table','order','fields','columns','create','change','delete','records','record','column','item','pair','DB','objRecords','objLoaded','objCache','objState','objSave','objGet','objAudit','objValidate','objLastErrors','idColumn','idType']
$fields = loop(static::schema(), fn($field, $column) => last($field->name ??= $column, $field->type === 'parent' && $field->obj ??= $column, $field))
foreach ($reserved AS $word) isset($fields[$word]) && error("Reserved column name '$word' in ".static::class)
return $fields
static

model :: field ($name)

line 52
使用提供的名称访问在模型的静态字段数组中定义的特定字段。
static::fields()[$name]
static

model :: create (...$args)

line 54
在验证输入并执行任何定义的生命周期钩子(如beforeSave、beforeCreate、afterCreate和afterSave)后,在数据库中创建新记录。
$class = static::class
if (static::objValidate() && !static::objRunValidation($args)) return null
$record = new $class(...$args)
method_exists(static::class, 'beforeSave') && $record->beforeSave()
method_exists(static::class, 'beforeCreate') && $record->beforeCreate()
$id = static::createRecord(...$args)
$record = static::record(id: $id)
method_exists(static::class, 'afterCreate') && $record->afterCreate()
method_exists(static::class, 'afterSave') && $record->afterSave()
static::objAudit() && %audit->log($record, 'create', [], (array)$record)
return $record
static

model :: objRunValidation ($data)

line 68
根据模型定义的字段验证提供的数据,收集在验证过程中遇到的任何错误。
$errors = []
$fields = static::fields()
foreach ($data AS $column => $value){
	if (!($field = $fields[$column] ?? null) || !method_exists($field, 'objValidate')) continue
	if ($error = $field->objValidate($value)) $errors[$column] = $error
}
static::$objLastErrors = $errors
return empty($errors)
static

model :: objErrors

line 79
返回模型的最后记录错误作为数组。如果没有记录错误,则返回空数组。
static::$objLastErrors ?? []
static

model :: createRecord (...$args)

line 80
使用提供的参数在指定的数据库表中创建新记录。
static::DB()->create(static::$table, ...$args)
static

model :: change ($where, ...$args)

line 81
使用提供的条件和参数在指定的数据库表上执行更改操作。
static::DB()->change(static::$table, $where, ...$args)
static

model :: delete ($where, ...$args)

line 83
从与模型关联的数据库表中删除记录,选项触发删除前和删除后钩子,并支持软删除。
if (method_exists(static::class, 'beforeDelete') || method_exists(static::class, 'afterDelete') || static::objAudit()){
	$records = static::DB()->query('SELECT '.static::$table.'.* FROM '.static::$table.' WHERE '.$where, ...$args)->fetchAll(\PDO::FETCH_CLASS, static::class)
	foreach ($records AS $record) method_exists(static::class, 'beforeDelete') && $record->beforeDelete()
	if (static::objSoftDelete()) $result = static::DB()->change(static::$table, $where, ...array_values($args), deleted_at: time())
	else $result = static::DB()->delete(static::$table, $where, ...$args)
	foreach ($records AS $record){
		method_exists(static::class, 'afterDelete') && $record->afterDelete()
		static::objAudit() && %audit->log($record, 'delete', (array)$record, [])
	}
	return $result
}
if (static::objSoftDelete()) return static::DB()->change(static::$table, $where, ...array_values($args), deleted_at: time())
return static::DB()->delete(static::$table, $where, ...$args)
static

model :: objLogChange ($where, ...$args)

line 99
记录对数据库中记录所做的更改,如果启用了审计,则审计之前和当前的状态。
if (!static::objAudit()) return static::change($where, ...$args)
$old = static::records(where: $where)
$result = static::DB()->change(static::$table, $where, ...$args)
foreach ($old AS $record){
	$fresh = static::record(id: $record->id)
	$fresh && %audit->log($fresh, 'update', (array)$record, (array)$fresh)
}
return $result
method

%model -> objSave

line 110
将当前对象保存到数据库中,创建新记录或更新现有记录,同时根据需要调用生命周期方法,如 beforeSave、afterSave、beforeCreate、afterCreate、beforeChange 和 afterChange。
$pk = static::idColumn()
$pkValue = $this->$pk ?? $this->id ?? null
$pkValue || error('Can\'t save '.static::class.' record without '.$pk)
$isNew = !static::item([$pk => $pkValue, 'columns' => $pk])
$old = $isNew ? null : clone $this
method_exists(static::class, 'beforeSave') && $this->beforeSave($old)
if ($isNew){
	method_exists(static::class, 'beforeCreate') && $this->beforeCreate()
	static::createRecord(...$this)
	$saved = static::record([$pk => $pkValue])
	method_exists(static::class, 'afterCreate') && $saved->afterCreate()
}
else {
	method_exists(static::class, 'beforeChange') && $this->beforeChange($old)
	static::change($pk.'=?', $pkValue, ...$this)
	$saved = static::record([$pk => $pkValue])
	method_exists(static::class, 'afterChange') && $saved->afterChange($old)
	static::objAudit() && %audit->log($saved, 'update', (array)$old, (array)$saved)
}
method_exists(static::class, 'afterSave') && $saved->afterSave($old)
return $saved
static

model :: transaction ($callback)

line 134
使用提供的回调函数执行数据库事务,确保在提交之前事务内的所有操作都成功完成。
static::DB()->transaction($callback)
static

model :: query

line 135
在模型的数据库上执行查询,根据指定条件返回结果。
phlo('query', class: static::class)
static

model :: objIncludeDeleted

line 137
该属性决定是否应将已删除的记录包含在模型的查询结果中,如果未指定,则默认为 false。
static::state()->includeDeleted[static::class] ?? false
static

model :: objWithDeleted ($callback)

line 138
此方法允许模型在查询结果中包含已删除的记录,通过在执行回调函数期间临时修改状态。
$state = static::state()
$state->includeDeleted[static::class] = true
try {
	$result = $callback()
} finally {
	unset($state->includeDeleted[static::class])
}
return $result
static

model :: objRestore ($id)

line 148
通过将 'deleted_at' 时间戳设置为 null 来恢复软删除的记录。
static::DB()->change(static::$table, static::idColumn().'=?', $id, deleted_at: null)
static

model :: column (...$args)

line 150
通过使用PDO的FETCH_COLUMN选项的fetchAll方法,访问模型加载的记录中的特定列。
static::recordsLoad($args, 'fetchAll', [\PDO::FETCH_COLUMN])
static

model :: item (...$args)

line 151
使用指定的参数和获取模式从数据库加载记录,返回单列数据。
static::recordsLoad($args, 'fetch', [\PDO::FETCH_COLUMN])
static

model :: pair (...$args)

line 152
使用指定的提取模式从数据库加载记录为键值对数组。
static::recordsLoad($args, 'fetchAll', [\PDO::FETCH_KEY_PAIR])
static

model :: records (...$args)

line 153
从模型中检索所有记录,将它们加载为模型类的实例。
static::recordsLoad($args, 'fetchAll', [\PDO::FETCH_CLASS|\PDO::FETCH_UNIQUE, static::class], true)
static

model :: recordCount (...$args)

line 154
返回模型数据库表中的记录总数。
static::item(...$args, columns: 'COUNT('.static::idColumn().')')
static

model :: record (...$args)

line 155
根据提供的参数从模型的记录中检索单个记录,如果找到多个记录则返回错误。
count($records = static::records(...$args)) > 1 ? error('Multiple records for '.static::class) : (current($records) ?: null)
static

model :: recordsLoad ($args, $fetch, $fetchMode, $saveRelations = false)

line 157
根据指定的参数从数据库加载记录,如果配置了缓存,则应用缓存,并管理加载记录的状态。
$pk = static::idColumn()
$args['table'] ??= static::$table
$saveRelations && $args['columns'] ??= static::$table.'.'.$pk.' as _,'.static::columns()
isset(static::$joins) && debug && error('DEPRECATED: static $joins in '.static::class.'. Use getParent/getChildren/getMany instead.')
isset(static::$joins) && $args['joins'] = static::$joins.(isset($args['joins']) ? " $args[joins]" : void)
method_exists(static::class, 'where') && $args['where'] = static::where().(isset($args['where']) ? " AND $args[where]" : void)
static::objSoftDelete() && !static::objIncludeDeleted() && $args['where'] = 'deleted_at IS NULL'.(isset($args['where']) ? " AND $args[where]" : void)
isset(static::$group) && $args['group'] ??= static::$group
isset(static::$order) && $args['order'] ??= static::$order
if ($cacheKey = $args['cacheKey'] ?? null) unset($args['cacheKey'])
if ($duration = $args['cache'] ?? static::objCache()){
	unset($args['cache'])
	$cacheArgs = $args; ksort($cacheArgs)
	$records = apcu($cacheKey ?? static::class.slash.md5(json_encode($cacheArgs)), fn() => static::DB()->load(...$args)->$fetch(...$fetchMode), $duration === true ? 86400 : $duration)
}
else $records = static::DB()->load(...$args)->$fetch(...$fetchMode)
if ($saveRelations && $records){
	$state = static::state()
	$state->records[static::class] = ($state->records[static::class] ?? []) + array_column($records, null, $pk)
	count($state->records[static::class]) > static::objRecordLimit() && $state->records[static::class] = array_slice($state->records[static::class], -static::objRecordLimit(), preserve_keys: true)
}
return $records
static

model :: objRel ($key)

line 182
访问模型中定义的关系对象,返回元数据或在存在时调用方法。
$state = static::state()
return $state->meta[static::class][$key] ??= method_exists(static::class, $key) ? static::$key() : static::$$key ?? []
prop

%model -> objState

line 187
模型的`$objState`属性保存对象的状态,包括其父级、子级和多重关系,初始化为空数组。
['parents' => [], 'children' => [], 'many' => []]
method

%model -> objGet ($key)

line 188
从模型的父级、子级或多个关系中检索与指定键关联的对象。
$this->getParent($key) ?? $this->getChildren($key) ?? $this->getMany($key)
method

%model -> objIn ($ids)

line 189
将ID数组转换为以逗号分隔的字符串,如果数组为空则返回'NULL'。
$ids ? dq.implode(dq.comma.dq, $ids).dq : 'NULL'
method

%model -> getParent ($key)

line 191
从模型的状态中检索与给定键关联的父对象,如有必要则加载它。
if (array_key_exists($key, $this->objState['parents'])) return $this->objState['parents'][$key]
$state = static::state()
$parents = self::objRel('objParents')
if (!$relation = $parents[$key] ?? null) return
$isArray = is_array($relation)
$class = $isArray ? $relation['obj'] : $relation
$column = $isArray ? $relation['key'] ?? $key : $key
if (!$parentId = $this->objData[$column] ?? null) return $this->objState['parents'][$key] = null
if (!isset($state->records[$class][$parentId])){
	$idsToLoad = [$parentId => true]
	$allObjData = array_map(fn($record) => $record->objData, $state->records[static::class] ?? [])
	foreach ($parents as $pKey => $pRelation){
		$pIsArray = is_array($pRelation)
		$pClass = $pIsArray ? $pRelation['obj'] : $pRelation
		if ($pClass === $class) foreach (array_column($allObjData, $pIsArray ? $pRelation['key'] ?? $pKey : $pKey) as $pId) $pId && !isset($state->records[$class][$pId]) && $idsToLoad[$pId] = true
	}
	if ($idsToLoad = array_keys($idsToLoad)) $class::records(where: $class::idColumn().' IN ('.$this->objIn($idsToLoad).')')
}
$parentObject = $state->records[$class][$parentId] ?? null
return $this->objState['parents'][$key] = $parentObject
method

%model -> getChildren ($key)

line 214
从模型的状态中检索与给定键关联的子对象,如果尚未加载,则从数据库中加载它们。
if (array_key_exists($key, $this->objState['children'])) return $this->objState['children'][$key]
$state = static::state()
if (!$relation = self::objRel('objChildren')[$key] ?? null) return
$isArray = is_array($relation)
$class = $isArray ? $relation['obj'] : $relation
$column = $isArray ? $relation['key'] : static::objShortName()
if (!isset($state->loaded[static::class]['children'][$key])){
	$parentIds = array_keys($state->records[static::class] ?? [])
	if ($parentIds){
		$fq = static::DB()->fieldQuotes
		$children = $class::records(where: $fq.$column.$fq.' IN ('.$this->objIn($parentIds).')')
		foreach ($state->records[static::class] AS $parentRecord) $parentRecord->objState['children'][$key] = []
		foreach ($children AS $childId => $child) !is_null($pId = $child->objData[$column] ?? null) && isset($state->records[static::class][$pId]) && $state->records[static::class][$pId]->objState['children'][$key][$childId] = $child
	}
	$state->loaded[static::class]['children'][$key] = true
}
return $this->objState['children'][$key] ?? []
method

%model -> getMany ($key)

line 234
从模型的状态中检索与指定键关联的多个相关记录,如果尚未加载,则从数据库中加载它们。
if (array_key_exists($key, $this->objState['many'])) return $this->objState['many'][$key]
$state = static::state()
if (!$relation = self::objRel('objMany')[$key] ?? null) return
$class = $relation['obj']
if (!isset($state->loaded[static::class]['many'][$key])){
	$parentIds = array_keys($state->records[static::class] ?? [])
	if ($parentIds){
		$fq = static::DB()->fieldQuotes
		$lk = $relation['localKey']; $fk = $relation['foreignKey']
		$pivotRows = static::DB()->rows(table: $relation['table'], columns: $fq.$lk.$fq.comma.$fq.$fk.$fq, where: $fq.$lk.$fq.' IN ('.$this->objIn($parentIds).')')
		$targetIds = array_unique(array_map(fn($row) => $row->{$relation['foreignKey']}, $pivotRows ?: []))
		$targetRecords = $targetIds ? $class::records(where: $class::idColumn().' IN ('.$this->objIn($targetIds).')') : []
		foreach ($state->records[static::class] AS $parentRecord) $parentRecord->objState['many'][$key] = []
		foreach ($pivotRows ?: [] AS $row){
			$parentId = $row->$lk
			$foreignId = $row->$fk
			if (isset($state->records[static::class][$parentId]) && isset($targetRecords[$foreignId])) $state->records[static::class][$parentId]->objState['many'][$key][$foreignId] = $targetRecords[$foreignId]
		}
	}
	$state->loaded[static::class]['many'][$key] = true
}
return $this->objState['many'][$key] ?? []
method

%model -> getCount ($key)

line 259
检索指定键的相关对象的计数,并缓存结果以优化未来的调用。
if (array_key_exists($key, $this->objState['counts'] ?? [])) return $this->objState['counts'][$key]
$state = static::state()
if ($relation = self::objRel('objChildren')[$key] ?? null){
	if (!isset($state->loaded[static::class]['children_count'][$key])){
			$parentIds = array_keys($state->records[static::class] ?? [])
			if ($parentIds){
				$isArray = is_array($relation)
				$class = $isArray ? $relation['obj'] : $relation
				$column = $isArray ? $relation['key'] : static::objShortName()
				$fq = static::DB()->fieldQuotes
				$counts = $class::pair(columns: $fq.$column.$fq.', COUNT(*)', where: $fq.$column.$fq.' IN ('.$this->objIn($parentIds).')', group: $fq.$column.$fq)
				foreach ($state->records[static::class] as $id => $record) $record->objState['counts'][$key] = (int)($counts[$id] ?? 0)
			}
			$state->loaded[static::class]['children_count'][$key] = true
	}
	return $this->objState['counts'][$key] ?? 0
}
if ($relation = self::objRel('objMany')[$key] ?? null){
	if (!isset($state->loaded[static::class]['many_count'][$key])){
		$parentIds = array_keys($state->records[static::class] ?? [])
		if ($parentIds){
			$fq = static::DB()->fieldQuotes
			$localKey = $relation['localKey']
			$counts = static::DB()->load(table: $relation['table'], columns: $fq.$localKey.$fq.',COUNT(*)', where: $fq.$localKey.$fq.' IN ('.$this->objIn($parentIds).')', group: $fq.$localKey.$fq)->fetchAll(\PDO::FETCH_KEY_PAIR)
			foreach ($state->records[static::class] as $id => $record) $record->objState['counts'][$key] = (int)($counts[$id] ?? 0)
		}
		$state->loaded[static::class]['many_count'][$key] = true
	}
	return $this->objState['counts'][$key] ?? 0
}
return 0
method

%model -> getLast ($key)

line 293
从模型的状态中检索与指定键关联的最后一个子对象,如果尚未加载,则进行加载。
if (array_key_exists($key, $this->objState['last_child'] ?? [])) return $this->objState['last_child'][$key]
$state = static::state()
if ($relation = self::objRel('objChildren')[$key] ?? null){
	if (!isset($state->loaded[static::class]['last_child'][$key])){
		if ($parentIds = array_keys($state->records[static::class] ?? [])){
			$isArray = is_array($relation)
			$class = $isArray ? $relation['obj'] : $relation
			$column = $isArray ? $relation['key'] : static::objShortName()
			$childTable = $class::$table
			$fq = static::DB()->fieldQuotes
			$qt = $fq.$childTable.$fq
			$qc = $fq.$column.$fq
			$ids = $this->objIn($parentIds)
			$childPk = $class::idColumn()
			$joins = ' INNER JOIN (SELECT MAX('.$fq.$childPk.$fq.') AS last_id, '.$qc.' AS parent_id FROM '.$qt.' WHERE '.$qc.' IN ('.$ids.') GROUP BY '.$qc.') AS lcmax ON '.$qt.'.'.$fq.$childPk.$fq.' = lcmax.last_id'
			$lastChildren = $class::records(joins: $joins)
			foreach ($state->records[static::class] as $record) $record->objState['last_child'][$key] = null
			foreach ($lastChildren as $child) if (isset($state->records[static::class][$parentId = $child->objData[$column]])) $state->records[static::class][$parentId]->objState['last_child'][$key] = $child
		}
		$state->loaded[static::class]['last_child'][$key] = true
	}
	return $this->objState['last_child'][$key] ?? null
}
return null
static

model :: objResolveClass ($name)

line 320
解析指定模型对象的类名,从而允许在Phlo中动态处理类。
$name
static

model :: objShortName ($class = null)

line 321
此表达式检索当前模型的类名或指定类的类名(如果存在),使用静态上下文。
$class ?? static::class
static

model :: objParents

line 323
返回与当前模型关联的父对象,利用定义的模式并过滤类型为'parent'的字段。
if (property_exists(static::class, 'objParents')) return static::$objParents
if (!method_exists(static::class, 'schema')) return []
return loop(array_filter(static::fields(), fn($f) => $f->type === 'parent'), fn($f, $c) => $f->key ? arr(obj: static::objResolveClass($f->obj), key: $f->key) : (static::objResolveClass($f->obj ?? $c)))
static

model :: objChildren

line 329
返回与当前模型关联的子对象,利用定义的模式并过滤类型为'child'的字段。
if (property_exists(static::class, 'objChildren')) return static::$objChildren
if (!method_exists(static::class, 'schema')) return []
return loop(array_filter(static::fields(), fn($f) => $f->type === 'child'), fn($f, $c) => $f->key ? arr(obj: static::objResolveClass($f->obj), key: $f->key) : (static::objResolveClass($f->obj ?? $c)))
static

model :: objMany

line 335
如果存在 'objMany' 属性,则返回该属性;否则,根据模式定义检索相关对象的数组。
if (property_exists(static::class, 'objMany')) return static::$objMany
if (!method_exists(static::class, 'schema')) return []
return loop(array_filter(static::fields(), fn($f) => $f->type === 'many'), fn($f) => arr(obj: static::objResolveClass($f->obj), table: $f->table, localKey: $f->localKey ?? static::objShortName(), foreignKey: $f->foreignKey ?? $f->obj))
object

%MySQL

/phlo/resources/DB/MySQL.phlo
version 1.1
creator q-ai.nl
summary MySQL handler via DB class
extends DB
package database
frontend false
backend true
requires @DB creds:mysql php-ext:pdo php-ext:pdo_mysql
tags mysql pdo database sql
prop

%MySQL -> PDO

line 11
使用提供的凭据创建一个新的PDO实例以连接到MySQL数据库。
new \PDO('mysql:host='.%creds->mysql->host.';dbname='.%creds->mysql->database, %creds->mysql->user, %creds->mysql->password)
prop

%MySQL -> objPers

line 12
此表达式将值'true'分配给MySQL对象的属性'$objPers'。
true
object

%PostgreSQL

/phlo/resources/DB/PostgreSQL.phlo
version 1.0
creator q-ai.nl
summary PostgreSQL resource
extends DB
package database
frontend false
backend true
requires @DB creds:postgresql php-ext:pdo php-ext:pdo_pgsql
tags postgresql pdo database sql
prop

%PostgreSQL -> PDO

line 11
使用提供的凭据创建一个新的PDO实例,以连接到PostgreSQL数据库。
new PDO('pgsql:host='.%creds->postgresql->host.';dbname='.%creds->postgresql->database, %creds->postgresql->user, %creds->postgresql->password)
prop

%PostgreSQL -> fieldQuotes

line 12
返回字段名称,用双引号包裹,以兼容PostgreSQL。
dq
object

%Qdrant

/phlo/resources/DB/Qdrant.phlo
version 1.0
creator q-ai.nl
summary Embeddings resource with Qdrant
package ai
frontend false
backend true
requires @AI creds:qdrant apcu
tags qdrant embeddings vector search ai
method

%Qdrant -> get (string $input, ?string $model = null)

line 10
使用指定的模型检索给定输入字符串的嵌入,并将结果缓存28天。
apcu('embedding/'.token(input: $input), fn($input) => %AI->embedding(input: $input, model: $model), 86400 * 28)
method

%Qdrant -> collections

line 12
从Qdrant API响应中检索集合名称的数组。
array_column($this->request('collections')->result->collections, 'name')
method

%Qdrant -> create ($collection, $size = 1536, $distance = 'Cosine')

line 13
在Qdrant中创建一个新的集合,指定向量大小和距离度量。
$this->request("collections/$collection", PUT: arr(vectors: arr(size: $size, distance: $distance)))->status === 'ok'
method

%Qdrant -> upsert ($collection, $id, $input, ...$payload)

line 14
此函数使用提供的ID和输入向量更新或插入指定Qdrant集合中的点,并可以附加可选的负载数据。
$this->request("collections/$collection/points", PUT: arr(points: [arr(id: $id, vector: $this->get($input), payload: $payload ?: null)]))->result->operation_id
method

%Qdrant -> delete ($collection, ...$ids)

line 15
根据ID从Qdrant集合中删除指定的点。
$this->request("collections/$collection/points/delete", POST: arr(points: $ids))->result
method

%Qdrant -> search ($collection, $input = null, $top = 100)

line 16
根据输入向量在指定的Qdrant集合中搜索点,并返回最佳结果。
create($this->request("collections/$collection/points/search", POST: arr(vector: is_null($input) ? array_fill(0, 1536, 0) : $this->get($input), top: $top, with_payload: true))->result, fn($record) => $record->id, fn($record) => last($record = array_merge(get_object_vars($record), get_object_vars($record->payload)), obj(...array_filter($record, fn($key) => $key !== 'payload', ARRAY_FILTER_USE_KEY))))
method

%Qdrant -> drop ($collection)

line 17
通过向适当的端点发送DELETE请求,从Qdrant中删除指定的集合。
$this->request("collections/$collection", DELETE: true)->result
method

%Qdrant -> request ($uri, ...$data)

line 19
向指定的 Qdrant 服务器 URI 发送 HTTP 请求,带有可选数据,并返回解码的 JSON 响应。
json_decode(HTTP(%creds->qdrant->server.$uri, %creds->qdrant->key ? ['api-key: '.%creds->qdrant->key] : [], true, ...$data))
object

%query

/phlo/resources/DB/query.phlo
version 1.0
creator q-ai.nl
summary Fluent query builder for Phlo ORM
package database
frontend false
backend true
requires @DB
tags query builder orm database sql
prop

%query -> class

line 10
检索当前查询对象的类类型。
prop

%query -> conditions

line 11
定义查询中结果过滤的条件。
[]
prop

%query -> bindings

line 12
`query->$bindings` 用于检索与 Phlo 中的查询相关联的绑定,从而访问查询执行中使用的参数。
[]
prop

%query -> orderBy

line 13
指定查询结果应按哪个字段排序。
prop

%query -> limitVal

line 14
设置从 Phlo 查询中返回的最大结果数量。
prop

%query -> offsetVal

line 15
检索查询中用于分页的当前偏移值。
method

%query -> fq

line 16
该表达式从与当前实例关联的数据库类中检索字段引用,如果未设置类,则默认为 'bt'。
($class = $this->class) ? $class::DB()->fieldQuotes : bt
method

%query -> q ($column)

line 17
验证指定的查询构建器列名,并通过用完全限定名称包围每个部分来格式化它。
preg_match('/^[A-Za-z_][A-Za-z0-9_.]*$/', $column) || error("Invalid column for query builder: $column")
$fq = $this->fq
return implode(dot, array_map(fn($part) => $fq.$part.$fq, explode(dot, $column)))
method

%query -> eq ($column, $value)

line 23
过滤查询结果,仅包括指定列等于给定值的记录。
$this->where($this->q($column)." = ?", $value)
method

%query -> neq ($column, $value)

line 24
过滤结果,其中指定的列不等于给定的值。
$this->where($this->q($column)." != ?", $value)
method

%query -> gt ($column, $value)

line 25
向查询添加条件,过滤出指定列大于给定值的结果。
$this->where($this->q($column)." > ?", $value)
method

%query -> gte ($column, $value)

line 26
生成一个查询条件,检查指定列的值是否大于或等于给定值。
$this->where($this->q($column)." >= ?", $value)
method

%query -> lt ($column, $value)

line 27
向查询添加条件,以过滤结果,其中指定的列小于给定值。
$this->where($this->q($column)." < ?", $value)
method

%query -> lte ($column, $value)

line 28
向查询添加条件,过滤结果,其中指定的列小于或等于给定值。
$this->where($this->q($column)." <= ?", $value)
method

%query -> like ($column, $value)

line 29
向查询添加一个条件,检查指定列是否包含与提供的值相似的值,使用SQL LIKE运算符。
$this->where($this->q($column)." LIKE ?", $value)
method

%query -> in ($column, array $values)

line 30
过滤查询结果,仅包括指定列的值在提供的值数组中的记录。
$this->where($this->q($column)." IN (".implode(',', array_fill(0, count($values), '?')).")", ...$values)
method

%query -> isNull ($column)

line 31
检查查询中指定的列是否为 null。
$this->where($this->q($column)." IS NULL")
method

%query -> notNull ($column)

line 32
向查询添加条件,以确保指定的列不为 null。
$this->where($this->q($column)." IS NOT NULL")
method

%query -> between ($column, $min, $max)

line 33
过滤结果,仅包括指定列的值在给定的最小值和最大值之间的记录。
$this->where($this->q($column)." BETWEEN ? AND ?", $min, $max)
method

%query -> raw ($sql, ...$bindings)

line 34
使用提供的绑定执行原始 SQL 查询,允许动态查询构建。
$this->where($sql, ...$bindings)
method

%query -> where ($condition, ...$values)

line 35
将条件添加到查询中,并为绑定指定值。它允许根据提供的条件动态过滤结果。
$this->conditions[] = $condition
foreach ($values AS $v) $this->bindings[] = $v
return $this
method

%query -> order ($order)

line 41
使用指定的$order值设置查询的顺序,并返回当前实例。
$this->orderBy = $order
return $this
method

%query -> limit ($limit)

line 46
设置从查询中返回的结果的最大数量,由 $limit 参数定义。
$this->limitVal = $limit
return $this
method

%query -> offset ($offset)

line 51
设置查询的偏移值,从而允许结果的分页。
$this->offsetVal = $offset
return $this
method

%query -> build

line 55
根据指定的条件、顺序、限制和绑定构建查询参数数组,以用于数据库操作。
$where = $this->conditions ? implode(' AND ', $this->conditions) : void
$limit = $this->limitVal ? ($this->offsetVal ? "$this->offsetVal,$this->limitVal" : "$this->limitVal") : void
$args = ['where' => $where ?: void, 'order' => $this->orderBy ?: void, 'limit' => $limit ?: void]
foreach ($this->bindings AS $b) $args[] = $b
return $args
prop

%query -> records

line 63
使用提供的构建参数从指定类中检索记录集合。
($class = $this->class) && $class::records(...$this->build)
prop

%query -> record

line 64
使用提供的构建参数从指定类中检索记录。
($class = $this->class) && $class::record(...$this->build)
prop

%query -> column

line 65
使用定义的类和构建参数访问查询结果集中的特定列。
($class = $this->class) && $class::column(...$this->build)
prop

%query -> item

line 66
使用提供的构建参数从类中检索项。
($class = $this->class) && $class::item(...$this->build)
prop

%query -> count

line 67
使用recordCount方法返回指定类中的记录总数。
($class = $this->class) && $class::recordCount(...$this->build)
method

%query -> delete

line 68
根据指定条件从数据库中删除记录。如果没有提供条件,则会引发错误。
$class = $this->class
$where = $this->conditions ? implode(' AND ', $this->conditions) : error('Cannot delete without conditions')
return $class::delete($where, ...$this->bindings)
object

%SQLite

/phlo/resources/DB/SQLite.phlo
version 1.0
creator q-ai.nl
summary SQLite resource
extends DB
package database
frontend false
backend true
requires @DB php-ext:pdo php-ext:pdo_sqlite
tags sqlite pdo database sql
static

SQLite :: __handle

line 11
此属性保存与SQLite数据库连接的句柄,允许与数据库进行交互。
"SQLite/$file"
method

%SQLite -> __construct (private string $file)

line 12
使用指定的数据库文件初始化一个新的SQLite实例。
prop

%SQLite -> PDO

line 13
使用指定的文件为SQLite创建一个新的PDO实例。
new PDO('sqlite:'.$this->file)

我们使用必要的cookie来使该网站正常工作。在您的许可下,我们还使用分析工具来改善网站。