some of session varibles gets back to the old value - php

i use centos 6.6, php 5.3.4
I have a php script called in an iframe(let's call it a.php)..
when it's called as a.php?p_type=1&item_num=1234,
it saves an array into session.
sometimes, it merges two array in session and save it into session again
but the merging doesnt work..
here is the simplified code.
(i will hide minor details for brevity)
header('P3P: CP="CAO PSA OUR"');
session_start();
$p_type_val = $_GET["p_type"];
$sess_var = "a".$p_type_val;
$some_array = $_SESSION[$sess_var];
if(isset($_GET["item_num"])
{
$some_array[] = $_GET["item_num"];
$_SESSION[$sess_var] = $some_array;
}
if($p_type_val == 1) // when p_type is 1, merge two arrays in the session.
{
$sess_var2 = "a"."2";
$some_array2 = $_SESSION[$sess_var2];
$_SESSION[$sess_var2] = array_merge($some_array,$some_array2);
}
else if($p_type_val == 2)
{
$some_array2 = $_SESSION["p2"];
print_r($some_array2);
}
.........
first, i called a.php?p_type=1&item_num=1234, then i called a.php?p_type=2 lator,
then the newly added item number 1234 to "a2" is lost. the values in the array "a2" is back to the old values.
but the values in "a1" are no problem.
i checked the session file in /var/lib/php/session directory and found all the result is as i expected.
after i called a.php?p_type=1, the values in the file are as i expected.
but right after a.php?p_type=2, the values go back to the old ones.
the funny thing is when i call a.php?p_type=2 twice with diffrent item_nums,
the array "a2" works correctly.
i don't know why the some values in a session go back to old values.
where should i start debugging for this..
any suggestion would be appreciated..

i guess your problem is you don't read the manual about it, no rudeness intended but it clearly say there than when you merge two arrays that can happend, explain also the 'whys' of it, because of that i suggest you read the stuff entirely, no kittin, there is some overlapping examples explained in the section of examples of the manual too, and explain how to avoid/use that "problem".
it textualy says:
"If the input arrays have the same string keys, then the later value for that key will overwrite the previous one. If, however, the arrays contain numeric keys, the later value will not overwrite the original value, but will be appended."
So, probably you are using the same string values in both $_SESSION variables, or both of them have the same int to index data, i told you, it is necesary to see the creation of the $_SESSION, otherwise i cant see the compositions of that arrays that you are merging and, because of that, i can't suggest one way to solve the problem oriented to your necesitys.
which, in fact, you are not saying, you are merging two $_SESSION variables but not saying why is that for, and taking that in perspective, the rest of the people cannot even know if that is the right aproach for what you want.
Anyway, your solution is to read that part of the manual & instanciate that to your code.
http://php.net/manual/en/function.array-merge.php
Have a good day

Related

Overwrite the original array values in PHP in nested loop

Cutting out some of the code on the innermost foreach, I'm trying to change HERE to make it so that it alters the original value. I want to pass a pointer basically and alter it. I was able to kind of do this with the &$ keyword in the foreach but (as the docs state) it results in some buggy behavior and I'm trying to do it the way they, and others on SO suggest. The problem is all the examples I find are for a single foreach, not for nested.
The following code loops properly but when I get to the HERE it doesn't actually alter the original value. Also worth mentioning that $sources could be an array of arrays (by index) or an array of key values. This looping code seems to iterate over both fine though, just not overriding the original value of $sources
fwiw, on top of the &$ I also tried:
$sources[$sourceKey][$rowKey][$cellKey] = $date->format('m/d/Y');
Which $sources[$sourceKey][$rowKey][$cellKey] returns the right value if I print it but it still doesn't overwrite the original array.
function convertDates($sources) {
foreach($sources as $sourceKey => $sourceValue){
foreach ($sourceValue as $rowKey => $rowValue) {
foreach ($rowValue as $cellKey => $cellValue) {
HERE = $date->format('m/d/Y');
}
}
}
}
I never could get this to work correctly since there were two formats this loop could get (JSON encoded object and an array). Making it work for both was much harder than just doing it in JavaScript so instead of modifying on the server I format the data how I want client side and send it up. This formatting is purely presentational and for personal use so if someone were to put in a debugger and change the code to send a different format thats fine and there's no security issues.
So in the end, this code was rewritten in JS and since JS handles arrays and objects using the same pointers the above issue wasn't an issue any longer.

I need to add fields to a JSON string in PHP, but I'm having problems

So... I need to save a large-ish amount of data from a platform with an excruciatingly limited amount of memory.
Because of this, I'm basically storing the data on my webserver, using a php script to just write JSON to a flat file, because I'm lazy af.
I could go to the trouble of having it store the data in my mysql server, but frankly the flat file thing should have been trivial, but I've run up against a problem. There are several quick and dirty workarounds that would fix it, but I've been trying to fix it the "right" way (I know, I know, the right way would be to just store the data in mysql, but I actually need to be able to take the json file this produces and send it back to the platform that needs the data (In a ridiculously roundabout fashion), so it made sense to just have the php save it as a flat file in the first place. And It's already working, aside from this one issue, so I hate to reimpliment.
See... Because of the low memory on the platform I'm sending the json to my server from... I'm sending things one field at a time. Each call to the php script is only setting ONE field.
So basically what I'm doing is loading the file from disk if it exists, and running it through json_decode to get my storage object, and then the php file gets a key argument and a value argument, and if the key is something like "object1,object2", it explodes that, gets the length of the resulting array, and then stores the value in $data->$key[0]->$key[1].
Then it's saved back to disk with fwrite($file, json_encode($data));
This is all working perfectly. Except when $value is a simple string. If it's an array, it works perfectly. If it's a number, it works fine. If it's a string, I get null from json_decode. I have tried every way I can think of to force quotes on to the ends of the $value variable in the hopes of getting json_decode to recognize it. Nothing works.
I've tried setting $data->$key[0]->$key[1] = $value in cases where value is a string, and not an array or number. No dice, php just complains that I'm trying to set an object that doesn't exist. It's fine if I'm using the output of json_decode to set the field, but it simply will not accept a string on its own.
So I have no idea.
Does anyone know how I can either get json_decode to not choke on a string that's just a string, or add a new field to an existing php object without using the output of json_decode?
I'm sure there's something obvious I'm missing. It should be clear I'm no php guru. I've never really used arrays and objects in php, so their vagaries are not something I'm familiar with.
Solutions I'm already aware of, but would prefer to avoid, are: I could have the platform that's sending the post requests wrap single, non-numeric values with square braces, creating a single item array, but this shouldn't be necessary, as far as I'm aware, so doing this bothers me (And ends up costing me something like half a kilobyte of storage that shouldn't need to be used).
I could also change some of my json from objects to arrays in order to get php to let me add items more readily, but it seems like there should be a solution that doesn't require that, so I'd really prefer not to...
I skim through your post.
And I know this works for StdClass :
$yourClass->newField = $string;
Is this what you wanted ?
OK so... ultimately, as succinctly as possible, the problem was this:
Assuming we have this JSON in $data:
{
"key1":
{
"key2":["somedata","someotherdata"]
}
}
And we want it to be:
{
"key1":
{
"key2":["somedata","someotherdata"],
"key3":"key3data"
}
}
The php script has received "key=key1,key3&value=key3data" as its post data, and is initialized thusly:
$key = $_POST["key"];
$key = explode($key,",");
$value = $_POST["value"];
...which provides us with an array ($key) representing the nested json key we want to set as a field, and a variable ($value) holding the value we want to set it to.
Approach #1:
$data->$key[0]->$key[1] = json_decode($value);
...fails. It creates this JSON when we re-encode $data:
{
"key1":
{
"key2":["somedata","someotherdata"],
"key3":null
}
}
Approach #2:
$data->$key[0]->$key[1] = $value;
...also fails. It fails to insert the field into $data at all.
But then I realized... the problem with #2 is that it won't let me set the nonexistent field, and the problem with approach #1 is that it sets the field wrong.
So all I have to do is brute force it thusly:
$data->$key[0]->$key[1] = json_decode($value);
if (json_decode($value) == NULL)
{
$data->$key[0]->$key[1] = $value;
}
This works! Since Approach #1 has created the field (Albeit with the incorrect value), PHP now allows me to set the value of that field without complaint.
It's a very brute force sort of means of fixing the problem, and I'm sure there are better ones, if I understood PHP objects better. But this works, so at least I have my code working.

Using explode with setcookie to set one cookie with multiple name and values

I really not getting how to do this
From PHP Manual
Cookies names can be set as array names and will be available to your
PHP scripts as arrays but separate cookies are stored on the user's
system.
This is okay to me and I got and could use like below
setcookie("cookie[three]", "cookiethree");
setcookie("cookie[two]", "cookietwo");
But this method will create multiple cookies and that is I don't want
PHP manual also says
Consider explode() to set one cookie with multiple names and
values.
But I did not get how to use explode to set one cookie with multiple names and values?
Please someone explain this.
But not getting this
Cookies are nothing else than a dumb key/value storage system. It's as simple as that.
It happens that PHP offers a nifty feature on top of that: cookies whose names contain square brackets in the described format will be combined into a single array variable when reading cookies back from PHP. But that's the only exception, it doesn't affect the way cookies work and, as you've said, it's a feature you don't need.
Said that, you only need to think of the cookie value as a whiteboard where you can put anything you want, as long as it's text. And there're many PHP functions that allow you to convert exotic stuff like arrays into plain text:
serialize()
json_encode()
implode()
...
Use your imagination and you're done ;-)
Update: A little remarkā€”I've mentioned serialize() for completeness, but it's probably not worth the effort since it'd be very complicate to ensure you don't open the door to code injection.
Use Serialize and Unserialize
Ex :
$ckArr= array();
$ckArr['abc'] = "abc";
$ckArr['xyz'] = "xyz";
$ckArr['pqr'] = "pqr";
$ckStr= serialize($ckArr);
setcookie("mycookie", $ckStr, $time, $servername);
And you can unserialised it using :
$cookieContent = unserialize($_COOKIE['mycookie']);
print_r($cookieContent);
You can set a cookie like this:
setcookie("cookiename", "value1;value2;value3;value4");
and then use explode like so:
$a = explode(';', $_COOKIE['cookiename']);
Then you will get an array of values from a single cookie.
It is also saying you should not do this... in the following sentence of the doc.
setcookie("cookiename", serialize( array("value1", "value2", "value3") );
// next request
$a = unserialize($_COOKIE['cookiename']);
because that is unsafe as users can modify their cookies to non-array values.

$data = array() vs unset($array)

this is my first question.
I am doing some optimizations on a php script, improving its speed of execution...
Between :
$datas = array();
$datas['file_import'] = $file_name_reporting;
And :
unset($datas);
$datas['file_import'] = $file_name_reporting;
Can someone tell me which one is faster ?
Thank you
Your second example causes warning, because $datas is right now null and you are treating it as an array, so you have to declare it as an empty array before.
So just follow your first example - assign an empty array and then put into it some data.
array() will create an array whereas unset() will destroy a variable.
I think first method is just a overwriting but second one includes deleting, checking existence, triggering warning and creating new array
It's ridiculous to claim that either form is "faster" than the other. Both versions will execute so fast that you would need to run them millions of times inside a loop to perhaps notice a difference. Do you actually do that inside your script? If not, forget about "optimization" here (actually, it would be a good idea to forget about all optimization "by eye", as any experienced developer can tell you).
On top of that, the two versions actually do different things, in that unset will remove the name $datas from the sumbol table (and give you a notice in the next line when you attempt to add a value to an array).
Just use what feels right, and look inside heavy loops to find something to optimize.
In both cases, a new Array will be constructed. Unsetting a variable in php, will set it's value to null, only to call the array constructor on the next line. Although I agree with knittl, my suggestion would be:
$datas = array('file_import' => $file_name_reporting);
By creating a new array, you automatically 'unset' the variable, and by passing values to the array constructor, you can fill your array with whatever values you want while you're at it.
Obviously the first code will work faster because you do only two operations: explicitly create an array and add a portion of data. The second example will cause a warning because you destroy a variable and then try to use it again.
Additionally unset will not release used memory, it will only release a pointer on variable. Memory will be released when gc will be runned. To release a memory, use $datas = null; instead.

PHP Change Array Over and Over

I have any array
$num_list = array(42=>'0',44=>'0',46=>'0',48=>'0',50=>'0',52=>'0',54=>'0',56=>'0',58=>'0',60=>'0');
and I want to change specific values as I go through a loop
while(list($pq, $oin) = mysql_fetch_row($result2)) {
$num_list[$oin] = $pq;
}
So I want to change like 58 to 403 rather then 0.
However I always end up getting just the last change and non of the earlier ones. So it always ends up being something like
0,0,0,0,0,0,0,0,0,403
rather then
14,19,0,24,603,249,0,0,0,403
How can I do this so it doesn't overwrite it?
Thanks
Well, you explicititly coded that each entry should be replaced with the values from the database (even with "0").
You could replace the values on non-zero-values only:
while(list($pq, $oin) = mysql_fetch_row($result2)) {
if ($pq !== "0") $num_list[$oin] = $pq;
}
I don't get you more clear, i thought your asking this only. Check this
while(list($pq, $oin) = mysql_fetch_row($result2)) {
if($oin==58) {
$num_list[$oin] = $pq;
}
}
In my simulated tests (although You are very scarce with information), Your code works well and produces the result that You want. Check the second query parameter, that You put into array - namely $pg, thats what You should get there 0,0,0,0,0...403 OR Other thing might be that Your $oin numbers are not present in $num_list keys.
I tested Your code with mysqli driver though, but resource extraction fetch_row is the same.
Bear in mind one more thing - if Your query record number is bigger than $numlist array, and $oin numbers are not unique, Your $numlist may be easily overwritten by the folowing data, also $numlist may get a lot more additional unwanted elements.
Always try to provide the wider context of Your problem, there could be many ways to solve that and help would arrive sooner.

Categories