grithin / record
管理网页资源的包含
Requires
- php: >=7
- ext-pdo: *
- grithin/phpbase: ^5.0
This package is auto-updated.
Last update: 2024-09-22 07:07:39 UTC
README
一个任意深度的数组,用于跟踪更改、触发事件,
旨在成为一个与数据库记录匹配的可观察者,允许像数组一样处理记录,跟踪更改,处理深层数据结构,并允许监听器对更改事件做出反应。
(类似于SplSubject,但由于SplSubject使用无用的SplObserver,因此未实现)
composer require grithin/record
使用
基本
跟踪任意深度的结构
$data = [ 'id' => 1, 'name' => 'bob', 'children' => [ ['name' => 'sue'] ] ]; $record = new \Grithin\Record($data); $record['name'] = 'bill'; $record->changes(); #> ['name'=>'bill'] $record->apply(); # or alias $record->save(); $record->changes(); #> [] $record['children'][] = ['name'=>'jan']; $record->changes(); /*> {"children": { "1": { "name": "jan"}}} */ unset($record['children'][0]); $record->changes(); /*> {"children": [ {"_class": "Grithin\\MissingValue"}, {"name": "jan"}]} */
获取器、设置器和事件
# Lets make a mock database $database_records = [ 1=>[ 'id'=>1, 'name'=>'bob', 'children' => '[{"name":"sue"}]' ]]; #+ make the getter and setter methods { $get_from_db = function($Record) use ($database_records){ return $database_records[$Record->id]; }; $set_to_db = function($Record, $changes) use ($database_records){ $record_data = $database_records[$Record->id]; $record_data= \Grithin\Dictionary::diff_apply($record_data, $changes); $database_records[$Record->id] = $record_data; return $record_data; }; #+ } # initialize the record, using the 'id' option $record = new \Grithin\Record(false, $get_from_db, $set_to_db, ['id'=>1]); $record->get(); # let's capitalize the name when we set it $capitalize_name = function($Record, $diff){ if(isset($diff['name'])){ $diff['name'] = strtoupper($diff['name']); } }; $record->before_change($capitalize_name); $record['name'] = 'bill'; # the name will become capitalized because of the event listener $record['name']; #> BILL # the children key points to a JSON string $record['children']; #> '[{"name":"sue"}]' # We can make it so JSON is automatically encoded and decoded when moving between the database $jsonify = function($Record, $diff){ if(isset($diff['children'])){ $diff['children'] = json_encode($diff['children']); } }; $unjsonify = function($Record){ if(isset($Record['children'])){ $Record->record['children'] = json_decode($Record->record['children'], true); } }; $record->after_get($unjsonify); $record->before_update($jsonify); $record->get(); # now can access the full structure $record['children'][0]['name']; #> sue $record['children'][0]['name'] = 'jan'; $record->save(); # will encode the json for the db, then decode it for regular access $record['children'][0]['name']; #> 'jan' var_export($database_records); /* > array ( 1 => array ( 'id' => 1, 'name' => 'bob', 'children' => '[{"name":"sue"}]', ), ) */
以上的一些额外亮点。
在after_get
函数unjsonify
中,使用$Record->record['children']
以避免触发更多事件。如果你不介意before_change
和after_change
被运行,可以使用$Record['children']
。
当以$Record['name'] = 'bob'
的方式设置记录时,每次赋值都会触发两个事件。可能更倾向于进行批量更改,这将允许多个东西更改,并且只会触发两个事件。这可以在本地副本和源代码中完成
# update local copy $Record->local_update(['name'=>'bill', 'age'=>1]); # update both $Record->update(['name'=>'bill', 'age'=>1]);
概述
事件、观察者
类型
- EVENT_AFTER_GET : 调用getter函数后立即。这可以用于解码JSON
- EVENT_CHANGE_BEFORE
- EVENT_CHANGE_AFTER
- EVENT_UPDATE_BEFORE : 在更新源之前。这可以用于重新编码JSON
- EVENT_UPDATE_AFTER
便捷函数after_get
、before_change
、after_change
、before_update
、after_update
将在对应的事件上调用参数函数,参数为($this, $details)
,其中在$details
中是一个表示更改的数组对象。
(EVENT_UPDATE_AFTER在EVENT_AFTER_GET之后运行,因为它可能需要通过EVENT_AFTER_GET重新格式化数据)
更新和更改事件只有在有更改时才会触发。
提供给事件观察者的diff参数是一个ArrayObject,该对象在将diff应用于记录时使用。因此,在“before”事件观察者内部修改diff将影响结果记录。如果diff计数变为0,则不会应用更改。
观察者的潜在用途
- 修改特定列(将时间戳转换为日期时间格式)
- 检查记录状态的有效性。如果状态不良,则抛出异常或清除diff
- 创建组合列。例如:total_cost = cost1 + cost2
- 记录特定更改