JBurlison
JBurlison

Reputation: 673

PHP insert nested arrays into mongoDB

I have a function that updates fine with a single dimensional array, but with a multidimensional array (or nested array) it will not update. the document data, the BSONfield (acts as the find key), and the collection are imputed. Any Idea what i am doing wrong?

Public Static function updateDocument($collection, $BSONfield, $document){
    $dbcollection = $db->selectCollection($collection);
    $sdata = $document[$BSONfield];
    $secureInnerDocument = array();
            $secureDocument = array();
    if($BSONfield == "_id"){
        $sdata = new MongoID($sdata);
        unset($document["_id"]);
    }
    $filter = array($BSONfield=>$sdata);
    foreach ($document as $k => $v) {   
        if (is_array($v)) {
            foreach ($v as $sk => $sv) {
                $secureInnerDocument[$sk] = Security::secureQuery($sv);
            }
                $secureDocument[$k] = $secureInnerDocument;
        }else{      
            $secureDocument[$k] = Security::secureQuery($v);
        }
    }
    $dbcollection->update($filter,array('$set'=>$secureDocument));
    $objid = (string) $secureDocument['_id'];
    return $objid;
}

Upvotes: 0

Views: 2438

Answers (3)

Mick Sear
Mick Sear

Reputation: 1566

It translates fairly directly:

db.collection.update(
   {fieldNameFilter:'filterValue'}, 
   {$set: {'stringFieldName' : 'newValue'}}
);

Translates to:

$collection->update(
   array('fieldNameFilter'=>'filterValue'), 
   array($set => array('stringFieldName'=>$value))
);

Then there are some flags for multi-row updates, etc. which I'm not showing here, but which are in the PHP and Mongo docs.

You might also want to look at: MongoDB - help with a PHP query

Upvotes: 1

Chris Henry
Chris Henry

Reputation: 12010

You don't seem to be using the $set operator correctly. As per the MongoDB docs, you need to format your update document like so;

{ $set : { field : value } }

If you're running a $set on nested keys, you need to use dot notation to get to them. For example;

{ $set : { field.nest : value } }

Upvotes: 0

JBurlison
JBurlison

Reputation: 673

So after fiddling around with is my solution ended up being kind of janky, I deleted the Document then re-create it. Here is the code in case anyone is looking:

/**
 * updates document in the collection.
 * This function secures the data
 *
 * @return  object ID
 * @param   string $collection  The name of the collection
 * @param   string $BSONfield   The $BSON Field you want to index by
 * @param   string $document    The document contents as an array
 */
Public Static function updateDocument($collection, $BSONfield, $document){
    $db =  Database::dbConnect();
    $collection = Security::secureQuery($collection);
    $BSONfield = Security::secureQuery($BSONfield);
    $dbcollection = $db->selectCollection($collection);
    if(array_key_exists('_id', $document)){
        $document["_id"] = new MongoID($document["_id"]);
    }
    Database::deleteDocument($collection, $BSONfield, $document);
    $objid = Database::createDocument($collection, $document);
    return $objid;
}

/**
 * Deletes a document in the collection.
 * This function secures the data
 *
 * @return  Boolean     True - if successfully deleted, False if document not found
 * @param   string $collection  The name of the collection
 * @param   string $BSONfield   The $BSON Field you want to index by
 * @param   string $document    The document contents as an array
 */
Public Static function deleteDocument($collection, $BSONfield, $document){
    $db =  Database::dbConnect();
    $collection = Security::secureQuery($collection);
    $BSONfield = Security::secureQuery($BSONfield);
    $exists = False;
    $dbcollection = $db->selectCollection($collection);
    $documentList = $dbcollection->find();
    $sdata = $document[$BSONfield];
    if($BSONfield == "_id"){
        $sdata = new MongoID($sdata);
    }
    foreach ($documentList as $doc) {
        $documentID = $doc[$BSONfield];
        if ($documentID == $sdata){
            $exists = True;
        }
    }
    if ($exists){
        $deleted = True;
        $filter = array($BSONfield=>$sdata);
        $dbcollection->remove($filter,true);
    }else{
        $deleted = False;
    }
    return $deleted;
}


/**
 * Inserts document into the collection.
 * This function secures the data
 *
 * @return  object ID.
 * @param   string $collection  The name of the collection
 * @param   string $document    The document contents as an array
 */
Public Static function createDocument($collection, $document){
    $db =  Database::dbConnect();
    $collection = Security::secureQuery($collection);
    $dbcollection = $db->selectCollection($collection);
    $secureDocument = array();
    $secureInnerDocument = array();
    foreach ($document as $k => $v) {   
        if (is_array($v)) {
            foreach ($v as $sk => $sv) {
                $secureInnerDocument[$sk] = Security::secureQuery($sv);
            }
                $secureDocument[$k] = $secureInnerDocument;
        }else{  
            if ($k == '_id'){   
                $secureDocument[$k] = $v;
            }else{  
                $secureDocument[$k] = Security::secureQuery($v);
            }   
        }
    }
    $dbcollection->insert($secureDocument);
    $objid = (string) $secureDocument['_id'];
    return $objid;
}

and how i am securing all the data from injections:

/**
 * Secures string to be inputed into a database.
 * 
 * @return Retuns secure string
 * @param   String $string  String to be secured
 */
Public Static Function secureQuery($string){
    $secureString = strtr($string, array(
            "'"  => "0x27",
            "\"" => "0x22",
            "\\" => "0x5C",
            "<"  => "0x3C",
            ">"  => "0x3E",
            "="  => "0x3D",
            "+"  => "0x2B",
            "&"  => "0x26",
            "{"  => "0x7B",
            "}"  => "0x7D",
    ));
    return $secureString;
}

/**
 * Un-Secures string to be inputed into a database.
 *
 * @return Retuns unsecure string
 * @param   String $string  String to be un-secured
 */
Public Static Function unsecureQuery($string){
    $secureString = strtr($string, array(
            "0x27"  => "'",
            "0x22" => "\"",
            "0x5C" => "\\",
            "0x3C"  => "<",
            "0x3E"  => ">",
            "0x3D"  => "=",
            "0x2B"  => "+",
            "0x26"  => "&",
            "0x7B"  => "{",
            "0x7D"  => "}",
    ));
    return $secureString;
}

enjoy!

Upvotes: 0

Related Questions