diff --git a/system/Model.php b/system/Model.php
index e2a9ef55720e..821c512ecb79 100644
--- a/system/Model.php
+++ b/system/Model.php
@@ -120,7 +120,7 @@ class Model
/**
* If this model should use "softDeletes" and
- * simply set a flag when rows are deleted, or
+ * simply set a date when rows are deleted, or
* do hard deletes.
*
* @var boolean
@@ -182,7 +182,7 @@ class Model
*
* @var string
*/
- protected $deletedField = 'deleted';
+ protected $deletedField = 'deleted_at';
/**
* Used by asArray and asObject to provide
@@ -356,7 +356,7 @@ public function find($id = null)
if ($this->tempUseSoftDeletes === true)
{
- $builder->where($this->table . '.' . $this->deletedField, 0);
+ $builder->where($this->table . '.' . $this->deletedField, null);
}
if (is_array($id))
@@ -427,7 +427,7 @@ public function findAll(int $limit = 0, int $offset = 0)
if ($this->tempUseSoftDeletes === true)
{
- $builder->where($this->table . '.' . $this->deletedField, 0);
+ $builder->where($this->table . '.' . $this->deletedField, null);
}
$row = $builder->limit($limit, $offset)
@@ -457,7 +457,7 @@ public function first()
if ($this->tempUseSoftDeletes === true)
{
- $builder->where($this->table . '.' . $this->deletedField, 0);
+ $builder->where($this->table . '.' . $this->deletedField, null);
}
// Some databases, like PostgreSQL, need order
@@ -912,7 +912,7 @@ public function delete($id = null, bool $purge = false)
if ($this->useSoftDeletes && ! $purge)
{
- $set[$this->deletedField] = 1;
+ $set[$this->deletedField] = $this->setDate();
if ($this->useTimestamps && ! empty($this->updatedField))
{
@@ -947,8 +947,8 @@ public function purgeDeleted()
}
return $this->builder()
- ->where($this->deletedField, 1)
- ->delete();
+ ->where($this->table . '.' . $this->deletedField . ' IS NOT NULL')
+ ->delete();
}
//--------------------------------------------------------------------
@@ -981,7 +981,7 @@ public function onlyDeleted()
$this->tempUseSoftDeletes = false;
$this->builder()
- ->where($this->deletedField, 1);
+ ->where($this->table . '.' . $this->deletedField . ' IS NOT NULL');
return $this;
}
@@ -1543,7 +1543,7 @@ public function countAllResults(bool $reset = true, bool $test = false)
{
if ($this->tempUseSoftDeletes === true)
{
- $this->builder()->where($this->deletedField, 0);
+ $this->builder()->where($this->table . '.' . $this->deletedField, null);
}
return $this->builder()->countAllResults($reset, $test);
diff --git a/tests/_support/Database/Migrations/20160428212500_Create_test_tables.php b/tests/_support/Database/Migrations/20160428212500_Create_test_tables.php
index f3e5842ffa8f..b980a80acfbc 100644
--- a/tests/_support/Database/Migrations/20160428212500_Create_test_tables.php
+++ b/tests/_support/Database/Migrations/20160428212500_Create_test_tables.php
@@ -26,11 +26,6 @@ public function up()
'type' => 'VARCHAR',
'constraint' => 40,
],
- 'deleted' => [
- 'type' => 'TINYINT',
- 'constraint' => 1,
- 'default' => '0',
- ],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
@@ -39,6 +34,10 @@ public function up()
'type' => 'DATETIME',
'null' => true,
],
+ 'deleted_at' => [
+ 'type' => 'DATETIME',
+ 'null' => true,
+ ],
]);
$this->forge->addKey('id', true);
$this->forge->createTable('user', true);
@@ -58,11 +57,6 @@ public function up()
'type' => 'TEXT',
'null' => true,
],
- 'deleted' => [
- 'type' => 'TINYINT',
- 'constraint' => 1,
- 'default' => '0',
- ],
'created_at' => [
'type' => 'INTEGER',
'constraint' => 11,
@@ -73,6 +67,11 @@ public function up()
'constraint' => 11,
'null' => true,
],
+ 'deleted_at' => [
+ 'type' => 'INTEGER',
+ 'constraint' => 11,
+ 'null' => true,
+ ],
]);
$this->forge->addKey('id', true);
$this->forge->createTable('job', true);
diff --git a/tests/_support/Models/EntityModel.php b/tests/_support/Models/EntityModel.php
index 4460242330bf..46abfa59c43e 100644
--- a/tests/_support/Models/EntityModel.php
+++ b/tests/_support/Models/EntityModel.php
@@ -12,7 +12,7 @@ class EntityModel extends Model
protected $dateFormat = 'int';
- protected $deletedField = 'deleted';
+ protected $deletedField = 'deleted_at';
protected $allowedFields = [
'name',
diff --git a/tests/_support/Models/EventModel.php b/tests/_support/Models/EventModel.php
index e9df2ecd6166..ed3312424d41 100644
--- a/tests/_support/Models/EventModel.php
+++ b/tests/_support/Models/EventModel.php
@@ -16,7 +16,7 @@ class EventModel extends Model
'name',
'email',
'country',
- 'deleted',
+ 'deleted_at',
];
protected $beforeInsert = ['beforeInsertMethod'];
diff --git a/tests/_support/Models/UserModel.php b/tests/_support/Models/UserModel.php
index 05018820f380..7be6d889ccca 100644
--- a/tests/_support/Models/UserModel.php
+++ b/tests/_support/Models/UserModel.php
@@ -10,7 +10,7 @@ class UserModel extends Model
'name',
'email',
'country',
- 'deleted',
+ 'deleted_at',
];
protected $returnType = 'object';
diff --git a/tests/system/Database/Live/DbUtilsTest.php b/tests/system/Database/Live/DbUtilsTest.php
index f355d94084d3..906e7c7809b2 100644
--- a/tests/system/Database/Live/DbUtilsTest.php
+++ b/tests/system/Database/Live/DbUtilsTest.php
@@ -188,7 +188,7 @@ public function testUtilsCSVFromResult()
$data = array_filter(preg_split('/(\r\n|\n|\r)/', $data));
- $this->assertEquals('"1","Developer","Awesome job, but sometimes makes you bored","0","",""', $data[1]);
+ $this->assertEquals('"1","Developer","Awesome job, but sometimes makes you bored","","",""', $data[1]);
}
//--------------------------------------------------------------------
@@ -203,7 +203,7 @@ public function testUtilsXMLFromResult()
$data = $util->getXMLFromResult($data);
- $expected = '4MusicianOnly Coldplay can actually called Musician';
+ $expected = '4MusicianOnly Coldplay can actually called Musician';
$actual = preg_replace('#\R+#', '', $data);
$actual = preg_replace('/[ ]{2,}|[\t]/', '', $actual);
diff --git a/tests/system/Database/Live/ModelTest.php b/tests/system/Database/Live/ModelTest.php
index b29b5b381762..b3ec505751a0 100644
--- a/tests/system/Database/Live/ModelTest.php
+++ b/tests/system/Database/Live/ModelTest.php
@@ -143,7 +143,7 @@ public function testFindRespectsSoftDeletes()
{
$this->db->table('user')
->where('id', 4)
- ->update(['deleted' => 1]);
+ ->update(['deleted_at' => date('Y-m-d H:i:s')]);
$model = new UserModel($this->db);
@@ -219,7 +219,7 @@ public function testFindAllRespectsSoftDeletes()
{
$this->db->table('user')
->where('id', 4)
- ->update(['deleted' => 1]);
+ ->update(['deleted_at' => date('Y-m-d H:i:s')]);
$model = new UserModel($this->db);
@@ -254,7 +254,7 @@ public function testFirstRespectsSoftDeletes()
{
$this->db->table('user')
->where('id', 1)
- ->update(['deleted' => 1]);
+ ->update(['deleted_at' => date('Y-m-d H:i:s')]);
$model = new UserModel();
@@ -403,11 +403,11 @@ public function testDeleteWithSoftDeletes()
{
$model = new UserModel();
- $this->seeInDatabase('user', ['name' => 'Derek Jones', 'deleted' => 0]);
+ $this->seeInDatabase('user', ['name' => 'Derek Jones', 'deleted_at IS NULL' => null]);
$model->delete(1);
- $this->seeInDatabase('user', ['name' => 'Derek Jones', 'deleted' => 1]);
+ $this->seeInDatabase('user', ['name' => 'Derek Jones', 'deleted_at IS NOT NULL' => null]);
}
//--------------------------------------------------------------------
@@ -416,7 +416,7 @@ public function testDeleteWithSoftDeletesPurge()
{
$model = new UserModel();
- $this->seeInDatabase('user', ['name' => 'Derek Jones', 'deleted' => 0]);
+ $this->seeInDatabase('user', ['name' => 'Derek Jones', 'deleted_at IS NULL' => null]);
$model->delete(1, true);
@@ -461,7 +461,7 @@ public function testPurgeDeleted()
$this->db->table('user')
->where('id', 1)
- ->update(['deleted' => 1]);
+ ->update(['deleted_at' => date('Y-m-d H:i:s')]);
$model->purgeDeleted();
@@ -479,7 +479,7 @@ public function testOnlyDeleted()
$this->db->table('user')
->where('id', 1)
- ->update(['deleted' => 1]);
+ ->update(['deleted_at' => date('Y-m-d H:i:s')]);
$users = $model->onlyDeleted()
->findAll();
@@ -757,7 +757,6 @@ public function testPasswordsStoreCorrectly()
'name' => $pass,
'email' => 'foo@example.com',
'country' => 'US',
- 'deleted' => 0,
];
$model->insert($data);
@@ -1403,7 +1402,7 @@ public function testDeleteWithSoftDelete()
$model->delete(1);
- $this->seeInDatabase('job', ['id' => 1, 'deleted' => 1]);
+ $this->seeInDatabase('job', ['id' => 1, 'deleted_at IS NOT NULL' => null]);
}
//--------------------------------------------------------------------
@@ -1414,7 +1413,7 @@ public function testPurgeDeletedWithSoftDeleteFalse()
$this->db->table('job')
->where('id', 1)
- ->update(['deleted' => 1]);
+ ->update(['deleted_at' => time()]);
$model->purgeDeleted();
@@ -1629,7 +1628,7 @@ public function testSoftDeleteWithTableJoinsFindAll()
{
$model = new UserModel();
- $this->seeInDatabase('user', ['name' => 'Derek Jones', 'deleted' => 0]);
+ $this->seeInDatabase('user', ['name' => 'Derek Jones', 'deleted_at' => null]);
$results = $model->join('job', 'job.id = user.id')
->findAll();
@@ -1645,7 +1644,7 @@ public function testSoftDeleteWithTableJoinsFind()
{
$model = new UserModel();
- $this->seeInDatabase('user', ['name' => 'Derek Jones', 'deleted' => 0]);
+ $this->seeInDatabase('user', ['name' => 'Derek Jones', 'deleted_at' => null]);
$results = $model->join('job', 'job.id = user.id')
->find(1);
@@ -1661,7 +1660,7 @@ public function testSoftDeleteWithTableJoinsFirst()
{
$model = new UserModel();
- $this->seeInDatabase('user', ['name' => 'Derek Jones', 'deleted' => 0]);
+ $this->seeInDatabase('user', ['name' => 'Derek Jones', 'deleted_at' => null]);
$results = $model->join('job', 'job.id = user.id')
->first(1);
diff --git a/user_guide_src/source/models/model.rst b/user_guide_src/source/models/model.rst
index 3d7ee2b4e91d..70b78e837543 100644
--- a/user_guide_src/source/models/model.rst
+++ b/user_guide_src/source/models/model.rst
@@ -106,6 +106,7 @@ what table to use and how we can find the required records::
protected $useTimestamps = false;
protected $createdField = 'created_at';
protected $updatedField = 'updated_at';
+ protected $deletedField = 'deleted_at';
protected $validationRules = [];
protected $validationMessages = [];
@@ -137,13 +138,15 @@ method.
**$useSoftDeletes**
-If true, then any delete* method calls will simply set a flag in the database, instead of
+If true, then any delete* method calls will set ``deleted_at`` in the database, instead of
actually deleting the row. This can preserve data when it might be referenced elsewhere, or
can maintain a "recycle bin" of objects that can be restored, or even simply preserve it as
part of a security trail. If true, the find* methods will only return non-deleted rows, unless
the withDeleted() method is called prior to calling the find* method.
-This requires an INT or TINYINT field to be present in the table for storing state. The default field name is ``deleted`` however this name can be configured to any name of your choice by using $deletedField property.
+This requires either a DATETIME or INTEGER field in the database as per the model's
+$dateFormat setting. The default field name is ``deleted_at`` however this name can be
+configured to any name of your choice by using $deletedField property.
**$allowedFields**
@@ -262,8 +265,8 @@ Returns the first row in the result set. This is best used in combination with t
**withDeleted()**
-If $useSoftDeletes is true, then the find* methods will not return any rows where 'deleted = 1'. To
-temporarily override this, you can use the withDeleted() method prior to calling the find* method.
+If $useSoftDeletes is true, then the find* methods will not return any rows where 'deleted_at IS NOT NULL'.
+To temporarily override this, you can use the withDeleted() method prior to calling the find* method.
::
// Only gets non-deleted rows (deleted = 0)
@@ -421,8 +424,8 @@ Takes a primary key value as the first parameter and deletes the matching record
$userModel->delete(12);
-If the model's $useSoftDeletes value is true, this will update the row to set 'deleted = 1'. You can force
-a permanent delete by setting the second parameter as true.
+If the model's $useSoftDeletes value is true, this will update the row to set ``deleted_at`` to the current
+date and time. You can force a permanent delete by setting the second parameter as true.
An array of primary keys can be passed in as the first parameter to delete multiple records at once::
@@ -435,7 +438,7 @@ previously::
**purgeDeleted()**
-Cleans out the database table by permanently removing all rows that have 'deleted = 1'. ::
+Cleans out the database table by permanently removing all rows that have 'deleted_at IS NOT NULL'. ::
$userModel->purgeDeleted();
diff --git a/user_guide_src/source/testing/database.rst b/user_guide_src/source/testing/database.rst
index 5001aa6108c0..8edfb5089f6a 100644
--- a/user_guide_src/source/testing/database.rst
+++ b/user_guide_src/source/testing/database.rst
@@ -157,7 +157,7 @@ Asserts that a number of matching rows are found in the database that match ``$c
::
$criteria = [
- 'deleted' => 1
+ 'active' => 1
];
$this->seeNumRecords(2, 'users', $criteria);