COMMUNITY

Trouble with using PHP PDO prepared statements

Hello everyone!

I have been trying to figure out how to operate on fetching executed statements both in Mysqli and PDO without much success. I am currently testing on a very simple example to find out the best approach:

var stmt = _dbConn.prepare(query, Lib.toPhpArray([]));
        stmt.execute(Lib.toPhpArray([]));

        var queryResults = stmt.setFetchMode(PDO.FETCH_ASSOC);
        for (k => v in stmt.fetchAll().keyValueIterator())
        {
            Lib.print(k + ": " + v);
        }

Which results in:

v, as you can see, is another Key-Value iterator but Haxe doesn’t recognise this, it simply assumes it’s Dynamic.

This is usually fine, except because it’s a key-value iterator I can’t literally create a for loop to iterate over it.

var stmt = _dbConn.prepare(query, Lib.toPhpArray([]));
stmt.execute(Lib.toPhpArray([]));

var queryResults = stmt.setFetchMode(PDO.FETCH_ASSOC);
for (k => v in stmt.fetchAll().keyValueIterator())
{
    for (col => value in v)
    {
        Lib.print(col + ": " + value);
    }
}

Gives the error: characters 34-35 : You can't iterate on a Dynamic value, please specify KeyValueIterator or KeyValueIterable

Attempting to cast the Dynamic type to a Map<String, String> also causes the following error: Cast type parameters must be Dynamic.

I’ve printed out the result of Type.typeof(v) and it’s just TUnknown, thinking perhaps there was a specific type I could cast to where Haxe won’t complain. I’m at a dead end now. I’m not sure I want to resort to writing PHP directly, as it defeats the point of what I’m doing.

Any ideas as to how to solve this? Any help greatly appreciated.

I’ve attempted something else:

var rows = cast (v, Map<Dynamic, Dynamic>);

This compiled, but I got a runtime error: Cannot cast [id => 1, name => , description => ] to haxe.IMap.

Okay, I’ve got there in the end:

var stmt = _dbConn.prepare(query, Lib.toPhpArray([]));
stmt.execute(Lib.toPhpArray([]));

var queryResults = stmt.setFetchMode(PDO.FETCH_ASSOC);
for (k => v in stmt.fetchAll().keyValueIterator())
{
    Syntax.foreach(v, (col, value) -> {
        var instance = Type.createInstance(cls, []);
        Reflect.setField(instance, col, value);
        results.push(instance);
    });
}

Lots of workarounds required when dealing with dynamic languages it seems.

Try check-type syntax instead of a cast:

for(col => value in (v:Map<String,String>)) {
}

Keep in mind that unlike cast it does not perform any runtime checks. And if v will happen to be e.g. an Array instead of Map at runtime, then the behavior is undefined (most likely an exception about accessing a non-existent method).