| core_storage

# Class: Bs_OoDbBasics Source Location: /core/storage/oodb/Bs_OoDbBasics.class.php
### Class Overview
    Bs_Object
       |
       --Bs_OoDbBasics
Basic function library for Bs_OoDb.class.php OoDb is the abriviation for "Object Oriented Database" For details on how to use ooDb see Bs_OoDb.class.php (or Bs_OoDbForMySql.class.php) The folling text will discribe details and concepts of the implementation. #### Author(s): Sam Blum <at blueshoes dot org> #### Version: 4.0.$Revision: 1.2 $ #### Copyright: blueshoes.org | ### Variables $pDataHasChanged $pDefaultScope $pDefaultScope $pErrorDelete $pErrorFetch $pErrorStore $pInfoList $pMetaData $pObjFetchedFromStorage $pObjName $pObjPutInStorage $pObjToPersist $pStorageAutoCreate | ### Methods Bs_OoDbBasics errorDump flattenObjArray forceSave getError_Delete getError_Persist getError_Unpersist getFieldNames getID getPersistTag getScope setHardScope setID _getStreamFields _setError_Delete _setError_Fetch _setError_Store
### Child classes: Bs_OoDb A B S T R A C T [*1] Object Bs_OoDb.class.php | ### Inherited Variables | ### Inherited Methods #### Class: Bs_Object Bs_Object::Bs_Object() Bs_Object::getErrors() Basic error handling: Get *all* errors as string array from the global Bs_Error-error stack. Bs_Object::getLastError() Basic error handling: Get last error string from the global Bs_Error-error stack. Bs_Object::getLastErrors() Basic error handling: Get last errors string array from the global Bs_Error-error stack sinc last call of getLastErrors(). Bs_Object::persist() Persists this object by serializing it and saving it to a file with unique name. Bs_Object::setError() Basic error handling: Push an error string on the global Bs_Error-error stack. Bs_Object::toHtml() Dumps the content of this object to a string using PHP's var_dump(). Bs_Object::toString() Dumps the content of this object to a string using PHP's var_dump(). Bs_Object::unpersist() Fetches an object that was persisted with persist()
### Class Details [line 202] Basic function library for Bs_OoDb.class.php OoDb is the abriviation for "Object Oriented Database" For details on how to use ooDb see Bs_OoDb.class.php (or Bs_OoDbForMySql.class.php) The folling text will discribe details and concepts of the implementation. I decided to explain this class unsing a FAQ list. FAQ: 0) INTRO a) How are the objetcts stored? b) What is a strong and weak reference? c) What does soft-Delete mean? 1) SCOPE a) What is a Scope? b) Where is the scope stored? c) Scope priority? 2) STORAGE TABLE CREATION/MODIFICATION 2 a) Are the storage-tables created automaticaly? 2 b) What happens if I add new field To the object? 3) PERSISTING (STORING) 3 a) If the object hasn't changed since the last fetch, does OoDb still write it to the storage? 3 b) Are the sub-objects ('has a'-relations) of an object also saved? 3 c) Are array of objects also supported? 3 d) Are values with NULL supported? 3 e) What happens, if objects happen to have the value NULL or are unSet? 3 f) What happens if I move a object from one 'Array of Objects' to an other 'Array of Objects'? 3 g) How are cyclic referencing objects handled? 4) UNPERSISTING (FETCHING) 4 b) What happens when I fetch the same object a few times? Do I get a copy? 0) INTRO a) How are the objects stored? --------------------------------- Wrong question for this class, as it should not have any methods to store the data. It only has methods to help the underlying storage. (But we can assume that it's a table based relational Db). See Bs_OoDbForMySql.class.php and/or study the ABSTRACT functions part of Bs_OoDb.class.php b) What is a strong and weak reference? --------------------------------------- During the work with objects that use other objects in a 'has a'-relation ooDb keeps track of 'Who's Using Who'. If an object has *no strong references*, ooDb will remove it from the storage. Well, when is a reverence strong and when weak? By default a reference to an other object is 'strong' unless: a) It's defined in the $_ooDbProperty['reference']='weak'. b) References to other scopes (Db's) are always 'weak'. And what is the use? SAMPLE: (Objects are braced with []) A [Firm] holding a *strong* reference to the 'Array of [Employee]' A [Telephone book] holding an *weak* reference to the 'Array of [Employee]' If the [Firm] fires an [Employee], the [Employee] would never be removed, because of the entry in the [Telephone book]. But because this reference is *weak* ooDb will removed a fired [Employee] anyway. NOTE: Always expect that a *weak* reference may be NULL on unpersist. c) What does soft-Delete mean? -------------------------------- Read 0 b). Soft delete will remove object data that has *no strong references*, to it. 1) SCOPE a) What is a scope? --------------------- The scope is the area to store the data. As the underlying storage function may use different techniques to store an object it's our believe, that all these methods will use a 'scope' to identify the storage area. For a SQL-dbs this would be the <dbName> and for a file-dbs this could be the directory. It's also used to build target- and source- keys of the object. It's also used for the $_persistTag of the pObjToPersist. b) Where is the scope stored? -------------------------------- The scope-information is stored in 2 ways: a) By setting the default scope. That is the scope-info stored in this object (in $pDefaultScope). It is set as a mandatory parameter in persist() / unpersist() / delete() b) By setting the 'strong'-scope of the object. That is a scope attached to the object (in $this->pObjToPersist->_ooDbScope). See function setHardScope(). c) Scope priority? -------------------- 1: The 'strong'-scope of the $pObjToPersist is used. (If not empty) 2: The default-scope of this object is used. (If not empty) 3: If no scope is given, the data will be stored at the 'current' location. That is where the underlying storage handler currently is 'standing'. 2) STORAGE TABLE CREATION/MODIFICATION 2 a) Are the storage-tables created automatically? ------------------------------------------------- By default *NO*. There is a variable $pStorageAutoCreate that may be set to TRUE. The underlying storage will the create/modify the tables it needs *BUT* it's a performance killer! Turn it on during develop and the turn it back off. Better to used my tool Bs_OoDbAble.class.php 2 b) What happens if I add new field to the object? ---------------------------------------------------- This depends on the underlying storagehandler. In Bs_OoDbForMySql.class.php will add (but not delete) missing fields if $pStorageAutoCreate==TRUE. It will even try to change the fieldType if it changes. Better to used my tool Bs_OoDbAble.class.php 3) PERSISTING (STORING) 3 a) If the object hasn't changed since the last fetch, does OoDb still write it to the storage? --------------------------------------------------------------------------------------------- NO! To detect if the object has changed I'm using a md5-fingerpring. *BUT* to prepare and calculate the fingerprint I have to gather the data of the object, sort it, serialize it and finally md5 it. This cost CPU and in some cases where the object is complex I'm not sure if it's worth the effort. If for some reason you wish to force a save for the lonely-data of an object, you may call the function forceSave(&$object, $force=TRUE). But this shouldn't necessary. 3 b) Are the sub-objects ('has a'-relations) of an object also saved? --------------------------------------------------------------------- YES, *but* only the objects/object-arrays are saved that are marked as $_ooDbProperty['mode']='object' in the _ooDbProperty variable. The sub-object may then have an _ooDbProperty variable too. a.s.o. 3 c) Are array of objects also supported? ----------------------------------------- YES. If a variable is marked as object (see 3 b). ooDb will detect an array (hash or vector) and assume it's an 'Array of Object'. Or even an 'Array-tree of Objects' (array of array). NOTE: There are some limitation on how deep the tree may be and what happens if the array has cycling references. (See function _flattenObjArray). 3 d) Are values with NULL supported? ------------------------------------ NO! There are a few reasons *not* to support NULL values. 1) You don't really need it. It's 99.999% passable to find a substitute for NULL like -1 or -(2^16) or '' or 'NULL' ... 2) Can't have index on fields with NULL values. 3) Complicated (unperforming) to detect a NULL when unpersisting 4) Queries get very complicated. 3 e) What happens, if objects happen to have the value NULL or are unSet? ------------------------------------------------------------------------- It is ignored during the persist phase. 3 f) What happens if I move a object from one 'Array of Objects' to an other 'Array of Objects'? ------------------------------------------------------------------------------------------------ Quite often you will have a 'main'-object that handles many other objects; shuffling them around from on 'Array of Objects' to an other 'Array of Objects'. When you persist the 'main'-object now, the references are updated. Any objects that not referenced any more by the 'main'-object are soft-Deleted (See: 0 c) What does soft-Delete mean?). New objects or objects that have changed are stored/updated. (Assuming these objects are marked for persistence in the _ooDbProperty variable). 3 g) How are cyclic referencing objects handled? ------------------------------------------------- Cyclic referencing objects (direct or indirect) Sample for direct cycle: An object [A] containing an object [B] and [B] is pointing back to [A] The problem is that this could end in an endless loop. For this reason ooDb keeps track of which objects have been saved, by marking the saved object. The same object is only saved once. 4) UNPERSISTING (FETCHING) 4 b) What happens when I fetch the same object a few times? Do I get a copy? ---------------------------------------------------------------------------- During a unpersist *call* all fetched objects are cached. If the *same* object (*same* means: objectName, ID AND scope match) is fetched a second time the object will be taken from cash *by reference*. When the call has ended the cache is emptied. It's important to note that a second unpersist *call* would not know about the already fetched objects. So the answer is: A call to unpersist will not create multiple copies of the *same* object. Multiple calls to unpersist will. Most data is hold by pointer, so changes to the data effect immediately *BUT* streamed data is an exception. Streams have to be prepared on every call. That's way caching is default FALSE; Similar effect with the tag info, that depending on the current scope. The ID data must be set to the right tag-info. #### Tags:
access: | public
version: | 4.0.$Revision: 1.2 $
status: | deprecated USE Bs_SimpleObjPersister
copyright: | blueshoes.org
author: | Sam Blum <at blueshoes dot org>
[ Top ] ### Class Variables #### $pDataHasChanged = TRUE [line 278] Only persist if something has changed. The auto change detection works with a md5 fingerprint #### Tags:
see: | _prepareToPersistData()
Type: | mixed
[ Top ] #### $pDefaultScope = '' [line 210]
Type: | mixed
[ Top ] #### $pDefaultScope = '' [line 547]
Type: | mixed
[ Top ] #### $pErrorDelete = [line 935]
Type: | mixed
[ Top ] #### $pErrorFetch = [line 934]
Type: | mixed
[ Top ] #### $pErrorStore = [line 933] A vector of the errors that happend during the last persist/unpersist/delete trys. The entries are chronologicaly starting by 0; Structure: pErrorStore[] = array( 'className'=> <class>, 'varName' => <varName>, 'msg' => <string> or <Exception> NOTE: The errors are stored in 2 paces! a) In the static vars $pErrorStore, -Fetch, -Delete holding *ALL* the errors that occured. b) In the $pObjectToPersist vars $_persistError_Store, -Fetch, -Delete holding only the errors of that object. #### Tags:
static: | !
Type: | mixed
[ Top ] #### $pInfoList = NULL [line 271]
Type: | mixed
[ Top ] #### $pMetaData = NULL [line 270] Cached information from _prepareToPersistData() For what we want to do, we need data in different structurs. #### Tags:
var: | pMetaData, pInfoList
see: | _prepareToPersistData()
Type: | hash
[ Top ] #### $pObjFetchedFromStorage = [line 681] A list of all objects, that have been already fetched from the storage. When trying to fetching the same object two and more times during a unpersist() -call, the result should be *one* object with the vars pointing to the same object! In this way we also pervent deadlock-loops when objects reference each other. This variable is *static* #### Tags:
var: | Hash pointing to objects already fetched. The key is a unique sourceID (e.g. 'db.table:ID')
see: | _memorizeObjFetched()
static: |
Type: | hash
[ Top ] #### $pObjName = '' [line 207]
Type: | mixed
[ Top ] #### $pObjPutInStorage = [line 670] A list of all objects, that have already been put into the storage. When persisting, we have to mark each object with a targetID and when finished we have to remove the marker. That's wy we keep a vector of all objects we marked, thus to unmarke them at the end of persisting. This variable is *static* #### Tags:
var: | Vector pointing to objects already stored.
see: | _memorizeObjStored()
static: |
Type: | vector
[ Top ] #### $pObjToPersist = NULL [line 204]
Type: | mixed
[ Top ] #### $pStorageAutoCreate = FALSE [line 213]
Type: | mixed
[ Top ] ### Class Methods ### constructor Bs_OoDbBasics [line 222]
`Bs_OoDbBasics Bs_OoDbBasics( mixed $fileName)`
Constructor During the process of storing '$this' is cloned (copied), reset and reused. Data that has to be kept available is static. Currently the stored/fetched objects are kept in a array and all error during the process of store/fetch/delete. [ Top ] ### method errorDump [line 990]
`void &errorDump( )`
[ Top ] ### method flattenObjArray [line 871]
`void &flattenObjArray( mixed &$objTree, array &$objTree.)`
Wrapper for function _flattenObjArray() #### Tags:
see: | _flattenObjArray()
access: | public
#### Parameters:
array | &$objTree. | Any hash or vector of objects.
[ Top ] ### method forceSave [line 618]
`void forceSave( object &$object, [bool $force = TRUE])`
If 'forceSave' is set to TRUE the "md5 autodetect modification" will not be used and the data will always be stored. #### Tags:
access: | public
#### Parameters:
object | $object | The object to set to force save.
bool | $force | TRUE (default)
[ Top ] ### method getError_Delete [line 979]
`void &getError_Delete( [mixed $all = FALSE])`
[ Top ] ### method getError_Persist [line 959]
`void &getError_Persist( [mixed $all = FALSE])`
[ Top ] ### method getError_Unpersist [line 969]
`void &getError_Unpersist( [mixed $all = FALSE])`
[ Top ] ### method getFieldNames [line 901]
`hash &getFieldNames( [mixed $useCach = TRUE], bool &$useCach.)`
I sometimes need all varNames that will have a filed in the underlying storage #### Tags:
return: | with all the streamNames as keys.
access: | public
#### Parameters:
bool | &$useCach. |
[ Top ] ### method getID [line 557]
`integer. getID( object &$object, [string $scope = ''])`
Get the objects sorage ID. NOTE: Every scope has it's own ID. But it's optional if you use current scope. #### Tags:
return: | If the object has no ID (in that scope) 0 is returned
access: | public
#### Parameters:
object | $object | The object to get the ID from.
string | $scope | (opt, default:''). The scope to use.
[ Top ] ### method getPersistTag [line 646]
`&hash &getPersistTag( object &$object, [mixed $scope = ''])`
Status info is set in the $_persistTag -hash. For exsample the ID of the object when it's fetched from the storage. The $_persistTag is dependent on the scope. (See header info: Scope) Thus the ID may differ from one scope to the other. E.g. Imagine this object stored in (or fetched from) db_A.tblFoo and db_B.tblFoo. Quite certin the ID's will differ !! Structure: $_persistTag[$scope] = array( 'ID' => <ID> // The storage ID 'md5' => <md5> // Data fingerprint. Used to autodetect modifications. 'forceSave' => [TRUE|FALSE] ) If no scope is set, a dummy scope 'this' is used. 'ID' and 'md5' are set when a object is unpersisted. If 'forceSave' is set to TRUE the "md5 autodetect modification" is ignored. and storage write is forced. NOTE I: The $_persistTag-hash is part of the object we handle. (Not of $this). NOTE II: If no tag is found a default tag will be set. #### Tags:
return: | The $_persistTag-hash of *current* scope. (See text above)
see: | setScope()
access: | public
#### Parameters:
object | $object | The object to get the tag from.
[ Top ] ### method getScope [line 584]
`string. getScope( object &$object)`
(See header info: Scope) Get the scope; the area to store the data. NOTE: If the determined scope is the same as the scope currently used by the storage we return ''. A scope with value '' has the meaning to just use the current scope of the storage. #### Tags:
return: | The scope. If scope is not set OR same as storage scope, return ''.
access: | public
#### Parameters:
object | $object | The object to get the scope from.
[ Top ] ### method setHardScope [line 605]
`void setHardScope( object &$object, [string $scope = ''])`
(See header info: Scope) Set a 'strong'-scope. That is: the passed object will be stored with the given scope. For a SQL-dbs this would mean to *always* store this object in the same DB, using the scope as <db_Name>. NOTE: This is the scope with the highest priority. #### Tags:
see: | Bs_OoDbBasics::getPersistTag()
access: | public
#### Parameters:
object | $object | The object to set.
string | $scope | (see above)
[ Top ] ### method setID [line 569]
`void setID( mixed $ID, object &$object, [string $scope = ''])`
Set the objects sorage ID. NOTE: Every scope has it's own ID. But it's optional if you use current scope. #### Tags:
access: | public
#### Parameters:
object | $object | The object to set the ID to.
string | $scope | (opt, default:''). The scope to use.
[ Top ] ### method _getStreamFields [line 883]
`hash &_getStreamFields( [mixed $useCach = FALSE])`
I sometimes need all the streamNames from the PersistProperty #### Tags:
return: | with all the streamNames as keys.
access: | public
[ Top ] ### method _setError_Delete [line 951]
`void _setError_Delete( mixed $varName, mixed &$error, [mixed $type = 'error'])`
[ Top ] ### method _setError_Fetch [line 945]
`void _setError_Fetch( mixed $varName, mixed &$error, [mixed $type = 'error'])`
[ Top ] ### method _setError_Store [line 939]
`void _setError_Store( mixed $varName, mixed &$error, [mixed $type = 'error'])`
[ Top ] Documentation generated on Mon, 29 Dec 2003 21:12:27 +0100 by phpDocumentor 1.2.3