Join a member of a collection or array of child entities to a parent entity.
This is the opposite of a one-to-many relationship, so is basically a one-to-many relationship as seen from the point of view of the child object. The entity holding the many-to-one relationship points to a single other entity (its parent), but it will be held in an array or collection along with siblings of the same type as itself.
As the entity holding the many-to-one relationship only points to a single parent object, as far as Objectiphy is concerned, it is treated almost identically to a one-to-one relationship, and is defined in the same way - only the relationship type is different. The only difference in behaviour between many-to-one and one-to-one is when deleting data - ie. if orphan removal is enabled, it will check to make sure the object with a many-to-one relationship is not owned by any other parents before deleting it. Also, cascade deletes is not allowed on many-to-one relationships, as by definition, the child could belong to more than one parent. See the page on deleting for more information about that.
For example, suppose we have a Customer entity and an Order entity, and a customer can have multiple orders. The Order entity has a many-to-one relationship with Customer. The code for these entities looks like this:
classCustomer{publicint $id;publicstring $name;publicarray $orders = []; // <--One to Many}// Note: Each class would of course normally be// in a separate file.classOrder{publicint $id;publicCustomer $customer; // <--Many to one//... more properties}
We store the values of the properties for these entities in two database tables, named customer and order:
customer
id
name
order
id
customer_id<-- Foreign key
...more columns
The order table contains a foreign key column named customer_id which holds the primary key value of the customer table. We have no choice over which side owns the relationship - only the order table can have a the foreign key, because a customer can have multiple orders, and we can't store multiple foreign keys in a single column.
Examples
Here are two examples of how to set up the mapping for a many-to-one relationship using attributes or annotations (these examples are all equivalent; you only need to use one type of mapping provider, it is up to you which one).
As with one-to-one, note that the sourceJoinColumn attribute (or @ORM\JoinColumn annotation if using Doctrine annotations) exists on the owning side (Order), and the other side (Customer) has a mappedBy attribute, telling Objectiphy where to look for the join column. The value of mappedBy must be a property name, not a column name!
Example 1: Minimal Mapping
The following example shows the bare minimum mapping information necessary, on the assumption that the foreign key in the owning table is the primary key of the owned table and that a left join is sufficient. If you are using non-standard columns, or require an inner join, you will need to define them in full as shown in example 2 (note, if using Doctrine annotations, you cannot specify the join type with an annotation).
useObjectiphy\Objectiphy\Table;useObjectiphy\Objectiphy\Column;useObjectiphy\Objectiphy\Relationship;#[Table(name:'customer')]classCustomer{ #[Column(isPrimaryKey:true)]publicint $id; #[Column]publicstring $name; #[Relationship( relationshipType:'one_to_many', childClassName:Order::class, mappedBy:'customer')]publicarray $orders = [];}// Note: Each class would of course normally be// in a separate file.#[Table(name:'order')]classOrder{ #[Column(isPrimaryKey:true)]publicint $id; #[Relationship( relationshipType:'many_to_one', childClassName:Customer::class)]publicCustomer $customer;//... more properties}
useObjectiphy\Objectiphy\Table;useObjectiphy\Objectiphy\Column;useObjectiphy\Objectiphy\Relationship;/** * @Table(name="customer") */classCustomer{/** * @Column(isPrimaryKey=true) */publicint $id;/** * @Column */publicstring $name;/** * @Relationship( * relationshipType="one_to_many" * childClassName="Order", * mappedBy="customer" * ) */publicarray $orders = [];}// Note: Each class would of course normally be// in a separate file./** * @Table(name="order") */classOrder{/** * @Column(isPrimaryKey=true) */publicint $id;/** * @Relationship( * relationshipType="many_to_one", * childClassName="Customer" * ) */publicCustomer $customer;//... more properties}
useDoctrine\ORM\Mappingas ORM;/** * @ORM\Table(name="customer") */classCustomer{/** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */publicint $id;/** * @ORM\Column() */publicstring $name;/** * @ORM\OneToMany( * targetEntity="Order", * mappedBy="customer" * ) */publicarray $orders = [];}// Note: Each class would of course normally be// in a separate file./** * @ORM\Table(name="order") */classOrder{/** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */publicint $id;/** * @ORM\ManyToOne(targetEntity="Customer") */publicCustomer $customer;//... more properties}
Example 2: Full Mapping
The following example shows all of the mapping information defined, even though some items could be omitted as Objectiphy can guess some of the mapping if it follows standard conventions. You only need to specify all of the mapping information if you are not joining in a standard way from foreign key to primary key, if your foreign key column name is not suffixed with 'id', or the primary key of the target table, or if you need an inner join (note, if using Doctrine annotations, you cannot specify the join type with an annotation). Example 1, above, shows the exact same mapping as this in an abbreviated format.
useObjectiphy\Objectiphy\Table;useObjectiphy\Objectiphy\Column;useObjectiphy\Objectiphy\Relationship;#[Table(name:'customer')]classCustomer{ #[Column(isPrimaryKey:true)]publicint $id; #[Column]publicstring $name; #[Relationship( relationshipType:'one_to_many', childClassName:Order::class, mappedBy:'customer')]publicarray $orders = [];}// Note: Each class would of course normally be// in a separate file.#[Table(name:'order')]classOrder{ #[Column(isPrimaryKey:true)]publicint $id; #[Relationship( relationshipType:'many_to_one', childClassName:Customer::class, sourceJoinColumn:'customer_id', targetJoinColumn:'id', joinType:'INNER')]publicCustomer $customer;//... more properties}
useObjectiphy\Objectiphy\Table;useObjectiphy\Objectiphy\Column;useObjectiphy\Objectiphy\Relationship;/** * @Table(name="customer") */classCustomer{/** * @Column(isPrimaryKey=true) */publicint $id;/** * @Column */publicstring $name;/** * @Relationship( * relationshipType="one_to_many", * childClassName="Order", * mappedBy="customer" * ) */publicarray $orders = [];}// Note: Each class would of course normally be// in a separate file./** * @Table(name="order") */classOrder{/** * @Column(isPrimaryKey=true) */publicint $id;/** * @Relationship( * relationshipType="many_to_one", * childClassName="Customer", * sourceJoinColumn="customer_id", * targetJoinColumn="id", * joinType="INNER" * ) */publicCustomer $customer;//... more properties}
useDoctrine\ORM\Mappingas ORM;/** * @ORM\Table(name="customer") */classCustomer{/** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */publicint $id;/** * @ORM\Column() */publicstring $name;/** * @ORM\OneToMany( * targetEntity="Order", * mappedBy="customer" * ) */publicarray $orders = [];}// Note: Each class would of course normally be// in a separate file./** * @ORM\Table(name="order") */classOrder{/** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */publicint $id;/** * @ORM\ManyToOne(targetEntity="Customer") * @ORM\JoinColumn( * name="customer_id", * referencedColumnName="id" * ) */publicCustomer $customer;//... more properties}