frootbox/db 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

frootbox/db

Composer 安装命令:

composer require frootbox/db

包简介

Frootbox Database Abstraction Layer

README 文档

README

Frootbox Db is a small PHP database abstraction and Active Record layer for MySQL. It wraps PDO, provides a lightweight query builder, maps result rows to row objects, and offers a migration path from dynamic Active Record accessors to explicit getter and setter methods.

The package is intentionally compact. It is useful when you want simple models and rows without adopting a full ORM.

Installation

Install the package with Composer:

composer require frootbox/db

Requirements:

  • PHP 8.0 or newer
  • ext-pdo
  • MySQL or MariaDB when using the bundled MySQL adapter

Creating A Connection

Create a DBMS adapter and wrap it in Frootbox\Db\Db:

use Frootbox\Db\Db;
use Frootbox\Db\Dbms\Mysql;

$db = new Db(new Mysql(
    host: 'localhost',
    schema: 'app',
    user: 'app',
    password: 'secret',
));

Db exposes low-level methods such as query(), prepare(), fetch(), update(), delete(), and transaction helpers.

Rows

A row represents one database record. Extend Frootbox\Db\Row for your entities:

namespace App\Persistence;

use Frootbox\Db\Row;

class Page extends Row
{
    protected $table = 'pages';
    protected $model = Pages::class;

    public function getTitle(): ?string
    {
        return $this->getAttribute('title');
    }

    public function setTitle(?string $title): static
    {
        return $this->setAttribute('title', $title);
    }

    public function isVisible(): bool
    {
        return !empty($this->getAttribute('isVisible'));
    }
}

Rows store their raw database values internally and track changed attributes. Call save() to persist changed values and delete() to remove the record.

$page->setTitle('About us');
$page->save();

Legacy Dynamic Accessors

Older projects can still call accessors that are not explicitly defined:

$page->getTitle();
$page->setTitle('About us');
$page->isVisible();

These calls are handled by Row::__call() for backward compatibility. New code should add explicit methods that delegate to getAttribute() and setAttribute(). Deprecated dynamic calls are logged once per call site by default.

Disable that logging when needed:

\Frootbox\Db\Row::setDeprecatedMagicCallLogging(false);

Models

A model acts as a repository for one table:

namespace App\Persistence;

use Frootbox\Db\Model;

class Pages extends Model
{
    protected string $table = 'pages';
    protected string $class = Page::class;
}

Fetch rows:

$pages = new Pages($db);

$result = $pages->fetch([
    'where' => [
        'isVisible' => 1,
    ],
    'order' => [
        'title ASC',
    ],
]);

foreach ($result as $page) {
    echo $page->getTitle();
}

Fetch one row:

$page = $pages->fetchById(42);
$latest = $pages->fetchOne([
    'order' => ['date DESC'],
]);

Insert a row:

$page = new Page([
    'title' => 'About us',
    'isVisible' => 1,
]);

$pages->persist($page);

insert() is still available as a deprecated alias for persist().

Conditions

Condition objects can be used in where arrays for comparisons beyond equality:

use Frootbox\Db\Conditions\Greater;
use Frootbox\Db\Conditions\Like;

$result = $pages->fetch([
    'where' => [
        new Greater('id', 10),
        new Like('title', '%About%'),
    ],
]);

Available conditions include:

  • Equal
  • NotEqual
  • Greater
  • GreaterOrEqual
  • Less
  • LessOrEqual
  • Like
  • IsNull
  • IsNotNull
  • InArray
  • NotInArray
  • MatchColumn

Results

Frootbox\Db\Result is an iterator, Countable, and JsonSerializable. It lazily converts raw database records into row objects while iterating.

Useful helpers:

$result->getCount();
$result->isEmpty();
$result->getById('42');
$result->extractValues('title');
$result->implode(', ', 'title');
$result->removeByValue('status', 'archived');

Nested Sets

The package includes optional nested-set base classes:

  • Frootbox\Db\Rows\NestedSet
  • Frootbox\Db\Models\NestedSet

They provide helpers such as appendChild(), getChildren(), getParent(), getTrace(), getSiblings(), and rewriteIds().

Generating Explicit Accessors

The package ships a Composer binary:

vendor/bin/frootbox-db

Generate missing getter and setter methods for existing row classes:

vendor/bin/frootbox-db generate-accessors src/Persistence

When the command is run from a project root containing localconfig.php, it automatically reads the database connection from:

return [
    'database' => [
        'dbms' => 'mysql',
        'host' => 'localhost',
        'user' => 'root',
        'password' => 'root',
        'schema' => 'app',
    ],
];

Use a custom config path when needed:

vendor/bin/frootbox-db generate-accessors src/Persistence --localconfig=config/localconfig.php

Alternatively, a bootstrap file can return a Frootbox\Db\Db instance, or an array with a db key:

<?php

return $container->get(\Frootbox\Db\Db::class);

You can also pass connection details directly:

vendor/bin/frootbox-db generate-accessors src/Persistence \
  --db-host=localhost \
  --db-schema=app \
  --db-user=app \
  --db-password=secret

Preview changes without writing files:

vendor/bin/frootbox-db generate-accessors src/Persistence --dry-run

The generator scans concrete classes extending Frootbox\Db\Row, reads their protected $table value, loads columns from INFORMATION_SCHEMA.COLUMNS, and adds missing methods. Existing methods are not overwritten.

Transactions

Use transactionStart() and transactionCommit() around multi-step changes:

$db->transactionStart();

$page->setTitle('New title');
$page->save();

$db->transactionCommit();

Call rollback() if a transaction should be reverted.

Error Handling

Model::persist() maps common MySQL integrity errors to package exceptions:

  • UniqueConstraintViolationException
  • ForeignKeyViolationException
  • ConstraintViolationException

All extend Frootbox\Db\Exception\DatabaseException.

License

This package is licensed under the GPL-3.0-or-later license.

frootbox/db 适用场景与选型建议

frootbox/db 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 3.12k 次下载、GitHub Stars 达 0, 最近一次更新时间为 2019 年 06 月 22 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 frootbox/db 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 frootbox/db 我们能提供哪些服务?
定制开发 / 二次开发

基于 frootbox/db 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 3.12k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 1
  • 依赖项目数: 2
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: GPL-3.0-or-later
  • 更新时间: 2019-06-22