naril/dbase

访问 dbase / xbase / dbf 数据库文件的库

1.1.5 2017-07-31 12:46 UTC

This package is not auto-updated.

Last update: 2024-09-24 18:19:50 UTC


README

Build Status SensioLabsInsight Latest Stable Version Total Downloads Latest Unstable Version PHP Version License

处理 dbase 表的库。

目录

  1. 支持的格式
    1. 支持的备忘录格式
  2. 安装
  3. 文档
    1. 读取表
    2. 插入行
    3. 自动类型转换
    4. 记录对象
      1. 从记录中读取数据
      2. 向记录中写入数据
    5. 记录对象
    6. 更新表
    7. 删除记录
    8. 事务
    9. 定义表
      1. 从另一个表创建表
    10. 过滤器
      1. 使用过滤器
      2. 编写自定义过滤器

支持的格式

  • dBASE III
  • dBASE III PLUS
支持的备忘录格式
  • DBT
  • FPT

安装

Composer

强烈推荐使用 composer 安装此库。

composer require org.majkel/dbase

然后在你的脚本中使用此行代码

require_once 'vendor/autoload.php'

旧式风格

下载库并将其放置在磁盘上的某个位置。

然后在你的脚本中使用此行代码

require_once 'DBASE/LIB/DIR/autoloader.php';

文档

读取表

表对象既是数组可访问的,也是可遍历的。你可以将其作为集合循环或通过其索引读取特定记录。

require_once 'vendor/autoload.php'

use org\majkel\dbase\Table;

$totalSum = 0;

$dbf = Table::fromFile('some/table.dbf');

foreach ($dbf as $record) {
    // returns all records includeing deleted ones
    if (!$record->isDeleted()) {
        $totalSum += $record->int_val;
    }
}

echo "Total sum is $totalSum, 5th description: {$record[4]['description']}\n";

插入行

你可以作为记录对象或关联数组插入记录。

注意,插入操作不是原子的。使用事务以实现完整性安全。

require_once 'vendor/autoload.php'

use org\majkel\dbase\Table;
use org\majkel\dbase\Record;

$dbf = Table::fromFile('some/table.dbf');

$record = new Record();
$record->fieldBool = true;
$record->fieldInt  = 123;
$record->fieldChar = 'some text 1';
$record->fieldMemo = 'some long text';

$dbf->insert($record);

$dbf->insert([
    'fieldBool' => false,
    'fieldInt'  => 321,
    'fieldChar' => 'some text 2',
]);

自动类型转换

在检索和存储行时,dBase 和 PHP 类型会自动转换。

记录对象

记录基本上是 ArrayObject。可以将对象视为数组。

从记录中读取数据

require_once 'vendor/autoload.php'

use org\majkel\dbase\Table;

$dbf = Table::fromFile('some/table.dbf');

// fetch first record
$record = $dbf[0];

echo "int  field: {$record->number}\n"; // returns integer
echo "bool field: {$record->boolean}\n"; // returns boolean
echo "date field: {$record->date->format('Y-m-d')}\n"; // return DateTime object
echo "text field: {$record->text}\n"; // returns string
echo "memo field: {$record->memo}\n"; // returns string (not entity id)
echo "memo field id: {$record->getMemoEntryId('memo')}\n"; // returns entity id for memo field `memo`
echo "is record deleted: {$record->isDeleted('memo')}\n"; // returns whether record is deleted

// ... or ...

echo "int  field: {$record['number']}\n"; // returns integer
echo "bool field: {$record['boolean']}\n"; // returns boolean
echo "date field: {$record['date']->format('Y-m-d')}\n"; // return DateTime object
echo "text field: {$record['text']}\n"; // returns string
echo "memo field: {$record['memo']}\n"; // returns string (not entity id)
echo "memo field id: {$record->getMemoEntryId('memo')}\n"; // returns entity id for memo field `memo`
echo "is record deleted: {$record->isDeleted('memo')}\n"; // returns whether record is deleted

// you can loop over fields in the record
foreach ($record as $fieldName => $fieldValue) {
    echo "$fieldName = $fieldValue\n";
}

向记录中写入数据

require_once 'vendor/autoload.php'

use org\majkel\dbase\Table;

$dbf = Table::fromFile('some/table.dbf');

// fetch first record
$record = $dbf[0];

$record->number  = 123;
$record->boolean = true;
$record->date    = new DateTime();
$record->text    = 'some text';
$record->memo    = 'some longer text';

// ... or ...

$record['number']  = 123;
$record['boolean'] = true;
$record['date']    = new DateTime();
$record['text']    = 'some text';
$record['memo']    = 'some longer text';

