ORM¶
Note
if you want to automatically generate the models, consult the generating models part.
A model class is just a plain old php object without inheritance.
Models are located by default in the app\models folder.
Object Relational Mapping (ORM) relies on member annotations or attributes (since PHP8) in the model class.
Models definition¶
A basic model¶
- A model must define its primary key using the @id annotation on the members concerned
- Serialized members must have getters and setters
- Without any other annotation, a class corresponds to a table with the same name in the database, each member corresponds to a field of this table
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | namespace models;
use Ubiquity\attributes\items\Id;
class User{
#[Id]
private $id;
private $firstname;
public function getFirstname(){
return $this->firstname;
}
public function setFirstname($firstname){
$this->firstname=$firstname;
}
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | namespace models;
class User{
/**
* @id
*/
private $id;
private $firstname;
public function getFirstname(){
return $this->firstname;
}
public function setFirstname($firstname){
$this->firstname=$firstname;
}
}
|
Mapping¶
Table->Class¶
If the name of the table is different from the name of the class, the annotation @table allows to specify the name of the table.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | namespace models;
use Ubiquity\attributes\items\Table;
use Ubiquity\attributes\items\Id;
#[Table('user')]
class User{
#[Id]
private $id;
private $firstname;
public function getFirstname(){
return $this->firstname;
}
public function setFirstname($firstname){
$this->firstname=$firstname;
}
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | namespace models;
/**
* @table("name"=>"user")
*/
class User{
/**
* @id
*/
private $id;
private $firstname;
public function getFirstname(){
return $this->firstname;
}
public function setFirstname($firstname){
$this->firstname=$firstname;
}
}
|
Field->Member¶
If the name of a field is different from the name of a member in the class, the annotation @column allows to specify a different field name.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | namespace models;
use Ubiquity\attributes\items\Table;
use Ubiquity\attributes\items\Id;
use Ubiquity\attributes\items\Column;
#[Table('user')
class User{
#[Id]
private $id;
#[Column('column_name')]
private $firstname;
public function getFirstname(){
return $this->firstname;
}
public function setFirstname($firstname){
$this->firstname=$firstname;
}
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | namespace models;
/**
* @table("user")
*/
class User{
/**
* @id
*/
private $id;
/**
* column("user_name")
*/
private $firstname;
public function getFirstname(){
return $this->firstname;
}
public function setFirstname($firstname){
$this->firstname=$firstname;
}
}
|
Associations¶
Note
Naming convention
Foreign key field names consist of the primary key name of the referenced table followed by the name of the referenced table whose first letter is capitalized.
Example
idUser
for the table user
whose primary key is id
ManyToOne¶
A user belongs to an organization:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | namespace models;
use Ubiquity\attributes\items\ManyToOne;
use Ubiquity\attributes\items\Id;
use Ubiquity\attributes\items\JoinColumn;
class User{
#[Id]
private $id;
private $firstname;
#[ManyToOne]
#[JoinColumn(className: \models\Organization::class, name: 'idOrganization', nullable: false)]
private $organization;
public function getOrganization(){
return $this->organization;
}
public function setOrganization($organization){
$this->organization=$organization;
}
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | namespace models;
class User{
/**
* @id
*/
private $id;
private $firstname;
/**
* @manyToOne
* @joinColumn("className"=>"models\\Organization","name"=>"idOrganization","nullable"=>false)
*/
private $organization;
public function getOrganization(){
return $this->organization;
}
public function setOrganization($organization){
$this->organization=$organization;
}
}
|
The @joinColumn annotation or the JoinColumn attribute specifies that:
- The member $organization is an instance of modelsOrganization
- The table user has a foreign key idOrganization refering to organization primary key
- This foreign key is not null => a user will always have an organization
OneToMany¶
An organization has many users:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | namespace models;
use Ubiquity\attributes\items\OneToMany;
use Ubiquity\attributes\items\Id;
class Organization{
#[Id]
private $id;
private $name;
#[OneToMany(mappedBy: 'organization', className: \models\User::class)]
private $users;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | namespace models;
class Organization{
/**
* @id
*/
private $id;
private $name;
/**
* @oneToMany("mappedBy"=>"organization","className"=>"models\\User")
*/
private $users;
}
|
In this case, the association is bi-directional.
The @oneToMany annotation must just specify:
- The class of each user in users array : modelsUser
- the value of @mappedBy is the name of the association-mapping attribute on the owning side : $organization in User class
ManyToMany¶
- A user can belong to groups.
- A group consists of multiple users.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | namespace models;
use Ubiquity\attributes\items\ManyToMany;
use Ubiquity\attributes\items\Id;
use Ubiquity\attributes\items\JoinTable;
class User{
#[Id]
private $id;
private $firstname;
#[ManyToMany(targetEntity: \models\Group::class, inversedBy: 'users')]
#[JoinTable(name: 'groupusers')]
private $groups;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | namespace models;
class User{
/**
* @id
*/
private $id;
private $firstname;
/**
* @manyToMany("targetEntity"=>"models\\Group","inversedBy"=>"users")
* @joinTable("name"=>"groupusers")
*/
private $groups;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | namespace models;
use Ubiquity\attributes\items\ManyToMany;
use Ubiquity\attributes\items\Id;
use Ubiquity\attributes\items\JoinTable;
class Group{
#[Id]
private $id;
private $name;
#[ManyToMany(targetEntity: \models\User::class, inversedBy: 'groups')]
#[JoinTable(name: 'groupusers')]
private $users;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | namespace models;
class Group{
/**
* @id
*/
private $id;
private $name;
/**
* @manyToMany("targetEntity"=>"models\\User","inversedBy"=>"groups")
* @joinTable("name"=>"groupusers")
*/
private $users;
}
|
If the naming conventions are not respected for foreign keys,
it is possible to specify the related fields.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | namespace models;
use Ubiquity\attributes\items\ManyToMany;
use Ubiquity\attributes\items\Id;
use Ubiquity\attributes\items\JoinTable;
class Group{
#[Id]
private $id;
private $name;
#[ManyToMany(targetEntity: \models\User::class, inversedBy: 'groupes')]
#[JoinTable(name: 'groupeusers',
joinColumns: ['name'=>'id_groupe','referencedColumnName'=>'id'],
inverseJoinColumns: ['name'=>'id_user','referencedColumnName'=>'id'])]
private $users;
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | namespace models;
class Group{
/**
* @id
*/
private $id;
private $name;
/**
* @manyToMany("targetEntity"=>"models\\User","inversedBy"=>"groupes")
* @joinTable("name"=>"groupeusers",
* "joinColumns"=>["name"=>"id_groupe","referencedColumnName"=>"id"],
* "inverseJoinColumns"=>["name"=>"id_user","referencedColumnName"=>"id"])
*/
private $users;
}
|
ORM Annotations¶
Annotations for classes¶
@annotation | role | properties | role |
---|---|---|---|
@database | Defines the associated database offset (defined in config file) | ||
@table | Defines the associated table name. |
Annotations for members¶
@annotation | role | properties | role |
---|---|---|---|
@id | Defines the primary key(s). | ||
@column | Specify the associated field characteristics. | name | Name of the associated field |
nullable | true if value can be null | ||
dbType | Type of the field in database | ||
@transient | Specify that the field is not persistent. |
Associations¶
@annotation (extends) | role | properties [optional] | role |
---|---|---|---|
@manyToOne | Defines a single-valued association to another entity class. | ||
@joinColumn (@column) | Indicates the foreign key in manyToOne asso. | className | Class of the member |
[referencedColumnName] | Name of the associated column | ||
@oneToMany | Defines a multi-valued association to another entity class. | className | Class of the objects in member |
[mappedBy] | Name of the association-mapping attribute on the owning side | ||
@manyToMany | Defines a many-valued association with many-to-many multiplicity | targetEntity | Class of the objects in member |
[inversedBy] | Name of the association-member on the inverse-side | ||
[mappedBy] | Name of the association-member on the owning side | ||
@joinTable | Defines the association table for many-to-many multiplicity | name | The name of the association table |
[joinColumns] | @column => name and referencedColumnName for this side | ||
[inverseJoinColumns] | @column => name and referencedColumnName for the other side |