PHP Trait method works only on first load - php

I'm using MAMP with PHP 5.4.10 and I have a problem with the following MWE:
<?php
trait T {
public function hello() { echo 'hello'; }
}
class A {
use T;
}
$a = new A();
$a->hello();
?>
The page shows 'hello' on the first load. But then, when I hit refresh, I get an Error 500.
If I modify the file (just by adding an empty line somewhere for instance) and refresh again, 'hello' shows up again. Hit refresh again, and the Error 500 is back.
Any clue where this might be coming from?
Update:
This shows up in the PHP errors log (nothing in the Apache errors log): PHP Fatal error: Call to undefined method A::0?
()
(the 0 doesn't always have the same name when I repeat the operation).

Xcache might be the problem here, try turning caching off (or at least xcache) and try it again

I had the same problem, and thanks to the #Leon Weemen i focused on the XCache. I found this bug (which is fixed in XCache 3.0.1) to be exactly what causes the problem (my version of XCache was 2.0.0). They suggest you to set in your php.ini the following values to solve the problem;
xcache.mmap_path = "/tmp/xcache"
xcache.readonly_protection = on
However, this workaround does not solve the problem for me. The only way I was able to disable the XCache was by using the ini_set() PHP method. The following snippet at the very begginning of my application solves the problem and is ready to use XCache as soon as it is updated:
try{
$xCache = new ReflectionExtension('xcache');
if(version_compare($xCache->getVersion(), '3.0.1', '<')){
ini_set('xcache.cacher', 0);
}
} catch(ReflectionException $e){
// xCache not installed - everything should work fine
}

Related

How to make new version updating safe in PHP OpCache?

My php project is now working on Apache with mod_php. I want to open OpCache to accelerate my code. But I'm worry about if it's safe to update the code.
The validate_timestamps should be 0. Because the code may expire when you update new version, and this can make the code of new version call the code of old version.
But even if I set validate_timestamps=0, this can also happen. When I update the code file, one of the code file that hasn't been cached is called. And thus this code file is in new version while the caller is in old version. Maybe I can load all the code files into cache before the server start?
If I find a way to make sure all the files in the project dir are loaded into cache before the Apache start to serve requests, I can update new version code first, and then clear all the OpCache. But does it have an impact on those working requests? Will they run an old logic and then be switch into a new one?
Besides, how to clear all the OpCache in an atom time? If it takes time to clear all the OpCache, the problem is still there, right?
Can anyone help me? Thank you very much!
Let me show an example.
I have two files on my directory, and the Apache's working directory is also there.
The entry file is index.php.
<?php
echo "verson 1: index";
// do some work
sleep(1);
// not all APIs will call this library
// I just use rand to represent a probability
if (rand(0,100) == 1) {
require_once BASEPATH.'lib.php';
t = new Tester();
t->func1();
}
And the other php file is lib.php.
<?php
echo "---- version 1: lib";
class Tester {
function __construct() {
echo "---- new Tester in lib.php";
}
public function func1() {
echo "---- Tester.func1()";
}
}
Now I'm going to upload my new version code.
In the new version, I declare a new function func2() in Tester and delete the old function func1(). I call it in the index.php.
index.php
<?php
echo "version 2: index";
// do some work
sleep(1);
// not all APIs will call this library
// I just use rand to represent a probability
if (rand(0,100) == 1) {
require_once BASEPATH.'lib.php';
t = new Tester();
t->func2();
}
lib.php
<?php
echo "---- version 2: lib";
class Tester {
function __construct() {
echo "---- new Tester in lib.php";
}
public function func2() {
echo "---- Tester.func2()";
}
}
I close the OpCache. I upload the index.php first and then the other one lib.php. At the moment between I finish to upload the index.php and begin to upload lib.php, a request is running into the "rand case". Then I will get an error about "func2() not defined", because the lib.php is still the old one at that time.
If I open the OpCache, it's the same if I don't set validate_timestamps to 0.
After I set validate_timestamps to 0, the opcode will not expire. So I must call opcache_reset manually after I finish to upload index.php and lib.php. At that moment, a request also runs into the "rand case". If the opcache_reset operation takes a period of time, and it doesn't block the request running, the error "func2() not defined" may also occur.
How to make all the requests safe when I upgrade my code version?

PHP 7 error 500 internal

I'm completely lost with an "500 internal server error".
Yesterday I updated to PHP 7.1.2 and then there were a lot of errors.
I solved them almost all except for this strange coding error.
When trying to find the problem I echoed some output to the screen.
And this is what happens:
for($iRecordNumber=0;$iRecordNumber==$iTotalAssignments;$iRecordNumber++){
$iNextRecordNumber = $iRecordNumber+1;
echo $iNextRecordNumber;
echo $aAssignments[$iRecordNumber][2];
echo $aAssignments[$iNextRecordNumber][2];
}
With this code I get the "500-error".
When I comment out the line with echo $aAssignments[$iNextRecordNumber][2]; the error is gone and it does what it should do. Showing me a record from the nested array $aAssignments(PDO query).
for($iRecordNumber=0;$iRecordNumber==$iTotalAssignments;$iRecordNumber++){
$iNextRecordNumber = $iRecordNumber+1;
echo $iNextRecordNumber;
echo $aAssignments[$iRecordNumber][2];
// echo $aAssignments[$iNextRecordNumber][2];
}
I looked through the Backward compatabilty list but did not find anything.
And the tool codechecker says it's good too.
I dont know how this is possible.
What can I do to find an answer? Are there any programs or code checkers to check for more php 7 errors in my code. I have several php sites running and I do not want to check all code manually for errors.
I think $aAssignments[$iNextRecordNumber][2] is not always set.
You could replace:
echo $aAssignments[$iNextRecordNumber][2];
By:
echo $aAssignments[$iNextRecordNumber][2]?? '';
I hope it could help.
In PHP 7 is the error handling completly revised. A fatal error other errors no longer stops the script. To find these kind of errors, use the new error() method in the try and catch class. For example:
try{
code to test on errors
} catch(error $eCatchedError) {
echo get_class($eCatchedError)."<br>".$eCatchedError->getLine()."<br>".$eCatchedError->getFile()."<br>".$eCatchedError->getMessage();
} // End try and catch
By this way you get an more elegant way of showing an error (with css and everything)

Exception MongoCursorException: couldn't send query: ët§ôï9·H'ﯤ7·ø?u§Ht§ ö·Ì­u§®u§Ì½u§4e

I am trying to talk to a remote MongoDB server from my system. The code i use is like this
$con_string='mongodb://server_ip:27017';
$m = new Mongo($con_string);
$temp=$m->selectDB("DBName");
try {
$mc=$temp->collection_name->find()->limit(5);
var_dump($mc->info());
var_dump(iterator_to_array($mc));
}
catch (MongoCursorException $e) {
echo "error message: ".$e->getMessage()."</br>";
echo "error code: ".$e->getCode();
}
Now i get the following message from Xdebug
MongoCursorException: couldn't send query: ët§ôï9·H'ﯤ7·ø?u§Ht§ ö·Ì­u§®u§Ì½u§4e
Why is this exception raised and why is there junk at the end of exception. I dont get this exception every time but 5 out of 6 times.
Also the message i got from catch block is
error message: couldn't send query: QY¥ôï9·H§ï³¤7·DCY¥h §
error code: 14
The error code 14 means "C socket error on send." says the PHP manual.
What does this error mean?
A guy in chat suggested that the junk is indicator that the data might not be utf8_encoded but i am doing a simple find() with no criteria so what do i need to encode?
EDIT:
To get around this scenario i wrote this
function getCursor($conn,$db_name,$coll_name,$query_options=array(),$fields=array(),$cursor_options=array(),$max_tries=0) {
$counter=0;
while(1) {
try {
$cursor=new MongoCursor($conn,$db_name.'.'.$coll_name,$query_options,$fields);
if (array_key_exists('count',$cursor_options))
return $cursor->count();
if (array_key_exists('limit',$cursor_options))
$cursor=$cursor->limit($cursor_options['limit']);
if (array_key_exists('skip',$cursor_options))
$cursor=$cursor->skip($cursor_options['skip']);
if (array_key_exists('sort',$cursor_options))
$cursor=$cursor->sort($cursor_options['sort']);
return $cursor;
}
catch (MongoCursorException $e) {
$counter+=1;
if ($max_tries>0) {
if ($counter>$max_tries)
echo "error message: ".$e->getMessage()."\n";
echo "error code: ".$e->getCode()."\n";
return false;
}
}
}
}
The functions takes the query parameters and then send the query to the server and if the MongoCursorException is raised it sends the query again. It does this $max_tries times. If $max_tries is set to 0 it will keep on sending this query to the server until the query succeeds. Maybe this is stupid, i should have set this to some fixed value like 50. On success the function returns the cursor except when your looking for the count and in that case it returns the count
Your string looks like that if:
You have a charset encoding issue
Memory is broken
As in your code not much strings are involved, the chances that this is an encoding issue are not very high.
But as Xdebug is a PHP extension that deals a lot with internals, breaking memory can be one thing.
An easy way to find out is to disable the extension you suspect that is causing the issue, e.g. xdebug.
It is also useful for documentation purposes tp write down which PHP and extension versions you are using as well as on which operating system. I asked for that in comments, it's a list like:
PHP 5.3.10
Mongodb Extension 1.2.10
Mongodb Server 2.0.6
Xdebug 2.2.0
Centos 6.2 64-bit
Checking the website for xdebug shows that there is a new version available. As you have found out earlier by disabling xdebug that it influences the result, try with updating the xdebug extension and see if it helps.
Even if it does, keep your version list for further reference (as well with a short description of the problem), because in case the problem is not fully solved with the upgrade, this information can be very useful at a later time to do a useful bug-report. Those internal problems in the software are sometimes hard to spot, so the information can help to reproduce easier then or to identify the areas involved.
This is fixed in Mongo driver v1.3+
ref: https://groups.google.com/forum/?fromgroups=#!topic/mongodb-user/IJ1n_Xt_al8
Downloads: http://docs.mongodb.org/ecosystem/drivers/

apc_exist() does not exist?

I'm having some hard time getting PHP APC to work. Here's my test code:
<form>
<input type="text" name="apc">
<input type="submit">
</form>
<?php
apc_store('foo','FOO');
if (isset($_GET['apc'])) {
apc_store($_GET['apc'],$_GET['apc']);
}
?>
<pre>CACHE INFO (USER): <?php print_r(apc_cache_info("user",false)); ?></pre>
<pre>CACHE INFO: <?php print_r(apc_cache_info()); ?></pre>
<pre>FOO: <?php print_r(apc_fetch("foo")); ?></pre>
<pre>BAR: <?php print_r(apc_fetch("bar")); ?></pre>
<pre><?php if (apc_exists("bar")) { ?>bar exists!<?php } else { ?>bar does not exist!<?php } ?></pre>
<?php apc_clear_cache(); ?>
In short: you fill the form and the inserted value gets stored in APC. The key "foo" is always stored. You can try storing "bar" to see apc_fetch() working with a newly added key.
What works OK:
apc_store()
apc_fetch()
What does not:
apc_cache_info() (regardless of which parametres I pass to the function) always prints an empty array, despite apc_fetch() retrieving data successfully
apc_clear_cache() never clears the cache ("bar" is always displayed once input). This is true both if I provide a "user" parametre or leave the function with no parametres.
calling apc_exists() yields a fatal error: call to undefined function apc_exists()
In case it's helpful: I'm running Zend Server CE 5.6.0 (fresh install, finished half an hour ago), with PHP 5.3.9. Same happened with a more antique version of Zend Server CE yesterday (running PHP 5.3.5). I do not know which version of APC ships with Zend Server, phpinfo() only shows APC is enabled. I am on a Windows machine (Windows 7 Professional, 32 bit).
So. What's wrong here? Issues with my code? Maybe Zend Server ships with an older version of APC that just is buggy and/or does not support the functions I'm trying to use? Any clues?
[EDIT]
Inspired by clues provided by #Hannes, I modified the code, adding:
<?php
if (!function_exists('apc_exists') {
function apc_exists($key) { return (boolean)apc_fetch($key); }
}
?>
Since no error is raised, the code passes to the next line and the cache is cleared OK. This must have been why it wasn't cleared in the first place.
Still, apc_cache_info() doesn't return anything...
apc_exists is available for PECL apc >= 3.1.4 http://www.php.net/manual/en/function.apc-exists.php so your APC Version is probbaly lower, but its basically just a boolean wraper anyhow, a simple function shoud basically do the same:
function user_apc_exists($key){ return (bool) apc_fetch($key); }
in both cases your didint provide information for which cache to use, your probaby want user:
apc_clear_cache('user');
apc_cache_info('user);
http://www.php.net/manual/en/function.apc-clear-cache.php
http://www.php.net/manual/en/function.apc-cache-info.php
I ran across the same problem and after some debugging found out that the function in Hannes' answer works unless the stored data is a boolean false or an empty array.
This works also in those cases:
if (!function_exists('apc_exists')) {
function apc_exists($key) {
$success = false;
apc_fetch($key, $success);
return $success;
}
}

Why a PHP warning appearing in Chrome but not in any other browser?

I'm writing a web application in PHP, and I'm getting the following warning in Google Chrome only:
Warning: Cannot use a scalar value as an array in
M:\xampp\htdocs\MyProjectTitle\php\classes.php on line 18
Background: Please note that the web app works just fine in all browsers I tested (Firefox, Chrome, IE), but the warning appearing in Chrome is bugging the hell outta me.
Notes: I have tried restarting Chrome and clearing the Chrome cache. I have tried restarting the computer. I have tried searching the source code in FF and IE to see if the warning was just hidden, but to no avail. The warning is only popping up in Google Chrome, and I have no idea why.
UPDATE: Even though Safari also uses WebKit, it does not show the PHP warning. For some reason, Chrome is the only one that has the PHP warning. Weird stuff!
UPDATE: Here's the first 21 lines of code:
class Presenter {
public function includeFile($filePath) {
if (is_readable($filePath)) {
include $filePath;
} else {
echo '<p><strong>ERROR 404</strong></p>';
echo '<p>The resource you requested could not be located.</p>';
}
}
public function sanitize($string) {
return preg_replace("/\s/","_",$string);
}
public function set($varname,$value) {
$this->$varname = $value;
$_SESSION[$this->name][$varname] = $value;
return $this; // enables chaining!
}
// And there's more code after this, but I have cut it out here.
}
Note: The above code is inside a PHP class.
UPDATE: I know exactly what lines of code are causing the warning in Chrome (although I still have no clue why Chrome is the only browser that shows the warning). Since my webapp works perfectly despite the warning in Chrome, I have used # to suppress the warnings in Chrome (I'll fix the warning later).
Most likely it's this:
$_SESSION[$this->name][$varname] = $value;
if $_SESSION[$this->name] was not defined as an array earlier, you'll get the "can't use scalar as array" error. e.g. if you do
$_SESSION[$this->name] = 42;
$_SESSION[$this->name][$varname] = 'will not work';
the error is triggered.
I have the feeling that Chrome sends different data to the server, therefore you are having this error. If there's any $_POST data, or $_GET data please verify that with what other browsers send. You can easily display the contents using print_r() or var_dump() whichever you choose.
This usually happens because you do something browser-specific(maybe you do something IE specific, and firerfox-specific, but forgot to add a "default" case for other browsers?)
UPDATE: I know exactly what lines of code are causing the warning in Chrome (although I still have no clue why Chrome is the only browser that shows the warning...If you know, please let me know!). Since my webapp works perfectly despite the warning in Chrome, I have used # to suppress the warning as a temporary fix until I can fix it for real later.
Basically that is happening because you are trying to access a UNDEFINED variable (or not set variable).
PHP omits MANY common programming mistakes, that other languajes don't permit.
Ok if you start a program like:
<?php if(eregi("hi",$hello)) { echo "hi"; } ?>
Will get this "message"
Notice: Undefined variable: hello in C:\var\www\test.php on line 1
you sould predefined it as:
<?php $hello = "hello"; if(eregi("hi",$hello)) { echo "hi"; } ?>
Or a conditioned to avoid elimination of previous values:
$hello = isset($hello) ? $hello : null;
This code will send you a deprecated function message also.
any why this messages are caused by the PHP.INI configuration on your server, this is happening because you had something like this:
display_error = on;
error_reporting = E_ALL;
And sould be something like:
display_error = on;
error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT
This will remove all NOTICES messages and make PHP more permisive, also you can add ~E_DEPRECATED if you get deprecated messages,
how ever getting this messages, means that you need to be a more secitive programmer! Yes is more tediuos but some one has to make it!
Probably because you need to do ctr+f5 or restart in your other browser. It probably has a previous version of your page cached, happened to me a lot with Internet Explorer 8.

Categories