I'm running the following code and it works great, if no record exists it creates a new one. What I'm trying to do is modify this query so that the 'v' field also increases +1 but I'm not having any luck. Can someone help me out?
$result = $collection->update(
array('k'=>md5(SITE_ID.'-'.$_SERVER['HTTP_X_FORWARDED_FOR'])),
array('$set'=>
array(
'k'=>md5(SITE_ID.'-'.$_SERVER['HTTP_X_FORWARDED_FOR']), 'st'=>SITE_ID,
'ur'=>$_GET['u'],
'ts'=>time(),
'dt'=>date('Ymd'),
'ur'=>$_GET['p'],
'v'=>1
),
array(
'$inc' => array('v' => 1)
),
),
array('upsert'=>true)
);
Put both the $set and the $inc in a single object:
$result = $collection->update(
array('k'=>md5(SITE_ID.'-'.$_SERVER['HTTP_X_FORWARDED_FOR'])),
array(
'$set'=> array(
'k'=>md5(SITE_ID.'-'.$_SERVER['HTTP_X_FORWARDED_FOR']), 'st'=>SITE_ID,
'ur'=>$_GET['u'],
'ts'=>time(),
'dt'=>date('Ymd'),
'ur'=>$_GET['p']
),
'$inc' => array('v' => 1)
),
array('upsert'=>true)
);
You can use the $inc modifier liek:
{ $inc : { field : value } }
So in your case:
$result = $collection->update(
array('k'=>md5(SITE_ID.'-'.$_SERVER['HTTP_X_FORWARDED_FOR'])),
array('$set'=>
array(
'k'=>md5(SITE_ID.'-'.$_SERVER['HTTP_X_FORWARDED_FOR']), 'st'=>SITE_ID,
'ur'=>$_GET['u'],
'ts'=>time(),
'dt'=>date('Ymd'),
'ur'=>$_GET['p'],
array('$inc' => array('v' => 1))
),
),
array('upsert'=>true)
);
I just saw you're actually using the field though the example above should work.
Here's an example in the PHP doc: http://php.net/manual/en/mongocollection.update.php#example-1470
Related
Hi guys I am a beginner with PHP and want the best way in terms of performance to convert this array:
$old = array(
20 =>
array(
'name' => 'Heels',
'path' => '1/2/10/15/20',
),
15 =>
array(
'name' => 'Sandals',
'path' => '1/2/80/96/15',
),
10 =>
array(
'name' => 'Trainers',
'path' => '1/2/80/96/10',
),
);
To this:
$new = array(
20 =>
array(
'value' => 20,
'label' => 'Trainers > Sandals > Heels',
),
);
There is going to be loads of records surely exploding the paths and mapping them with the ids is going to slow it down in terms of performance just wondering whether there is a more efficient way if possible thanks.
If I understand correctly, you're trying to get the latest path relevant to each category and output it as a breadcrumb.
You can first sort the keys (ids) and then loop through the array creating the breadcrumb.
arsort($paths); # This gives the desired output in OP but makes more sense to use krsort() to sort DESC not ASC
$breadcrumb = (object) array (
'value' => array_keys($paths)[count($paths) - 1], # Get the highest id - if using krsort() use array_keys($paths)[0]
'labels' => implode(' > ', array_column($paths, 'name'));
);
# Update derived from The fourth bird's answer which skips the need for the foreach().
# Concept is to build an array of the labels to then make look pretty with the > effect
Here is a demo.
Output:
object (stdClass) (2) {
["value"] => int(20)
["labels"] => string(26) "Trainers > Sandals > Heels"
}
Another option could be to first create a mapper of the keys and the names. Then you could take the key from the mapper to create the path:
$result = [];
$mapper = array_combine(array_keys($old), array_column($old, 'name'));
foreach ($old as $key => $value) {
$path = implode(' > ', array_map(function($x) use ($mapper) {
return $mapper[(int)$x];
}, explode('/', $value['path'])));
$result[$key] = ['value' => $key,'label' => $path];
}
print_r($result);
Php demo
This is the hardcoded way, but i think you need to give a bit more information to get a dynamic solution.
<?php
$old = array(
20 =>
array(
'name' => 'Heels',
'path' => '1/2/10/15/20',
),
15 =>
array(
'name' => 'Sandals',
'path' => '1/2/80/96/15',
),
10 =>
array(
'name' => 'Trainers',
'path' => '1/2/80/96/10',
),
);
ksort($old);
$breadcrumbs = [];
$currentKey = 0;
foreach ( $old as $itemKey => $item) {
$currentKey = $itemKey;
$breadcrumbs[] = $item;
}
$new = [$currentKey] = [
'value' => $currentKey,
'label' => implode(' > ', $breadcrumbs)
];
printf($new);
I am trying to run an update on my documents, I'm using upsert true but its still overwriting?
$col = "A" . $user->agencyID;
$db = $m->rules;
$collection = $db->$col;
$validValue = $_POST['validValue'];
$id = $_POST['ruleID'];
$document = array(
'tags' => array(
$validValue
)
);
$collection->update(
array(
'_id' => new MongoId($id)
),
array('$set' => $document),
array('upsert'=>true)
);
$validValue is like - Foo Bar
The first value goes in fine but when I try adding a different value it overwrites the first one?
I managed to figure out the problem, I needed $addToSet and also needed to take the array() from arround my $validValue
Actually, use $addToSet which will not push a value into the array if it already exists. This code is untested, please change to fit your needs.
$col = "A" . $user->agencyID;
$db = $m->rules;
$collection = $db->$col;
$validValue = $_POST['validValue'];
$id = $_POST['ruleID'];
$document = array(
'tags' => array(
$validValue
)
);
$collection->update(
array(
'_id' => new MongoId($id)
),
array('$addToSet' => array('tags' => $document))
);
first of, just wanted to let you know that I am a newbie at CI. but I am having trouble with this piece of code where is breaking and I can't seem to be able to find the answer anywhere.
for some reason the code is breaking at the first if statement.. if possible could you help me out understand what is really happening there?
Thank you all for your help!
function main
{
$this->load->model(getData) psudo code for this area...
}
---model---
function getData....
{
Sql = this->db->query(sql code that returns all the information required.)
$result = $sql->result_array();
$types = array ( 'EVENT|TIME' => array( 'id' => 1, 'name' => 'Regular' ),
'PROPOSITION|REGULAR' => array( 'id' => 2, 'name' =>'Propositions'),
'EVENT|TIME' => array( 'id' => 3, 'name' => 'Now' ),
'PROPOSITION|FUTURES' => array( 'id' => 4, 'name' => 'Future' ));
$var = array();
foreach ($result as $event) {
$cat = $event['type'] . '|' . $event['sub_type'];
$typeId = $types[$cat]['id'];
if(!is_array($var[$event['event_id']]['var'][$event['type_id']]))
{
if(!is_array($var[$event['event_id']]))
{
$var[$event['event_id']] = array( 'event_name' =>
$event['event_name'],'event_abbreviation' =>
$event['event_abbreviation']);
}
$var[$event['event_id']]['var'][$event['type_id']] = array(
'type_name' => $event['abbreviation'],'type_abbreviation' => $event['name']
);
}
$event[$event['event_id']]['var'][$event['type_id']]['types'][$typeId] =
$types[$cat]['name'];
}
return $myResults;
}
In this line
if(!is_array($var[$event['event_id']]['var']$event['type_id']]))
You are missing a [ somewhere. I'm guessing before $event['type_id'].
So replace with:
if(!is_array($var[$event['event_id']]['var'][$event['type_id']]))
I am trying to loop through only a specific sub array in PHP with foreach. Example array:
$testData = array(
$test1=array(
'testname'=>'Test This',
'testaction'=>'create user',
$testData = array(
'item'=>'value',
'foo'=>'bar',
'xyz'=>'value'
),
$anotherArray = array()
),
$test2=array(
'testname'=>'Test That',
'testaction'=>'get user',
$testData = array(
'item'=>'value',
'foo'=>'bar',
'xyz'=>'value'
),
$anotherArray = array()
)
);
And now I am going to go through each test and set some logic based on the name and action, but then need to do several tests on the data. Not sure how to only get $test1's $testData and not $test1's $anotherArray data. I have the following but it doesn't work:
foreach($testData as $test => $section){
foreach($section['testData'] as $field => $value){
\\code
}
}
Any help is appreciated! Thanks!
Try this instead:
$testData = array(
'test1'=>array(
'testname'=>'Test This',
'testaction'=>'create user',
'testData' => array(
'item'=>'value',
'foo'=>'bar',
'xyz'=>'value'
),
'anotherArray' => array()
),
'test2'=>array(
'testname'=>'Test That',
'testaction'=>'get user',
'testData' => array(
'item'=>'value',
'foo'=>'bar',
'xyz'=>'value'
),
'anotherArray' => array()
)
);
Official PHP documentation states that filter_var_array() supports array filtering in the following format:
$data = array(
'testarray' => array('2', '23', '10', '12')
);
$args = array(
'testarray' => array('filter' => FILTER_VALIDATE_INT,
'flags' => FILTER_FORCE_ARRAY
)
);
$myinputs = filter_var_array($data, $args);
However, if the array in question is multi-dimensional and requires different filters for different parts, how would you approach defining filtering options?
As an example:
$data = array(
'testhash' => array('level1'=>'email',
'level2'=> array('23', '10', '12'))
);
Idea 1
Consider using FILTER_CALLBACK. In this way, you can write a callback function that itself uses the filter extension, thus providing a recursive ability.
function validate_array($args) {
return function ($data) use ($args) {
return filter_input_array($data, $args);
};
}
This will generate the callback functions.
$args = array(
'user' => array(
'filter' => FILTER_CALLBACK,
'options' => validate_array(array(
'age' => array('filter' => FILTER_INPUT_INT),
'email' => array('filter' => FILTER_INPUT_EMAIL)
))
)
);
This is what the config array would then look like.
Idea 2
Do not hesitate to pat me on the back for this one because I am quite proud of it.
Take an arg array that looks like this. Slashes indicate depth.
$args = array(
'user/age' => array('filter' => FILTER_INPUT_INT),
'user/email' => array('filter' => FILTER_INPUT_EMAIL),
'user/parent/age' => array('filter' => FILTER_INPUT_INT),
'foo' => array('filter' => FILTER_INPUT_INT)
);
Assume your data looks something like this.
$data = array(
'user' => array(
'age' => 15,
'email' => 'foo#gmail.com',
'parent' => array(
'age' => 38
)
),
'foo' => 5
);
Then, you can generate an array of references that map keys such as 'user/age' to $data['user']['age']. In final production, you get something like this:
function my_filter_array($data, $args) {
$ref_map = array();
foreach ($args as $key => $a) {
$parts = explode('/', $key);
$ref =& $data;
foreach ($parts as $p) $ref =& $ref[$p];
$ref_map[$key] =& $ref;
}
return filter_var_array($ref_map, $args);
}
var_dump(my_filter_array($data, $args));
Now the only question is how you deal with the mismatch between the validation record and the original data set. This I cannot answer without knowing how you need to use them.