org.majkel/dbase

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

1.1.7 2018-09-15 21:54 UTC

This package is auto-updated.

Last update: 2024-09-17 03:37:34 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]);
    }
}