更新表

注意,更新操作不是原子的。使用事务以实现完整性安全。

require_once 'vendor/autoload.php'

use org\majkel\dbase\Table;

$dbf = Table::fromFile('some/table.dbf');

foreach ($dbf as $record) {
    $record->int_val += 10;
    $dbf->update($record); // header is updated everytime
}

删除记录

不要使用 Record::setDeleted 来删除记录

require_once 'vendor/autoload.php'

use org\majkel\dbase\Table;

$dbf = Table::fromFile('some/table.dbf');

// delete 7th record
$dbf->delete(6);

// undelete 6th record
$dbf->markDelete(5, false);

事务

事务可以防止两个进程更新同一个文件。

当某些进程无法获取表的锁定时,会抛出异常。

事务还可以让您免于不必要的头更新。头在事务结束时更新。

require_once 'vendor/autoload.php'

use org\majkel\dbase\Table;

$dbf = Table::fromFile('some/table.dbf');

// header is updated. Transaction flag is set
$dbf->beginTransaction();

foreach ($dbf as $record) {
    $record->int_val += 10;
    $dbf->update($record);  // header is not written
}

// duplicate last row
$dbf->insert($record); // header is not written

// header is written, transaction flag is cleared, recond count is updated
$dbf->endTransaction();

定义表

使用构建器对象来构造新表。

require_once 'vendor/autoload.php'

use org\majkel\dbase\Builder;
use org\majkel\dbase\Format;
use org\majkel\dbase\Field;

$table = Builder::create()
    ->setFormatType(Format::DBASE3)
    ->addField(Field::create(Field::TYPE_CHARACTER)->setName('str')->setLength(15))
    ->addField(Field::create(Field::TYPE_LOGICAL)->setName('bool'))
    ->addField(Field::create(Field::TYPE_NUMERIC)->setName('num'))
    ->build('destination.dbf');

for ($i = 1; $i <= 3; ++$i) {
    $table->insert([
        'str' => "Str $i",
        'bool' => false,
        'num' => $i,
    ]);
}

从另一个表创建表

您可以从现有的表定义创建新表。

require_once 'vendor/autoload.php'

use org\majkel\dbase\Builder;
use org\majkel\dbase\Format;
use org\majkel\dbase\Field;

$table = Builder::fromFile('source.dbf')
    ->setFormatType(Format::DBASE3)
    ->addField(Field::create(Field::TYPE_NUMERIC)->setName('newField1'))
    ->build('destination.dbf');

for ($i = 1; $i <= 3; ++$i) {
    $table->insert([
        'oldField1' => "Str $i",
        'oldField2' => false,
        'newField1' => $i,
    ]);
}

过滤器

尽管值会根据列类型自动转换,但有时需要进行额外的处理。为了实现这一点,您可以在列上添加过滤器。

使用过滤器

require_once 'vendor/autoload.php'

use org\majkel\dbase\Builder;
use org\majkel\dbase\filter\TrimFilter;
use your\CurrencyFilter;

$dbf = Table::fromFile('some/table.dbf');
$dbf->getHeader()->getField('price')
    ->addFilter(new TrimFilter())
    ->addFilter(new CurrencyFilter(',', '.'));

foreach ($dbf as $record) {
    // ...
}

过滤器按定义的顺序在加载时应用。在序列化过程中,过滤器按相反的顺序应用。

编写自定义过滤器

require_once 'vendor/autoload.php'

use org\majkel\dbase\FilterInterface;
use org\majkel\dbase\Field;

class CurrencyFilter extends FilterInterface
{
    /** @var string */
    private $inputDot;
    /** @var string */
    private $outputDot;

    /**
     * @param string $inputDot
     * @param string $outputDot
     */
    public function __construct($inputDot, $outputDot)
    {
        $this->inputDot = $inputDot;
        $this->outputDot = $outputDot;
    }

    /**
     * From table value to PHP value
     *
     * @param mixed $value
     * @return mixed
     */
    public function toValue($value)
    {
        return str_replace($this->inputDot, $this->outputDot, $value);
    }

    /**
     * From PHP value to table value
     *
     * @param mixed $value
     * @return mixed
     */
    public function fromValue($value)
    {
        return str_replace($this->outputDot, $this->inputDot, $value);
    }

    /**
     * Filter can be applied on string like columns
     *
     * @param integer $type
     * @return boolean
     */
    public function supportsType($type)
    {
        return in_aray($type, [Field::TYPE_CHARACTER, Field::TYPE_MEMO]);
    }
}