1

(TYPO3 v11)

There is a table of events. Each event has a datetime_end field and a days_until_deletionfield. A scheduler script should delete old events automatically.

In SQL this works:

UPDATE `tx_myevents_domain_model_event` SET deleted = 1 
WHERE UNIX_TIMESTAMP() > (datetime_end + (days_until_deletion * 86400));

Is there a way to reproduce this SQL statement with the querybuilder? Something like:

$queryBuilder->where(
    $queryBuilder->expr()->lt( ('datetime_end' + ('days_until_deletion' * 86400)), time()
)

3 Answers 3

2

This here should work - note that Doctrine DBAL doesn't support arithmetic expressions, but does allow to pass raw WHERE SQL statements. You'll need to ensure yourself the SQL you write is compatible to your target SQL systems (for example PostgreSQL has no "UNIX_TIMESTAMP()" function)

$queryBuilder->update('tx_myevents_domain_model_event')
   ->set('deleted', 1)
   ->where('UNIX_TIMESTAMP() > (datetime_end + (days_until_deletion * 86400))');
$queryBuilder->executeStatement();
Sign up to request clarification or add additional context in comments.

2 Comments

Good to know. For me, it is cleaner to have this SQL code "encapsulated" with the add function. If problems arise in the future according to change of database systems, it is easier to find.
add() is dropped by doctrine dbal in newer versions. Unrelated to the used technique, even with plain concentated string and Connection->executeStatement()` you have your method/place using the database call covered with functional tests - right ? And switching the db version/vendor would reveal issues witht the tests already before deployment. Beide that, not getting why add() should encapsulate anything.
1

I found a way which maybe is useful for anybody.

  1. As I want to change the deleted field, restrictions have to be removed:

  2. To handle complicated SQL situations the add() function is appropriate.

Thus, this code works:

$queryBuilder = $this->connectionPool->getQueryBuilderForTable(tx_myevents_domain_model_event);
$queryBuilder
    ->getRestrictions()
    ->removeAll();
$queryBuilder
    ->update(tx_myevents_domain_model_event)
    ->add( 'where', '(datetime_end + (days_until_deletion * 86400)) < UNIX_TIMESTAMP()')
    ->set('deleted', '1');

4 Comments

Based on our experience, I recommend a different approach. Delete the data records via TYPO3 functions. Advantages: - TYPO3 sets timestamps, user (CLI) - TYPO3 resolves dependencies, for example to files (sys_file_reference)
Can you give an example or a hint for what you call TYPO3 functions?
add() should not be used, and vanish in newer Doctrine DBAL / TYPO3 version anyway. The correct api to use are where(), andWhere() and orWhere(). All the example omit proper quiting ... and I would resort using sprintf() here and have at least the fieldnames with placeholders and set as sprintf values using $queryBuilder->quoteIdentifier('datetime_end') for example. As already mentioned, i's better to use DataHandler cmdMap for delete a record, which keeps track of that in the history (audit) and automatically checks for soft-delete/hard delete depending on table/tca support.
This issue is not forgotten. I will return to it as soon as possible.
0
You can use this function, for example.


/** @var DataHandler $dataHandler */
$dataHandler = GeneralUtility::makeInstance(DataHandler::class);

$cmd = [];
foreach ($queryBuilder->executeQuery()->fetchFirstColumn() as $uid){
    $cmd[$table][$uid]['delete'] = 1;
}

$dataHandler->start([], $cmd);
$dataHandler->process_cmdmap();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.