# Basic Saving

### Basic Updates

In addition to basic saving of entities and collections demonstrated below, more complex requirements can be catered for using [custom queries](https://docs.objectiphy.net/query-builder).

If you have loaded an entity using Objectiphy, and made some changes to its property values which you want to save, you can do so by calling the `saveEntity` method (which returns the number of records affected by the save):

```php
$person = $repository->find(123);
$person->lastName = 'McBoatface';
$recordsAffected = $repository->saveEntity($person);
```

By default, Objectiphy keeps track of changes to the entity and only saves the things that have changed. If it cannot determine whether a field has changed (eg. if the cache is cleared, or you load and populate the entity outside of Objectiphy), it will save it. If you set the **`DISABLE_ENTITY_CACHE`** [config option](https://docs.objectiphy.net/configuration-options#global-config-options) to true, this tracking will be disabled - meaning *all* properties will be saved.

If your entity has child objects, they will usually be saved when the parent entity is saved. If you don't want that to happen, you can either change the default behaviour via the **`SAVE_CHILDREN_BY_DEFAULT`** [config option](https://docs.objectiphy.net/configuration-options#global-config-options), or pass false to the second argument when calling the `saveEntity` method (this can provide performance improvements, as there will be no need to check whether any child objects need updating):

```php
$person = $repository->find(123);
$person->user->username = 'Something'; //Will not be saved
$person->lastName = 'McBoatface';
$repository->saveEntity($person, false);
```

### Basic Inserts

Similarly, you can insert a new entity by calling the same method:

```php
$person = new Person();
$person->firstName = 'Slartibartfast';
$repository->saveEntity($person);

return $person->id;
```

If the entity has a primary key (which you can specify by setting `isPrimaryKey` to true on the [column mapping](https://docs.objectiphy.net/annotations#column)), and is set to auto-increment in the database, Objectiphy will run an insert query and populate the primary key with the value assigned by the database.

If you want to generate your own primary key value, rather than auto-increment, you can either set the `autoIncrement` attribute to false on the [column mapping](https://docs.objectiphy.net/annotations#column) (this is the recommended approach as you can just set it and forget it), or set the third parameter to true when you call the `saveEntity` method. In that case, Objectiphy will perform an `INSERT ... ON DUPLICATE KEY UPDATE ...` query - which means that the entity will be inserted if it does not exist, or updated if it does:

```php
$person = new Person();
$person->employeeNumber = 'A1234'; //Primary key
$person->lastName = 'Skywalker';
$repository->saveEntity($person, true, true);
```

### Saving Relationships

If you add a new child object to an existing entity, calling `saveEntity` will typically insert the record for the new child object (as well as updating any other changed fields on the parent entity):

```php
$person = $repository->find(123);
$person->user = new User();
$person->user->username = 'User123';
$repository->saveEntity($person);

return $person->user->id; //Newly inserted user
```

There may be times when you want to associate an existing child object to a parent entity. If you have an instance of the child object to hand, you can just assign it to the property on the parent entity and save the parent entity. However, if you do not have an instance of the child object, just its primary key value, you can save the relationship without needing to load the child object from the database by creating an object reference:

```php
$person = $repository->find(123);
$user = $repository->getObjectReference(User::class, 321);
$person->user = $user;
$repository->saveEntity($person);

//User with primary key 321 is now associated with $person
```

You can delete a relationship simply by setting the property value to null and calling `saveEntity`:

```php
$person = $repository->find(123);
$person->user = null;
$repository->saveEntity($person);
```

The same principle applies when dealing with one-to-many associations - you can add or remove objects or object references and save the parent entity.

### Counting Records Affected

Where child objects are involved, saving an entity can result in records being both inserted and updated, or both updated and deleted. In this case, you can get the individual count of inserts, updates, and deletes, by passing variables by reference to the relevant arguments of the `saveEntity` method:

```php
$person = $repository->find(123);
$person->user = null;
$person->lastName = 'Smith';
$insertCount = 0;
$updateCount = 0;
$deleteCount = 0;
$totalCount = $repository->saveEntity(
    $person, 
    true, 
    false, 
    null, 
    $insertCount,
    $updateCount, 
    $deleteCount
);

//$insertCount = 0
//$updateCount = 1
//$deleteCount = 1
//$totalCount = 2
```

Note that these counts relate to database records, not entities. So in the above example, we are assuming that [orphan removal](https://docs.objectiphy.net/deleting#orphan-removal) is applied to the relationship between `Person` and `User`, and having set the user to null, this will have caused one update (the `user_id` on the `person` table updated to null), and one delete (the orphaned user record being deleted).

### Transactions

Inserts and updates are wrapped in transactions, so if you try to insert a parent entity, and there is a problem inserting one of the child entities, the whole operation will be aborted. Of course this will only work if the tables support transactions (so it will not work for MyISAM tables, for example).

You can also manage transactions yourself, for cases where you want to perform several operations in a single transaction. To do this, call `beginTransaction` on the repository, followed by either `commit` or `rollback`. If you have started your own transaction with `beginTransaction`, Objectiphy will not start any transactions of its own, and will not commit your transaction, so you are in complete control.

### Advanced Saving

You can perform more advanced save operations (eg. updating certain properties on multiple records that match certain criteria) using queries that you create with the [query builder](https://docs.objectiphy.net/query-builder).
