QueryBuilder Custom Function bound parameter surrounded by literal strings

Currently, I have this query that works:

$query->select('*')->from('table')->where([
        'created_at >' => $query->newExpr('DATE_SUB(NOW(), INTERVAL :days DAY)'),
    ])->bind(':days', $days, 'integer');

Now, I read the following in the documentation:

Use func() to pass untrusted user data to any SQL function.

$days is not trusted, so binding it with bind() with newExpr() seems like a good solution, but I’m wondering how it could be solved with func() instead of newExpr().

The example in the documentation is using concat which accepts parameters that are only the bound value and nothing else (' - CAT: ' and ' - Age: '):

$concat = $query->func()->concat([
    'Articles.title' => 'identifier',
    ' - CAT: ',
    'Categories.name' => 'identifier',
    ' - Age: ',
    $query->func()->dateDiff([
        'NOW()' => 'literal',
        'Articles.created' => 'identifier',
    ])
]);
$query->select(['link_title' => $concat]);

But what about functions that take a string with multiple literal words but one of them being the bound value as a single parameter, like the DATE_SUB function in my first example.

GitHub Copilot tells me that I can use the custom function like this:

$query->select('*')->from('table')->where([
    'created_at >' => $query->func()->date_sub([
        'NOW()' => 'literal',
        'INTERVAL :days DAY' => 'literal'
    ])
])->bind(':days', $days, 'integer');

Is that correct code, and the only other way to do this? What is the recommended way of doing it, how would you do it?

Thank you for your insight in advance!

I think that when it says “Use func() to pass…”, it means “You can use func() to pass…”, not “You must use func() to pass…”. The binding you’re doing should be sufficient for this.