PHP serialize() is not properly serializing stdClass object - php

I have an application running on Google App Engine (using PHP 5.5.38), and I'm using a Laravel package for caching query results.
This worked well for a similar project, but for this one, I get errors such as, "unserialize(): Error at offset 14 of 860 bytes" (the numbers vary, depending on what was serialized.)
The error occurs in a class that has only these two functions:
public function encode($data){
return serialize($data);
}
public function decode($data){
return unserialize($data);
}
I found that when testing the app locally, everything works correctly, and the serialized data looks something like this:
a:1:{i:0;O:8:"stdClass":27:{s:2:"id";i:2;s:10:"first_name";s:4:"Zach";...
But when I run it on App Engine with the same data, it returns this:
a:1:{i:0;O:8:"#*lass":27:{s:2:"id";i:2;s:10:"first_name";s:4:"Zach";...
It might not show here, but there are invisible characters next to the '*' (in notepad++, they show up as [ENQ] and [DLE]).
I believe that the call to unserialize() fails because the serialized data contains #*lass instead of stdClass, but I don't know what's causing it, or how to prevent it. I tried using str_replace, and it worked at first, but not for everything. I also made sure that PHP was using UTF-8 as the default charset.
EDIT: I modified the encode function to try to pinpoint the moment the trouble starts.
I now have:
public function encode($data)
{
$serialized = serialize($data);
try{
unserialize($serialized);
} catch (\Exception $ex) {
var_dump($serialized);
die;
}
return $serialized;
}
And when it's executed on the server, it outputs:
a:1:{i:0;O:8:"#*lass":27:{s:2:"id";i:2;s:10:"first_name";s:4:"Zach"; ...
So it seems like the problem starts with before anything is saved or unserialized.

Probably not an ideal fix, but this seems to work...
public function encode($data)
{
return serialize(json_decode(json_encode($data), true));
}
public function decode($data)
{
return json_decode(json_encode(unserialize($data)));
}
The problem seemed to come from serializing an array of stdClass objects, so I figured it would help to convert stdClass to associative arrays.

This works for me
$data = json_decode(json_encode($data), true);
$data_serialized = serialize($data);

Related

How do you properly clear a json_encode error state?

I am using a PHP 5.6.40 development environment. Many of my classes implement JsonSerializable. The jsonSerialize method of one of these classes uses json_decode, since the value of one of its data members may or may not be encoded as JSON. The problem is that after calling json_decode on a data member whose value is just a plain string, the json_encode fails.
Here is an example:
class JsonSerializableClass implements JsonSerializable
{
private $dataMember;
public function __construct($dataMember)
{
$this->dataMember = $dataMember;
}
public function jsonSerialize()
{
$decodedDataMember = json_decode($this->dataMember, 1);
if ($decodedDataMember && $decodedDataMember['jsonDataMember'])
{
return $decodedDataMember['jsonDataMember'];
}
// json_encode(''); This keeps json_encode from failing, but I'm looking for a different solution.
return $this->dataMember;
}
}
// This works
$test1 = new JsonSerializableClass(json_encode(array(
'jsonDataMember' => 'plain string'
)));
var_export(json_encode($test1));
// This fails
$test2 = new JsonSerializableClass('plain string');
var_export(json_encode($test2));
This is fixed by adding a call to json_encode in the jsonSerialize method after the failed json_decode; however, another developer may not immediately realize what that accomplishes. Of course I would comment my reasoning for doing it, but I'm looking for a more clear solution. Is there error state data that json functions rely on that is being cleared by a successful json_encode? If so, is there a way to clearly reset that error state data, like clear_json_error_state?
I'm sorry if my explanation is hard to understand; it was difficult for me to explain. Please ask me for any clarification you need.
I downgrade the version to V4.1.5, It works.
"name": "pusher/pusher-php-server", "version": "v4.1.5",

Testing method with no output

I have the following method I want to test:
class SomeObject {
public function actionFromSomeController() {
$obj = new OtherObject();
$obj -> setAttributes();
$obj -> doAction();
}
}
class OtherObject {
private $_attr;
public function setAttributes() {
$this -> _attr = 'something';
Database :: execute('INSERT INTO table VALUES (' . $this -> _attr . ')');
$fileObj = new FileObj();
$content = $fileObj -> getSomeFileContent();
// do something else
}
public function doAction() {
echo $this -> _attr;
}
}
Now I want to test this method, its output depends on database content and one file on the server. It does a lot of things on the way, and the output is just one ID and success => 1.
How should I test it properly?
Some ideas on how to test small code pieces like this:
Generate test-data and pass it to your methods (also, fake database return data or file contents)
Use echo / var_dump() / die() to check property and variable content at different positions in your methods
Also use these commands to check whether execution reaches a certain point (for example to see whether a function got called or not)
If something doesn't work as expected without an error message: Check line by line with the above methods until you find the problem
Consider using interfaces and dependency injection if your code gets bigger - this is a bit over-the-top for this amount of code, but can be a tremendous time-saver when your application becomes big
Testing is never an automatic process and you will always have to think about what makes sense to do and what not. These things to do are never magic but basic PHP.
You should consider letting your scripts throw errors/exceptions if something goes wrong. Writing "silent" applications is almost never good since you can, if you really need a silent execution for production environments, just turn off error reporting and have the same effect. Many PHP functions return something special on failure and/or success and you can check for this. Database handlers do so, too. Do yourself a favor and use these return values!

How to print out value on controller Laravel?

I'm beginner on Laravel...
How to debug some value on controller in Laravel, result can show to console like syntax console.log() on javascript?
example controller function :
class TestMeController extends Controller {
public function __construct()
{
$this->middleware('jsonify');
}
public function callMe($id)
{
$params = Request::all();
console.log($id); <== how to write code on Laravel?
}
}
In Laravel use dd($id) or if you don't want to halt the execution, you can use dump($var).
You can still always use PHP's native functions like var_dump, die and print_r.
You can Use these several methods for printing in Laravel.
1. dump($var)
2. dd($id)
3. var_dump($var)
4. die($var)
5. print_r($var)
dd($var) is great because it stops the program after it runs so by moving it around you get a good sense of which line of code is causing an error.
In my case I am using laravel 7 with blade templates and to test my controller
(MVC ARCHITECHTURE)
I usually use:
return dd($variable)
or even just
return $variable
If you just want to see the data
$events = new Event();
echo "<pre>";
print_r($events->all()->toArray());
echo "</pre>";
die;
Use a return response with json:
return response()->json($dataVar, status_code);
instead console.log();
return response()->json($id, 200);

PHP variable loses its value

I have a really serious problem that I have not seen before.
On a website we are using opensource SQC eshop, PHP Version 5.3.3-7+squeeze15 and there is some kind of problem with variable memory I think.
SQC uses notORM and here the problem starts with fatal error "Call to function on non object notORMResult" .
So I dug deeper and found the constructor of NotORM that looks like this:
function __construct(PDO $connection, NotORM_Structure $structure = null,NotORM_Cache $cache = null) {
$this->connection = $connection;
if($_GET['test']){
var_dump($structure);
}
if (!isset($structure)) {
$structure = new NotORM_Structure_Convention;
}
if($_GET['test']){
var_dump($structure);
}
$this->structure = $structure;
if($_GET['test']){
var_dump($this->structure);
exit("1");
}
$this->cache = $cache;
}
And so the output is NULL because the constructor gets no structure param so we create an object. Second output is the object. Then we set the object to attribute and then the THIRD OUTPUT IS NULL
How is this even possible? The site was running for about year and half and no problems till yesterday. I didn't made yet any updates to php and this thing really freaks me out 'cause it's not a constant problem. It just happens sometimes after 2 hours, sometimes after 2 mins and I have really no idea why is this happening.
And btw ... this is just the start it happens across the whole script. Object attributes are set but when you want to read them they give you NULL. There is also second website running on the same server, same php same configuration without problem.
Thanks for any ideas :)

Seemingly random SoapFault: not a valid method

I'm experiencing a problem with my SOAP solution. Sometimes I get an error saying the following:
Function (functionA) is not a valid method for this service
Edit 8 months later
Although I could not find the cause of the problem I was able to work around it. Whenever I recieve an response from the API I check for the SoapFault and just send another identical request and use the answer that comes back the second time.(posted as an answer)
This occurs in calls from PHP like:
functionA() - expected response
functionA() - expected response
functionA() - SoapFault
functionA() - expected response
Same result is to be expected in all the above calls and the same parameters are used(if any). Since it's working fine for almost all calls I know that the function and the corresponding WSDL is there.
What I thougt were the problem was caching an old version which would not have that function. I tried disabling the caching with:
ini_set("soap.wsdl_cache_enabled", "0");
And makeing every call with added with a random dummy parameter as well as disabling it when I use Zend_SoapClient.
'cache_wsdl' = false
I hope someone could point me in any direction or have any direct suggestion on what could be the cause.
My code looks like:
public function __construct()
{
$wsdl = "http://catlovers.nl/index.php?wsdl&dummy=".rand(1000,9999);
$this->_client = new Zend_Soap_Client($wsdl, array(
'soapVersion' => SOAP_1_1,
'cache_wsdl' => false
));
$this->_client->setWsdlCache(false);
}
function __call($name, $arguments) // Calls are made this way
{
array_unshift($arguments, $this->_apiKey, $this->_user, $this->_password);
return call_user_func_array(array($this->_client, $name), $arguments);
}
public function getCat()
{
return ($this->__call('getCat',array()));
}
On "the other side" I have:
$server = new nusoap_server();
$server->wsdl->addComplexType('Cat', ....
$server->register( 'getCat', return Cat ...
function getCat($apikey, $email, $password)
{
$cat = $db->get("redCat");
return $cat;
}
First of all, try to call function using built-in SoapClient class and printing debug information:
$wsdl = "http://abcd.com/index.php?wsdl&dummy=".rand(1000,9999);
$soap = new SoapClient($wsdl, array(
'cache_wsdl' => WSDL_CACHE_NONE,
'trace' => true,
));
try {
var_dump($soap->functionA());
} catch ( Exception $ex ) {
var_dump($ex);
}
var_dump($soap->__getLastRequest());
var_dump($soap->__getLastRequestHeaders());
var_dump($soap->__getLastResponse());
var_dump($soap->__getLastResponseHeaders());
This way you'll know where is the problem. If everything is ok all the time, the problem is in Zend's class. If not, look what service responds. May be there is some server-side error or dummy generation with such id fails
I guess your problem is related to nusoap, because for many years I'm using PHP soap server/client and I never faced this problem. (but I always had strange problems with nusoap lib)
currently I'm using jool.nl web service helper which is very powerfull yet neat and object oriented library not only makes coding easier and cleaner but also provides you object oriented approach to web service designing. It also provides a nice web interface for your web service with documentation.
As this library uses internal PHP SOAP server I'm pretty sure you're problem will be disappear then.
I suggest you to give it a try and I'm sure if you make your first web service with this library you will never try something else.
I hope this helps you.
So the problem was still there after trying other solutions so I was never able to find underlying cause of the problem. On the other hand I found a way to work around the problem that has been working since I wrote it. This is how my call to the API looks like with user,password and key for authentication.
function __call($name, $arguments)
{
/* Using the stored data to ensure that the user is allowed to access */
/* ............... */
array_unshift($arguments, $this->_apiKey, $this->_user, $this->_password);
$call = call_user_func_array(array($this->_client, $name), $arguments);
if(isset($call->faultstring) && substr(trim($call->faultstring),0,7) == "Function")
{
$recall = call_user_func_array(array($this->_client, $name), $arguments);
return $recall;
}
else
return $call;
}
This is basicly: if it doesn't work the first time just try again.

Categories