1

i am currently running into an issue were i want to insert an array with prepared statements by pdo to my databse. I found some code here to start with, but currently its only inserting one of the files in the array $files which is passed to that method.

$amount = count($files);

for($i=0; $i<$amount; $i++){

    $dbArr=[
        'path'      => (string) dirname( $files[$i] ),
        'name'      => (string) basename( $files[$i] ),
        'size'      => (int) filesize($files[$i]),
        'mimeType'  => (string) mime_content_type( $files[$i] ),
    ];
}

foreach($dbArr as $k => $v ) {
    $prep[':'.$k] = $v;
}

new sql();

$q = sql::$db->prepare($str = "INSERT INTO filesSrc ( " . implode(', ',array_keys($dbArr)) . ") VALUES (" . implode(', ',array_keys($prep)) . ")");

$res = $q->execute($prep);

It works, but only inserts one of the array. the solution might be simple, i am overlooking something.

2 Answers 2

1
$params = [
        'path'      => ':path',
        'name'      => ':name',
        'size'      => ':size',
        'mimeType'  => ':mineType',
    ];
$sql    = "INSERT INTO filesSrc ( " . implode(',', array_keys($params)) . ") VALUES (" . implode(',', $params) . ")";
$amount = count($files);
$dbArrs = [];
for($i=0; $i<$amount; $i++){

    $dbArrs[] = [
        'path'      => (string) dirname( $files[$i] ),
        'name'      => (string) basename( $files[$i] ),
        'size'      => (int) filesize($files[$i]),
        'mimeType'  => (string) mime_content_type( $files[$i] ),
    ];
}



new sql();
#todo It is recommended to use 'try catch'
$q = sql::$db->prepare($sql);
foreach ($dbArrs as $dbArr) {
    foreach ($params as $key => $param) {
        $q->bindParam($param, $dbArr[$key]);
    }
    $q->execute();
}
Sign up to request clarification or add additional context in comments.

4 Comments

Hey and welcome to StackOverflow. Please don't post a second answer if it's not fundamentally different. And also then I'd recommend packing it into one. For your information, you can edit your answer if you get more information or noticed anything that should be changed (click the edit button right under the question [bottom left])
is executing in a loop the right way? i thought i would end up with one execute function at the end? Before i did such things with multiple statements in a loop, thats what i wanted to prevent this time.
Because I didn't see the overall code, I can't provide an accurate function.
If you want to insert a lot of data, it is recommended to use asynchronous mode.
1

Unless you are inserting thousands of rows, I would just insert them one by one with a single prepared statement in a transaction.

$q = sql::$db->prepare("
    INSERT INTO filesSrc (path, name, size, mimeType)
    VALUES (:path, :name, :size, :mimeType)
";

sql::$db->beginTransaction();

foreach ($files as $file) {
    $q->execute([
        'path'      => (string) dirname($file),
        'name'      => (string) basename($file),
        'size'      => (int) filesize($file),
        'mimeType'  => (string) mime_content_type($file),
    ]);
}

sql::$db->commit();

If you really want to execute a bulk insert (single multi-row insert), then I would use ? as placeholder:

$values = [];
$params = [];

foreach ($files as $file) {
    $values[] = '(?,?,?,?)';
    $params[] = (string) dirname($file);
    $params[] = (string) basename($file);
    $params[] = (int) filesize($file);
    $params[] = (string) mime_content_type($file);
}

$values = implode(',', $values);

$q = sql::$db->prepare("
    INSERT INTO filesSrc (path, name, size, mimeType)
    VALUES ($values)
";

$res = $q->execute($params);

To use named parameters instead of ?, change the for-loop to:

foreach ($files as $k => $file) {
    $values[] = "(:path_{$k}, :name_{$k}, :size_{$k}, :mimeType_{$k})";
    $params['path_{$k}'] = (string) dirname($file);
    $params['name_{$k}'] = (string) basename($file);
    $params['size_{$k}'] = (int) filesize($file);
    $params['mimeType_{$k}'] = (string) mime_content_type($file);
}

4 Comments

what function gives me a correct boolean return of the db success? $q? or sql::$db->commit()?
Don't you use PDO in exception mode?
i am using this param PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
Then a failed prepare(...) or execute(..) will raise an exception and you don't need a boolean to check for errors. Use try-catch blocks instead if needed.

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.