Silverstripe - Better way to delete Dataobjects instead of using custom sql querys

StackOverflow https://stackoverflow.com/questions/22385603

  •  14-06-2023
  •  | 
  •  

Вопрос

Is there a better way deleting dataobject older than x-days instead of using custom sql queries?

that's what I do now

    $host = 'localhost';
    $username = 'db123';
    $password = 'pass';
    $db_name = 'db123';

    mysql_connect("$host", "$username", "$password")or die("cannot connect"); 
    mysql_select_db("$db_name")or die("cannot select DB");

    $sql = "DELETE FROM Cart WHERE Created < (CURDATE() - INTERVAL 1 DAY)";
    $result = mysql_query($sql);

    mysql_close();
Это было полезно?

Решение

first of all, using mysql_query is bad, not just in this case. mysql_query has been deprecated and should no longer be used.

secondly, SilverStripe already has a DB connect, do not attempt to create another one. SilverStripe offers many ways to query the database.


Option 1:

the cleanest way of course is to use the SilverStripe ORM.
A DataObject has a method called ->delete().
Using delete has several advantages over writing your own SQL query.

  • its easy
  • it will delete the DataObject from all its tables for you (eg the DataObject class Folder is a subclass of File, so if you do $myFolder->delete() it will go and delete this Folder in the File Table but also in the Folder Table (if there is a Folder table))
  • it will execute the SilverStripe delete hooks (onBeforeDelete and onAfterDelete)

its pretty straight forward:

// to delete all `DataObject`s in a List, just loop it and call ->delete()
foreach($list as $item) { 
    $item->delete();
}

// there also is a method that does that for you, however, I would advise against it
// because it is currently inconsistently implemented and might lead to unexpected results
// $list->removeAll(); // i STRONGLY RECOMMEND AGAINST THIS
// if $list is a DataList, it will delete all records
// if $list is a ManyManyList, it will unlink all records
// if $list is a ArrayList, it will error because there is no removeAll() method on ArrayList

to solve your problem:

$date = date('Y-m-d H:i:s', strtotime("now -1 day"));

$list = Cart::get()->filter('Created:LessThan', $date);

foreach($list as $item) { 
    $item->delete();
}

it however has also a major disadvantage when deleting many DataObjects: performance.
I will however still recommend using ->delete() if you can say that performance is not a huge problem. The benefits usually outweigh the drawbacks.

Read more about DataList, ::get(), ->filter() and ->delete() in the SilverStripe docs for Datamodel / ORM and DataObject


Option 2:

if you however really need to, it is possible to use a lower level of the ORM to perform the delete:

$query = new SQLQuery();
$query->setDelete(true);
$query->setFrom('Cart');
$query->setWhere('Created  < (CURDATE() - INTERVAL 1 DAY)"');
// if you want to debug the query, you can use ->sql() to get it as string
// echo $query->sql();
$query->execute();

Read more about SQLQuery in the SilverStripe docs


Option 3:

if you for some reason really want to avoid the ORM at all, SilverStripe also lets you execute raw SQL queries:

 DB::query("DELETE FROM Cart WHERE Created < (CURDATE() - INTERVAL 1 DAY)");
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top