...

Hi! I’m Starx

experienced Software Developer. And this is my blog
Start Reading About me
Blog Page
April 18, 2012

PDO MySQL: Insert multiple rows in one query

Question by Adam Ramadhan

hello im making a class for doing multiple insert in pdo.

something like this

INSERT INTO $table (key1,key2,key3,etc) VALUE (value1,value2,value3,etc), (value1,value2,value3,etc), (value1,value2,value3,etc)

so after searching i found out that i have to build something like

INSERT INTO $table (key1,key2,key3,etc) VALUE (:key1,:key2,:key3,etc), (:key1,:key2,:key3,etc), (:key1,:key2,:key3,etc)

then execute with this $this->execute($data);
where $data is

 0 => 
    array
      'key1' => 'value1'
      'key2' => 'value2'
      'key3' => 'value3'
 1 => 
    array
      'key1' => 'value1'
      'key2' => 'value2'
      'key3' => 'value3'

 etc

the problem is i still get an error Array to string conversion on $insert->execute($data); how can i fix that?

heres a snippet of what im making.

public function multipleInsert($table, $data = array()) 
{

    # INSERT (name) VALUE (value),(value)
    if (count($data) > 1) 
    {
        $fieldnames = array_keys($data[0]);
        $count_inserts = count(array_values($data));
        $count_values = count(array_values($data[0]));

        # array(????) untill x from first data
        for($i = 0; $i < $count_values; $i++)
        {
            $placeholder[] = '?';
        }

        # array((????),(????),(????)) for query
        for ($i=0; $i < $count_inserts; $i++) 
        { 
            $placeholders[] = '('. implode(',',$placeholder) . ')';
        }

        $query  = 'INSERT INTO '. $table;
        $query .= '(`'. implode('`, `', $fieldnames) .'`)';
        $query .= ' VALUES '. implode(', ', $placeholders);

        $insert = $this->start->prepare($query);

        $i = 1;
        foreach($data as $item) 
        {
            foreach ($item as $key => $value) 
            {
               $insert->bindParam($i++, $item[$key]);
            }
        }

        echo $query;
        $insert->execute();

        $return['status'] = true;
        $return['lastid'] = $this->start->lastInsertId();

        return $return;
    } 
    else 
    {
        die('$data is less then two array, use single insert instead.');
    }
}

Answer by Starx

An easy way for this avoiding the complications would be something like this

$stmt = $pdo->prepare('INSERT INTO foo VALUES(:a, :b, :c)');
foreach($data as $item)
{
    $stmt->bindValue(':a', $item[0]);
    $stmt->bindValue(':b', $item[1]);
    $stmt->bindValue(':c', $item[2]);
    $stmt->execute();
}

However, this executes the statement multiple times. So, it is better if we create a long single query in order to do this.

Here is an example of how we can do this.

$query = "INSERT INTO foo (key1, key2) VALUES "; //Prequery
$qPart = array_fill(0, count($data), "(?, ?)");
$query .=  implode(",",$qPart);
$stmt = $dbh -> prepare($query); 
$i = 1;
foreach($data as $item) { //bind the values one by one
   $stmt -> bindParam($i++, $item['key1']);
   $stmt -> bindParam($i++, $item['key2']);
}
$stmt -> execute(); //execute
Read more

PHP and MySQL, what's wrong with this function?

Question by Peter Jonsson

This function doesn’t work and I can’t find the problem, which is somewhere inside the query.

