ok, this might sound strange, but i have a form and our business wants to track what is getting changed, when a user adds a new lead etc.
So i set up a function that does the following
function savedata($data){
$collection = $this->db->retail_logs;
$this->data = explode('|', $data['data']);
print_r($this->data);
try {
$collection->update(
array($this->data['0']=>$this->data['1'],$this->data[2]=>$this->data[3]),
array("date"=> date("d.m.Y"), "time"=>date("H:i:s"),"whochanged"=>$_COOKIE['CRMUIDkey']), // new lead document to insert
array("upsert" => true, "safe" => true)
);
} catch (Exception $e) {
// Something went wrong ..
}
}
it is basiclly a log file.
but as you may be able to see the $data sends data though like tradingname|ABC|owner|ownerID
But if I want to add to that i would need to run a loop or a foreach I am wondering what is the best way to make sure all teh data gets saved and not just data[0] to 3 so say they send 16 fields and values in it I need a foreach or something to split it.
It appears that you want to map the $data['data'] into key=>value pairs (an associative array). You want to be very careful about what fields you allow in this format especially since it looks like user-provided data (or data they can modify in a post request?). For example, a malicious user could update or add to another user's account if you aren't checking the allowed keys before doing the upsert.
To convert the $data string you want to do something like:
<?php
// Keys that can be updated
$allowed = array('tradingname','owner');
// Sample data
$data = 'tradingname|ABC|owner|ownerID|badkey|foo';
// Split into arrays based on '|' delimiter
preg_match_all("/([^\|]+)\|([^\|]+)/", $data, $keypairs);
// Combine matches into key => value array
$keypairs = array_combine($keypairs[1], $keypairs[2]);
// Sanity check to create $criteria
foreach ($keypairs as $key => $value) {
if (in_array($key, $allowed)) {
// Perhaps do some extra sanity checking that $value is expected format
$criteria[$key] = $value;
} else {
// Log and/or bailout as appropriate
echo "Ignoring: [$key] => [$value]\n";
}
}
// Criteria should now be reasonable to use in $collection->update(..) upsert
print_r($criteria);
?>
Send your data as json. And then use json_decode to convert it to the array you want.
Related
I have an IP phone that through 2 action urls makes a get request to my web server.
action urls:
http://192.168.25.126/action.php?ID=$call_id&remote=$display_remote
http://192.168.25.126/action.php?ID=$call_id&extension=$active_user
192.168.25.126 is the web server
action.php is printing to a log file the request
$call_id is a unique ID that the phone is giving to the current session
$remote is the caller's number
$extension is the ip phone extension number
on the server side I have the action.php that prints in a log file the requests through this simple line
<?php
file_put_contents("/tmp/post.log",print_r($_GET,true), FILE_APPEND));
?>
checking the log I can view the expected request
tail -f /tmp/post.log
Array
(
[ID] => 9
[remote] => +39123456789
)
Array
(
[ID] => 9
[extension] => 235
)
How can I merge in tmp.log the arreys with same ID like this?
Array
(
[ID] => 9
[remote] => +39123456789
[extension] => 235
)
pay attention that the first arrey is generated on the ringing event and the second arrey is generated when I pickup the phone(or better to say when a call in enstablished)so in a second moment
I cannot do this with only one action url like this
http://192.168.25.126/action.php?ID=$call_id&remote=$display_remote&extension=$active_user
due a limitation of my ip phone so I have to merge the 2 arreys. and if possible I would like,but this is not really necessary, that the log is printed only if the first arrey with same ID exist(so the log will appears only if an incoming call is answered and not when I make a call).
I'm a senior IT not a php coder so just want a suggestion to write the loop.. many thanks
From what I'm understanding this should do what you need - expecting IDs to be unique.
<?php
// get data from log
$fileData = file_get_contents("/tmp/post.log");
$data = json_decode($fileData, true); // make an array out of the json
// $data will now be something like this:
# $data = [["ID" => 9,"remote" => "+39123456789"],["ID" => 10,"remote" => "+41123456789"]];
// mocking input data
# $_GET = ['ID' => 10, 'otherparam' => 'bar'];
$key = array_search($_GET['ID'], array_column($data, 'ID')); // search for pre-saved data
if($key) { // an item with $ID was found -> merge new data
$item = array_merge($data[$key], $_GET);
$data[$key] = $item; // overwrite existing item with this ID
} else {
$item = $_GET; // create a new item, since we haven't found one
$data[] = $item; // append to data
}
file_put_contents("/tmp/post.log",json_encode($data,true))); // don't append, write the whole dataset
If the IDs are not unique, we could just grab the last added one (via end(), check if IDs match and merge there:
end($data); // set pointer to the end
$key = key($data); // get the key of the last element
if($data[$key]['ID']==$_GET['ID']) {
$item = array_merge($data[$key], $_GET); // merge old and new data
$data[$key] = $item; // overwrite item
}
EDIT:
If you only need the last call, we don't need to re-save the non-matching arrays, so this adapted code should do:
<?php
$fileData = file_get_contents("/tmp/post.log");
$data = json_decode($fileData, true);
// $data will now be something like this:
# $data = ["ID" => 9,"remote" => "+39123456789"]; // note, this time it's a one-dimentional (but assoc) array.
// mocking input data
# $_GET = ['ID' => 9, 'otherparam' => 'bar'];
// check if we have pre-saved data, that has an 'ID' and that matches our current one:
if(is_array($data) && isset($data['ID']) && $data['ID']==$_GET['ID']) { // the saved $ID was found -> merge new data
$data = array_merge($data, $_GET);
} else {
$data = $_GET; // create a new item, since we haven't found one
}
file_put_contents("/tmp/post.log",json_encode($data,true))); // don't append, write the whole dataset
Disclaimer: This code has no error checking whatsoever and will throw errors on a blank log (because json_decode will fail if there's no data yet), has some security issues (using $GET without sanitizing and writing that to a file...), doesn't test for proper input (what if no ID is sent), etc...
I have a working script, but I'm sure that my method of managing arrays could be better. I've searched for a solution and haven't found one, but I'm sure that I should be using the functionality of associative arrays to do things more efficiently.
I have two arrays, one from a CSV file and one from a DB. I've created the CSV array as numeric and the DB array as associative (although I'm aware that the difference is blurry in PHP).
I'm trying to find a record in the DB array where the value in one field matches a value in the CSV array. Both arrays are multi-dimensional.
Within each record in each array there is a reference number. It appears once in the CSV array and may appear in the DB array. If it does, I need to take action.
I'm currently doing this (simplified):
$CSVarray:
('reference01', 'blue', 'small' ),
('reference02', 'red', 'large' ),
('reference03', 'pink', 'medium' )
$Dbarray:
(0 => array(ref=>'reference01',name=>"tom",type=>"mouse"),
(1 => array(ref=>'reference02',name=>"jerry",type=>"cat"),
(2 => array(ref=>'reference03',name=>"butch",type=>"dog"),
foreach ($CSVarray as $CSVrecord) {
foreach ($Dbarray as $DBrecord) {
if ($CSVarray[$numerickey] == $DBrecord['key'] {
do something with the various values in the $DBrecord
}
}
}
This is horrible, as the arrays are each thousands of lines.
I don't just want to know if matching values exist, I want to retrieve data from the matching record, so functions like 'array_search ' don't do what I want and array_walk doesn't seem any better than my current approach.
What I really need is something like this (gibberish code):
foreach ($CSVarray as $CSVrecord) {
WHERE $Dbarray['key']['key'] == $CSVrecord[$numerickey] {
do something with the other values in $Dbarray['key']
}
}
I'm looking for a way to match the values using the keys (either numeric or associative) rather than walking the arrays. Can anyone offer any help please?
use a hash map - take one array and map each key of the record it belongs to, to that record. Then take the second array and simply iterate over it, checking for each record key if the hashmap has anything set for it.
Regarding your example:
foreach ($DBarray as $DBrecord){
$Hash[$record[$key]] = $DBrecord;
}
foreach ($CSVarray as $record){
if (isset($Hash[$record[$CSVkey]])){
$DBrecord = $Hash[$record[$CSVkey]];
//do stuff with $DBrecord and $CSVrecord
}
}
this solution works at O(n) while yours at O(n^2)...
You can use foreach loops like this too:
foreach ($record as $key => $value) {
switch($key)
{
case 'asd':
// do something
break;
default:
// Default
break;
}
}
A switch may be what you are looking for also :)
Load CSV into the db, and use db (not db array) if possible for retrieval. Index the referenceid field.
I need to update a json list of object via url post data. For example, with url:
http://myweb.com/index.php?name=Peter&surname=Brown
in php, using get method:
$name = $_GET["name"];
$surname = $_GET["surname"];
$json = array();
$json["nombre"] = $name;
$json["lat"] = $lat;
$data[] = $json;
$json_end= json_encode($data);
and json_end efectively is done like I want:
[{"name":"Peter","surname":"Brown"}]
My question is about how I can do it incrementing the json, in order to build an array like:
[{"name":"Peter","surname":"Brown"}]
[{"name":"newname","surname":"newsurname"}]
// and so on
each time user use the url with new parameters.
Do I need to write to a file, or to database? Any tips will be apreciated.
The idea is to be able that any user can add some dat using url. I tried to store the json to a fiel but the storing is durable only along the current session.
<?
/* This needs to be at the top of your file, without ANYTHING above it */
session_start();
/* ... */
if(!array_key_exists('entries', $_SESSION))
{
$_SESSION['entries'] = array();
}
$_SESSION['entries'][] = array("name" => $_GET["name"], "surname" => $_GET["surname"]);
$json_string = json_encode($_SESSION['entries']);
This would produce a single JSON. However I don't know whether you meant to or not, but your output is a series of separate JSONs. You could do this by replacing the last line above with:
$json_string = '';
foreach($_SESSION['entries'] as $entry){
$json_string.= json_encode($entry) . "\n";
}
You would also probably want a way to reset/empty the array. In which case I'd change the if test from:
if(!array_key_exists('entries', $_SESSION))
to:
if(!array_key_exists('entries', $_SESSION) || array_key_exists('reset', $_GET))
Which you could use by visiting
http://myweb.com/index.php?reset
Edit: If somewhere you add the following code:
foreach($_SESSION['entries'] as $id=>$entry){
printf("%2d: %s\n", $id, json_encode($entry));
}
You'll get a list of the json elements enumerated by their respective keys. For example, it might look like:
0: "[{\"name\":\"Peter\",\"surname\":\"Brown\"}]"
1: "[{\"name\":\"newname\",\"surname\":\"newsurname\"}]"
2: "[{\"name\":\"George\",\"surname\":\"Washington\"}]"
3: "[{\"name\":\"John\",\"surname\":\"Adams\"}]"
If you then add the following code:
if(array_key_exists('del', $_GET) && is_numeric($_GET['del']))
{
$key = (int)$_GET['del'];
if(array_key_exists($key, $_SESSION['entries']))
{
unset($_SESSION['entries'][$key]);
}
else
{
printf('<strong>ERROR: $_GET['del'] = %d but $_SESSION['entries'][%d] doesn't exist.</strong>', $key, $key);
}
}
you'll be able to delete individual json entries by specifying id as the del GET parameter.
For example,
http://myweb.com/index.php?del=2
would delete the entry corresponding to '[{"name":"George","surname":"Washington"}]';
And the remaining entries would be:
0: "[{\"name\":\"Peter\",\"surname\":\"Brown\"}]"
1: "[{\"name\":\"newname\",\"surname\":\"newsurname\"}]"
3: "[{\"name\":\"John\",\"surname\":\"Adams\"}]"
4: "[{\"name\":\"Thomas\",\"surname\":\"Jefferson\"}]"
Just make a nested array of users:
$data = array (
0 => array("name"=>"Peter","surname"=>"Brown"),
1 => array("name"=>"newname","surname"=>"newsurname")
);
echo json_encode($data);
// [{"name":"Peter","surname":"Brown"},{"name":"newname","surname":"newsurname"}]
I think it would be easiest to store the data in a session, something like this:
<?php
session_start();
if (isset($_GET['name'])) {
$_SESSION['json'][] = $_GET;
}
echo json_encode($_SESSION['json']);
?>
Edit: You may want to filter the $_GET array before storing it in the session so that you don't store values that aren't meant to be stored.
Edit: Of course, if you want to save this data for more than one session you would need to use files or a database (or perhaps a cookie). It all depends on what you want to do with the information.
I'm getting this error with my current PHP code:
Notice: TO id was not an integer: 1, 2. 1) APNS::queueMessage ->
How can I convert to an array of strings to an array of integers like in this other question: ID not integer... EasyAPNS ?
I'm basically trying to pass ids (from my database,) to newMessage() like this Apple example:
// SEND MESSAGE TO MORE THAN ONE USER
// $apns->newMessage(array(1,3,4,5,8,15,16));
// ($destination contain a string with the Ids like "1,2,3")
Here is my code below:
if (isset($destination))
{
//$destination = 1,2,..
$dest = explode(",", $destination);
if (isset($time))
{
$apns->newMessage($dest, $time);
}
else
{
$apns->newMessage($dest);
}
$apns->addMessageAlert($message);
$apns->addMessageBadge($badge);
$apns->addMessageSound('bingbong.aiff');
$apns->queueMessage();
header("location:$url/index.php?success=1");
}
I would create a wrapper function that accepts an array, and then call it.
function newMessageArray($array) {
foreach ($array as $element) {
$apns->newMessage($element);
}
}
This way, you can call newMessageArray() with an array of integers, such as array(1,2,3,4,5), and they will all be sent.
Also, you should change the variable names (from $array and $element) to something more meaningful. I don't know what you're trying to do, so I wasn't sure what names to use.
Your Question is not clear, It's only a guess work.
It seems to be error in convert integer, try
$dest = explode(",", $destination);
$destArray = array();
foreach($dest as $key => $val) {
$destArray[$key] = intval($val);
}
if (isset($time))
{
$apns->newMessage($destArray, $time);
}
else
{
$apns->newMessage($destArray);
}
Convert where the string is not integer using 'intval'.
I believe what you may be looking for is how to do this:
You have ids in your database table, right? And you are trying to get multiple ids into an array so that the array can be used in $apns->newMessage() call, right? (I checked the source for this...) But, the ids are somehow coming over as strings instead of ints.
So, you probably want to just make sure that the new array is made up of ints, like this:
function to_int($x) {
return (int)$x;
}
$dest = array_map("to_int", $dest);
There are probably other ways to do this, but this way, you at least know that you have int variables in that array. Hope that helps!
I need to truncate string and rewrite it back to array
I have got a function where I get data from data base
$data['about_text_list'] = $this->about_text_model->get_array();
I get these fields from data base : id, num, header, text, language
I need to strip_tags and truncate text with function word_limiter
foreach ($data['about_text_list'] as $items)
{
$data['about_text_list']['text'] = word_limiter($items['text'], 100);
$data['about_text_list']['text'] = strip_tags($items['text']);
}
in view I do foreach
<? foreach ($about_text_list as $line) : ?>
<td><?=$line['text']?></td>
<? endforeach; ?>
But I get error, please tell me how to do correct things like this...
In the loop in your controller, you're limiting the word count, then setting that to the value in the array. Then, you're overwriting that value with the strip_tags function. You're using both functions on the same value instead of using the altered values. (And I would strip the tags first, then limit the word count.)
You're also just overwriting the $data['about_text_list']['text'] value each iteration. I'm assuming this needs to be an array of 'text' values? I would create a new array with the updated content and merge your $data['about_text_list'] array with the new array.
Change that loop to this:
$newarray = array();
foreach ($data['about_text_list'] as $key => $value)
{
$item_text = $value['text'];
$altered = strip_tags($item_text);
$newarray[$key]['text'] = word_limiter($altered, 100);
}
$data['about_text_list'] = array_merge($data['about_text_list'], $newarray);
// here, you create a new empty array,
// then loop through the array getting key and value of each item
// then cache the 'text' value in a variable
// then strip the tags from the text key in that item
// then create a new array that mirrors the original array and set
// that to the limited word count
// then, after the loop is finished, merge the original and altered arrays
// the altered array values will override the original values
Also, I'm not sure what your error is (as you haven't told us), but make sure you're loading the text helper to give you access to the word_limiter function:
$this->load->helper('text');
Of course, this all depends on the structure of your array, which I'm guessing at right now.