This document shows example-led usage of Freshsauce\Model\Model for common application flows.
Define a model by extending the base class and setting the table name:
require_once 'vendor/autoload.php';
Freshsauce\Model\Model::connectDb(
'pgsql:host=127.0.0.1;port=5432;dbname=categorytest',
'postgres',
'postgres'
);
class Category extends Freshsauce\Model\Model
{
protected static $_tableName = 'categories';
}$category = new Category([
'name' => 'Fiction',
]);
$category->save();
echo $category->id;
echo $category->created_at;
echo $category->updated_at;save() inserts when the primary key is null and updates when the primary key is present.
$category = Category::getById(1);
if ($category !== null) {
echo $category->name;
}$category = Category::getById(1);
if ($category !== null) {
$category->name = 'Modern Fiction';
$category->save();
}If you want to call the insert path directly:
$category = new Category([
'name' => 'Biography',
]);
$category->insert();If you already know the object exists and want to call update directly:
$category = Category::getById(1);
if ($category !== null) {
$category->name = 'Memoir';
$category->update();
}$first = Category::first();
$last = Category::last();
$count = Category::count();Preferred camelCase methods:
$all = Category::findByName('Fiction');
$one = Category::findOneByName('Fiction');
$first = Category::firstByName(['Fiction', 'Fantasy']);
$last = Category::lastByName(['Fiction', 'Fantasy']);
$count = Category::countByName('Fiction');Legacy snake_case dynamic methods still work during the transition, but they are deprecated and should be migrated.
Check existence:
$hasCategories = Category::exists();
$hasFiction = Category::existsWhere('name = ?', ['Fiction']);Fetch ordered results:
$alphabetical = Category::fetchAllWhereOrderedBy('name', 'ASC');
$latest = Category::fetchOneWhereOrderedBy('id', 'DESC');Pluck one column:
$names = Category::pluck('name', '', [], 'name', 'ASC', 10);Fetch a single matching record:
$category = Category::fetchOneWhere(
'id = ? OR name = ?',
[1, 'Fiction']
);Fetch all matching records:
$categories = Category::fetchAllWhere(
'name IN (?, ?)',
['Fiction', 'Fantasy']
);Delete via an instance:
$category = Category::getById(1);
$category?->delete();Delete by primary key:
Category::deleteById(1);Delete by condition:
Category::deleteAllWhere(
'name = ?',
['Fiction']
);Delete with a richer SQL fragment that works across MySQL/MariaDB and PostgreSQL:
Category::deleteAllWhere(
'id IN (SELECT id FROM categories WHERE name = ? ORDER BY name DESC LIMIT 2)',
['Fiction']
);Drop down to PDO statements when needed:
$statement = Freshsauce\Model\Model::execute(
'SELECT * FROM categories WHERE id > ?',
[10]
);
$rows = $statement->fetchAll(PDO::FETCH_ASSOC);Use instance-aware hooks to enforce model rules before insert and update:
class Category extends Freshsauce\Model\Model
{
protected static $_tableName = 'categories';
protected function validateForSave(): void
{
if (trim((string) $this->name) === '') {
throw new RuntimeException('Name is required');
}
}
}Override validateForInsert() or validateForUpdate() when the rules are operation-specific.
The legacy static validate() method remains supported for backward compatibility.
Enable strict field mode when you want unknown assignments to fail immediately instead of being silently ignored on persistence:
class Category extends Freshsauce\Model\Model
{
protected static $_tableName = 'categories';
protected static bool $_strict_fields = true;
}Or enable it temporarily:
Category::useStrictFields(true);Freshsauce\Model\Model::connectDb(
'mysql:host=127.0.0.1;port=3306;dbname=categorytest',
'root',
''
);Freshsauce\Model\Model::connectDb(
'pgsql:host=127.0.0.1;port=5432;dbname=categorytest',
'postgres',
'postgres'
);