function get_category_posts($category, $page, $per_page) {
$start = (int)($page - 1) * $per_page;
$per_page = (int)$per_page;

$sql = "SELECT
    `posts`.`post_id` AS `id`,
    `posts`.`post_title` AS `title`,
    `posts`.`post_category` AS `category`,
    `posts`.`post_body` AS `preview`,
    `posts`.`post_user` AS `user`,
    DATE_FORMAT(`posts`.`post_date`, '%Y-%m-%d %H:%i:%s') AS `date`,
    `comments`.`total_comments`,
    DATE_FORMAT(`comments`.`last_comment`, '%Y-%m-%d %H:%i:%s') AS `last_comment`
FROM `posts`
WHERE `category`='".$category."'
LEFT JOIN (
    SELECT
        `post_id`,
        COUNT(`comment_id`) AS `total_comments`,
        MAX(`comment_date`) AS `last_comment`
    FROM `comments`
    GROUP BY `post_id`
) AS `comments`
ON `posts`.`post_id` = `comments`.`post_id`
ORDER BY `posts`.`post_date` DESC
LIMIT {$start}, {$per_page}";

$posts = mysql_query($sql);
//die(mysql_error());

$rows = array();
while (($row = mysql_fetch_assoc($posts)) !== false) {
    $rows[] = array(
        'id' => $row['id'],
        'title' => html_entity_decode($row['title']),
        'category' => html_entity_decode($row['category']),
        'preview' => html_entity_decode($row['preview']),
        'user' => html_entity_decode($row['user']),
        'date' => $row['date'],
        'total_comments' => ($row['total_comments'] === null) ? 0 : $row['total_comments'],
        'last_comment' => ($row['last_comment'] === null) ? 'aldrig' : $row['last_comment']
        );
}

return $rows;

}
The function works fine without the WHEREcategory='".$category."', however, with it it returns

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘LEFT JOIN ( SELECT post_id, COUNT(comment_id) AS total_comments, ‘ at line 12

Answer by Mikey

The WHERE clause must come after the table joins and before the ORDER BY and LIMIT

SELECT <column list>
FROM <table>
JOIN <table> USING (<column>)
WHERE <condition>
OR <condition>
AND <condition>
GROUP BY <column list>
HAVING <expression>

Answer by Starx

JOINs have to come before WHERE condition

$sql = "SELECT
    `posts`.`post_id` AS `id`,
    `posts`.`post_title` AS `title`,
    `posts`.`post_category` AS `category`,
    `posts`.`post_body` AS `preview`,
    `posts`.`post_user` AS `user`,
    DATE_FORMAT(`posts`.`post_date`, '%Y-%m-%d %H:%i:%s') AS `date`,
    `comments`.`total_comments`,
    DATE_FORMAT(`comments`.`last_comment`, '%Y-%m-%d %H:%i:%s') AS `last_comment`
FROM `posts`
LEFT JOIN (
    SELECT
        `post_id`,
        COUNT(`comment_id`) AS `total_comments`,
        MAX(`comment_date`) AS `last_comment`
    FROM `comments`
    GROUP BY `post_id`
) AS `comments`
ON `posts`.`post_id` = `comments`.`post_id`
WHERE `posts`.`category`='".$category."'
ORDER BY `posts`.`post_date` DESC
LIMIT {$start}, {$per_page}";
Read more
April 17, 2012

select value of dropdownlist item jquery

Question by Both FM

HTML

<select id="selectDepartment">
  <option value="1">120</option>
  <option value="2">20</option>
  <option value="3">140</option>
  <option value="4">4120</option>
  <option value="5">560</option>
  <option value="6">451</option>
  <option value="7">310</option>
  <option value="8">656</option>
  <option value="9">444</option>
  <option value="10">555</option>
  <option value="11">2560</option>
  <option value="12">450</option>
</select>

jQuery

$("#selectDepartment").change( function() {

alert($("select option:selected").val()); 

});

the above function always shows value 1 on alert, when I select any one of the options

Answer by Brad Christie

Your method of finding the selection option is vague. You’re saying “Grab all <select>s”. You then go on to grab the :selected option from each of them (of all <select>s on the page). Continued, .val() takes the first value off the top.

Simply put, you’re always fetching the selected value of the first <select> found on the page. Assuming #selectDepartment isn’t the first <select>, your value will never change.

Try to keep the scope to within the current <Select> using this:

$('#selectDepartment').change(function(){
  var selopt = $('option:selected',this);
});

Note that I specify the scope to within the <select> that triggered the .change(). Also note this really isn’t necessary as val() works just as easily:

var selopt = $(this).val();

Let jQuery do the heavy lifting. You really only need option:selected if you want control over styling that specific element, or you’re working with a multi-select and want more control.

Answer by Starx

You can do something like this:

$("#selectDepartment").change( function() {

     var selected = $(this).find(":selected");

});
Read more

PHP – Footer function sample

Question by NewLearner

I’ve been looking all over but I cannot find an example. I want to write a foother function into my functions.php Can you please give me a simple sample of how this is done. I think I have an idea but I’m not sure if will work.

 function footer_function()
 {
   $return_Str='';
   $return_Str .= '<h3>Copyright © 2012</h>';
   return $return_Str;
}

Thank you all for your help!!!

Answer by Starx

This is probably what you wanted.

function footer() {
    $return_str = "";
    $return_str .= '<h3>Copyright 2012</h3>';
    return $return_str;
}

To display the footer. Just do this

echo footer();
Read more

Best practice for storing database password

Question by beshiros

I am developing a custom server application that will access a database. I need to decide where I will store the credentials (and to address) to that server.

A common solution is to put the credential in a config file. However, I do not want a compromised server to mean that the hacker has access to the DB (which is hosted on a separate server).

I could store the credentials in the environment, but that is just security through obscurity. Mr. Evil can just look in the environment to find it.

Someone suggested encryption. However, if I store the key in the executable, a quick de-compile (we are using Java) and I am still doomed.

I also want to avoid having to enter a paraphrase every time I start the server.

Any suggestions? I feel like I’m missing something simple.

Thanks

Answer by T.J. Crowder

I don’t think you’re missing something simple. Either the server in question can connect to the database without your help, in which case it has to have the credentials; or it cannot connect without your supplying them. You can take various steps like the ones you’ve listed to make it harder for a compromised server to reveal the credentials to the database, but at the end of the day, if it has to have those credentials and supply them to the DB server to connect, they’ll have to be stored on it somewhere — or at least, it will have to have some means of getting them, and so will be hackable in that sense.

Your best bet is to focus on finding out about intrusions (compromised servers) as quickly as possible, keeping good off-site, off-line backups for the worst case, putting up lots of barriers to intrusion in the first place, etc.

Answer by Starx

I am sharing, the way I had solved this.

  • Build API, to query the authentication details from a foreign domain.
  • Use public key, and private key to read through the details.

But, honestly the only thing this did was over complicate simple things. After that, I created several users to the database, with different privileges.

Like

  • guest can only to SELECT
  • mod can only CREATE, INSERT, UPDATE, DELETE

etc and switched the user, whenever authenticated users appeared.

With the combination of users and session, I have been able to escape the threats so far. But ofcourse the code vulnerability have to be tested thoroughly.

Read more

insert dummy data to mysql fast

Question by fxuser

I have 1 function in my debug model which i want to use in order to add dummy data to my app to test its speed and such…

the problem is that it needs to add records to 2 different tables and also check for duplicates usernames etc before each record is added to db so it takes a little time…

also this procedure is repeated about $total different dummy records i want to add at once in a for loop…

for example for 100 new users i want to add it takes around 5 seconds to proceed.

is this time fine or do i need to optimize it?

what if i want to add 1000,10000 users at once?? is it possible?

EDIT:
Function called to insert data:

public function registerRandomUsers($total = 1){
    $this->load->model("misc_model");
    $this->load->model("encryption_model");
    $this->load->model("signup_model");

    for ($i=1;$i<=$total;$i++){
        $username = $this->misc_model->generateRandomString(15);
        $flag = false;
        while ($flag == false){
            if ($this->user_model->usernameExist($username)){
                $username = $this->misc_model->generateRandomString(15);
            }else{
                $flag = true;

                $password = 'Test123';
                $email = $username.'@email.com';
                $data = array(
                    'username' => $username,
                    'password' => $password,
                    'email' => $email
                );
                $this->signup_model->submitRegistration($data);
                $userdata = $this->user_model->getUserData($username, "username");
            }
        }
    }
}

Answer by Mikey

If you’re not worried about having a random string as the user name, just set the $email = 'user'.$i.'@email.com'; (so you don’t have to worry about collisions). The main reason this will be running slow is because you’re sending a new query to the database on each iteration of the loop – it would be much much faster to generate a bulk insert string like:

INSERT INTO user (email,pass)
VALUES ('user1@email.com','Test123')
,      ('user2@email.com','Test123')
,      ('user3@email.com','Test123')
,      ('user4@email.com','Test123')
,      ('user5@email.com','Test123');

This way you can avoid the overhead of tcp traffic from sending 10000 queries to the database and have it do it all in one go.

Answer by Starx

Build your query as this

$conjuctions = str_repeat("('dummy@email.com','test pass'),", 20); // 20 dummy datas
$query = "INSERT INTO user (email,pass) VALUES ".substr($conjunctions,0,str_len($conjuctions).";"
                                               // ^ This is to remove the last comma
Read more

How to horizontally center a modal div even after the browser is resized?

Question by saganbyte

I m trying to add an item to the DOM using jquery. I want it to overlay on top(z-index) of all other content (there are hundreds of z-indices set already) and it should be center aligned at all times.

While adding this div to the DOM, i m setting its ‘left’ property to $(window).width()/2 – 971/2. 971 is the width of the div I m trying to add. This is the CSS for it

width: 971px;
height: 669px;
background-image: url(/path/to/image/);
position: absolute;
margin: 0px auto;
z-index: 2500; 

The problem is, the div does not stay centered after the browser is resized. I ve even tried with left: 50% and some negative left margin in pixels. If I set the ‘left’ property in relation with the ‘screen’ then it s centered only if the browser window is maximized by the user.

What is a good way to position this absolutely positioned div with a high z-index such that its always centered?

Answer by Mikey

#someId{
    width: 971px;
    height: 669px;
    padding: 0;
    border: 0;

    margin-left:-486px; /* 971/2 */
    margin-top:-335px; /* 669/2 */

    position: fixed;
    left: 50%;
    top: 50%;

    background-image: url(/path/to/image/);
    z-index: 2500;
}

I know you’ve said you tried this – but this has always worked for me in any browser running in standards compliant mode (even ie) it might have been thrown off by not taking border or padding into consideration. Here’s a working example: http://jsfiddle.net/U3RrT/

I’ve just realised that it may be because you have set an element above it with a different position property; try position:fixed;.

Answer by Starx

First, margin: 0px auto; is enough to horizontally centre a div. So, just removing the left property may be able to fix the issue.


IF not, since you are using jQuery, there is a .resize() event of windowwhich you can control to fix the appearance again.

For example

function resizeMyBox() {
  //code to resize
}       
$(function() {
   resizeMyBox();  // Resize on DOM ready
});
$(window).resize(function() {
   resizeMyBox(); //Resize again on every resize
});
Read more

Split POST array into multiple variables

Question by methuselah

I’m coding a form right now using jQuery .post and the file responsible for processing has the code:

print_r($_POST);

Which returns the following dynamic output:

Array ( [data] => capacity=50-1000+people&bookingdate=17%2F04%2F2012&grade=1+star )

I am trying to split up this array into three variables namely capacity, booking date and grade but don’t really know how to. Any idea how? I’ve tried using echo $_POST[“capacity”]; but it doesn’t work.

Thanks in advance!

Edit

This is the jQuery I’m using:

<script type="text/javascript">
$(document).ready(function() {
    $("#postData").click(function() {
        $("#last-step").hide(600);


       $.post('resources/process2.php', { data: $("#task5_booking").serialize() }, function(data) {
            $("#result").html(data);
      });


        return false;
    });
});
</script>

which is working with the following form:

http://jsfiddle.net/xSkgH/93/

Answer by Salman A

I think you should change this line:

$.post('resources/process2.php', { data: $("#task5_booking").serialize() }, function(data) {

To

$.post('resources/process2.php', $("#task5_booking").serialize(), function(data) {

Notice that I changed the second parameter from an object literal to a (url-encoded) string. This posts each variable in your form as a separate variable (as if it were posted directly). On the server side, each variable should be available separately inside $_POST array.

Answer by Starx

You have to use explode for this.

$data = array();  // A array to store the extracted value
$temp = explode("&", $data); // First of all explode by "&" to get the each piece
foreach($temp as $tval) {
   $t = explode('=', $tval); // Next explode by "=" to get the index and value
   $data[$t[0]] = $t[1];  //Add them to the array
}

Another alternative is to use parse_str():

$data = array();
parse_str($_POST['data'], $data);

After this all the values will be mapped to the $data

Read more

how to reach into PHP nested arrays?

Question by user837208

I’ve a nested array whose print_r looks like this-

Array
(
    [keyId] => Array
        (
            [hostname] => 192.168.1.127
            [results] => Array
                (
                    [1] => false
                    [2] => false
                    [3] => false
                )

            [sessionIDs] => Array
                (
                    [0] => ed9f79e4-2640-4089-ba0e-79bec15cb25b
                )

        )

I would like to process(print key and value) of the “results” array. How do I do this?

I am trying to use array_keys function to first get all the keys and if key name is “results”, process the array. But problem is array_keys is not reaching into the “results”

Answer by Jon

foreach($array['keyId']['results'] as $k => $v) {
    // use $k and $v
}

Answer by Starx

One way to navigate through the array is this.

//Assuming, your main array is $array
foreach($array as $value) { //iterate over each item

   if(isset($value['results']) && count($value['results'])) { 
   // ^ check if results is present

       //Now that we know results exists, lets use foreach loop again to get the values
       foreach($value['result'] as $k => $v) {
           //The boolean values are now accessible with $v
       }
   }
}
Read more

Slide upping in jquery with ids

Question by Mert Metin

var Ids = $('.head:has(:checkbox:checked)')
               .map(function() { return this.id })
               .get(); alert(Ids);

i have ids with above code.However,
i cannot slide up with these Ids with

Why this does not work ?

function(response){
        alert("Başarıyla silindi");
         $('#'+Ids).each('slow', function() {
    }).slideUp();

Answer by Starx

First of all Ids is an array, so you cannot directly use $("#"+Ids).

Next, even if Ids was not an array and referrred to a string variable $("#"+Ids) would return an HTML element, which does not have .each() function.

The correct way to do this is

$.each(Ids, function(v) {
  $("#"+v).slideUp("slow"):
});
Read more
...

Please fill the form - I will response as fast as I can!