Introductions
Model
class inherits QueryExecuter
class (using delegation with the magic method). To understand the model, you need to understand QueryExecuter
class too.
Index
- Define models
- Export models
- Retrieving models
- Advanced model definition
- CachedQueryExecuter and Objects cache
- Using Custom collection
- Mixed method chain of Model and QueryExecuter
Define models
One model class corresponds to one table in the database. One model instance represents one row of the corresponding table.
Model name and table name, model property name and table field name are the same or converted with fixed rule. Transactd PHP ORM converts them with the rule similar to ActiveRecord of Ruby on Rails.
To define a model, inherit Model
class.
Define Customer
model
use Transactd\Model;
class Customer extends Model
{
}
Model name and table name
Transactd PHP ORM uses naming conventions rules like ActiverRecord. For table names,
- Make model names plural and lowercase.
Note: ActiverRecord requires snake_case
names, but Transactd PHP ORM does not support it. Transactd PHP ORM uses simplelowercase
names by default. You can specify the table name which does not follow the rules by static $table
.
use Transactd\Model;
class SalesSummary extends Model
{
protected static $table = 'sales_summary';
}
Property name and field name
The property name of the model is same as the field name of the table. Specify alias for static $aliases
if the name is not suitable. The original name will not be defined as the property.
class SalesSummary extends Model
{
protected static $table = 'sales_summary';
protected static $aliases = ['sales_amount' => 'salesAmount', 'tax_amount' => 'taxAmount'];
// 'salesAmount' and 'taxAmount' will be defined.
// 'sales_amount' or 'tax_amount' will not be.
}
Connection names
You can specify which connection to be used by each model with static $connection
.
use Transactd\Model;
class SalesSummary extends Model
{
protected static $table = 'sales_summary';
protected static $connection = 'Internal';
}
Export models
Transactd PHP ORM includes the PHP program MdlGen.php
which automatically generates models from the database. It generates @property
comments according to PHPDoc. You can use the property completion in the IDE.
MdlGen.php has following features:
- Specify directory and namespaces.
- Convert field names and generate
$ailas
automatically. - Convert table names and generate
$table
automatically. - Generate
@property
comments according to PHPDoc.
Usage
Execute from the command line as follows:
// On the directory where install by Composer
>php vendor/TransactdORMPHP-master/src/utility/MdlGen.php -slocalhost -dormtest -tcutomers
Results:
URI=tdap://localhost/ormtest
output = Customer.php
Generate done!
It generates one model at once. To generate multiple models, you are required to execute it for each table.
If it is executed without arguments, the description of the parameter will be displayed.
// On the directory where install by Composer
php vendor/TransactdORMPHP-master/src/utility/MdlGen.php
USAGE: php mdlgen.php -s[server] -d[database] -t[table] -u[userName] -p[password] -a[aliasList] -n[namespace] -o[output-directory]
-s : Name or ipaddress of a Transactd server.
-d : Database name.
-t : Table name of generate target.
-u : [optional] Username for server access.
-p : [optional] Password for server access.
-a : [optional] File name of alias list. (ini file format (key=value))
-n : [optional] Namespace of the target Model.
-o : [optional] Output directry name.(Include namespace)
Output directory and file names
The default output directory is where Composer has installed the libraries. If the namespace is specified, output directory is the directory with the same name as the namespace, under there. Namespace directories must be created in advance.
The file name is (MODEL NAME).php
.
Conversion dictionary of field and table names
You can specify a conversion dictionary file of field and table names with -a
option. The conversion dictionary is an ini format file in which source and destination are described with =
as follows. You can convert Japanese names. Save the file with utf8.
Example of the conversion dictionary:
customer_name=customerName
product_name=productName
得意先=customer
Example of generated code
<?php
use Transactd\Model;
/**
* Original table name:customers
*
* @property integer $id
* @property string $name
* @property string $update_at
*/
class Customer extends Model
{
}
Retrieving models
Retrieving all models
$customers = Customer::all();
Retrieving first model
If you do not specify index number, primary key will be used.
Retrieving first model by primary key
$customer = Customer::first();
Retrieving first model by index number 1
$customer = Customer::index(1)->first();
Retrieving single model
Find a customer id = 3
by primary key
$customer = Customer::find(3);
Find a customer name = 'John'
by name key
$nameKeyNum = 1;
$john = Customer::index($nameKeyNum)->find('John');
Find a customer by multiple segments (fields) key
$customer = Customer::index(2)->find([3, '1567-900-00']);
Retrieving multiple models
Find multiple records at once.
Find records id = 3
, id = 4
and id = 6
by primary key
$customers = Customer::findMany([3, 4, 6]);
Find records by multiple segments (fields) key
$customers = Customer::index(2)->findMany([[3, '1567-900-00'],[9, '1467-700-01']]);
Query multiple models
Like QueryExecuter
, you can search models with various conditions.
$customers = Customer::keyValue(0)->where('name', 'John')->noBreakReject()->get();
Just replace QueryExecuter
instance to the class name. Please see Query conditions.
Advanced model definition
Object-relational impedance mismatch
If the data handling areas are different between database and model, Transactd PHP ORM can transfer the values on database to another object.
For example, customers
table has customer's name and address. However, we want to manage the address with Address
object in address
property of Customer
.
Define transferring with static $transferMap
, 'field_name' => 'property_name_of_the_transfer_object'
.
class Address
{
}
class Customer extends Model
{
static protected $transferMap = ['zip' => 'address', 'city' => 'address', 'street' => 'address'];
public $address = null;
public function __construct()
{
parent::__construct();
$this->address = new Address(); // address must be created before transferring!
}
}
Then you can access to zip
property like bellow:
$customer = find(1);
if ($customer->address->zip === '390-0825') {
// (omitted)
}
Note: The object which receives the values must be created as a property value of the main object, before transferring. If the property is null, then the values will not be read or wrote.
Access modifiers
If you do not want to publish some members, make it to protected
.
Make note
property protected
class Customer extends Model
{
protected $note;
}
When loading models, if the setter method is defined, Transactd PHP ORM sets the value via it.
class Customer extends Model
{
protected $note;
public __set($name, $value)
{
if ($name === 'note') {
$this->note = trim($value); // The extension (php_tranasactd.[so|dll]) set value via this code.
}
}
}
When saving models, the getter method will not be used, even if it is defined. Transactd PHP ORM reads $note
directly, even if it is a protected member.
class Customer extends Model
{
protected $note;
public __get($name)
{
if ($name === 'note') {
return $this->note; // The extension (php_tranasactd.[so|dll]) does not use this code.
}
return parent::__get($name); // Call Model::__get (It is important for relationship opertions)
}
}
Access to a property that does not exist
An exception will be thrown when a property that does not exist in the model is read. This makes it easy to detect typos.
If the field which was not selected by select
is read, an exception will be thrown too.
$customer = Customer::keyValue(1)->select('id', 'name')->get();
echo $customer->phone; // Error !! \Exception will be thrown
However, the set of values is unconditionally possible.
$customer = new Customer();
// phone123 is not in field members.
$customer->phone123 = '0263-99-9999'; // OK!
CachedQueryExecuter and Objects cache
I wrote that the model inherits QueryExecuter
class. In exactly, it inherits CachedQueryExecuter
class. When Transactd PHP ORM reads objects, cached objects will be returned if it is in the cache. This cache reduces the number of accesses to the database.
The following methods add object(s) to the cache or update the cache:
first
,firstOrFail
,firstOrNew
,firstOrCreate
find
,findOrFail
,findMany
,refresh
update
,delete
,save
,create
,deleteObject
The following methods read from cache first:
find
,findOrFail
,findMany
, and Relation-ship methods.
Clear the cache of the Model
Clear all caches of Customer
.
Customer::clear();
Re-read a object and update the cache
$customer->refresh();
Using Custom collection
You can define custom collection.
Define custom collection
sample custom collection
class CCollection extends Transactd\Collection
{
public function __construct($array, $rel = null, $parent = null)
{
parent::__construct($array, $rel, $parent);
}
}
Using custom collection in ORM
Add newCollection
method that generates collection to model.
class Customer extends Model
{
public function newCollection($ar, $rel, $parent)
{
return new CCollection($ar, $rel, $parent);
}
}
Mixed method chain of Model and QueryExecuter
The methods which are prefixed with scope
in model can be called by QueryExecuter
instance.
Define method
scope
prefixed methods receive and return a QueryExecuter
instance.
class Customer extends Model
{
public function scopeInJapan($query) {
return $query->where('country', 'japan');
}
}
Using mixed method chain
To call the method, remove prefix scope
from its name. QueryExecuter
finds and calls the method which has scope
+ method name in the model.
$customer = Customer::keyValue(1)->where('id', '<', 11)->inJapan()->get();