Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Argument expects a literal string, got literal-string #560

Open
noemi-salaun opened this issue Mar 3, 2023 · 5 comments
Open

Argument expects a literal string, got literal-string #560

noemi-salaun opened this issue Mar 3, 2023 · 5 comments

Comments

@noemi-salaun
Copy link

When calling Connection::insert() with the table name as a literal-string, I got this error message

Argument #0 expects a literal string, got literal-string

@staabm
Copy link
Owner

staabm commented Mar 3, 2023

thanks for reporting. could you please provide a concrete code sample?

@noemi-salaun
Copy link
Author

I have some code that clone a user with all its data.

  1. So I got an hardcoded list of known tables.
  2. Foreach on the list.
  3. SELECT * FROM each table
  4. Change some of the data (replace the userId used as a foreign key, ...)
  5. INSERT the new data in the same table

For the insert, I use a function that add backquote around column and table name.

/**
 * @param literal-string       $tableExpression
 * @param array<string, mixed> $data
 */
private function insert(string $tableExpression, array $data): void
{
    $backquotedTableExpression = "`$tableExpression`";

    $backquotedData = [];
    foreach ($data as $key => $value) {
        $backquotedData["`$key`"] = $value;
    }

    $this->dbal->insert($backquotedTableExpression, $backquotedData);
}

So my real error message is

Argument#0 expects a literal string, got literal-string&non-falsy-string

But the error stay the same if I remove the backquote and pass $tableExpression directly to dbal insert

Argument#0 expects a literal string, got literal-string

@hemberger
Copy link
Contributor

hemberger commented Mar 11, 2023

What is being checked in the DoctrineKeyValueStyleRule is that the keys of the array passed to Doctrine\DBAL\Connection::insert correspond to columns in the database. In your insert function, PHPStan doesn't know the literal values of the keys of $data, and therefore it cannot check that they are columns in the database.

Similarly for the table name, if PHPStan doesn't know the literal value of the string, it can't check that the table exists in the database.

If you are wrapping calls to Doctrine\DBAL\Connection in your own class, e.g. My\Connection, then you should probably be declaring its function in your PHPStan configuration instead of the Doctrine ones. For example:

services:
    -
        class: staabm\PHPStanDba\Rules\DoctrineKeyValueStyleRule
        tags: [phpstan.rules.rule]
        arguments:
            classMethods:
                - 'My\Connection::insert#1'

(Note: technically this rule checks for a constant string, so maybe the error message should be revised to replace "literal" -> "constant"?)

@staabm
Copy link
Owner

staabm commented Mar 11, 2023

(Note: technically this rule checks for a constant string, so maybe the error message should be revised to replace "literal" -> "constant"?)

ohh I did not see that. we should not talk about literal strings when we expect constant strings and vice versa.
these are 2 different things - please fix that

hemberger added a commit to hemberger/phpstan-dba that referenced this issue Mar 11, 2023
Table names must be constant strings, not literal strings.

As per staabm#560 (comment).
@staabm
Copy link
Owner

staabm commented Mar 20, 2023

@hemberger the code example mentioned in #560 (comment) should be concluded as not analyzable and we should not error (as long as we are not in debug mode)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants