Any idea if PHP's memcached module supports some kind of isset() method?
Following case:
Memcached::set('foo', false);
if(Memcached::get('foo') === false) {
// Set or not set?
}
according to the documentation
if($memcached->get('var') === false && $memcached->getResultCode() == Memcached::RES_NOTFOUND){
//not set
}
You can of course extend the Memcached object to include it, however, you can't ask if it's set without getting it (some overhead on larger values):
class YourMemcached extends Memcached {
function var_isset($var){
return $this->get($var)!==false || $this->getResultCode() != Memcached::RES_NOTFOUND;
}
}
(you can't use isset as a method name as it's a language construct apparently).
Related
Why does Codeignitor not accept Controller in composer autoload when validating routes?
It's checking by: class_exists($class, FALSE) where the second parameter disables checking in autoload.
https://github.com/bcit-ci/CodeIgniter
$e404 = FALSE;
$class = ucfirst($RTR->class);
$method = $RTR->method;
if (empty($class) OR ! file_exists(APPPATH.'controllers/'.$RTR->directory.$class.'.php'))
{
$e404 = TRUE;
}
else
{
require_once(APPPATH.'controllers/'.$RTR->directory.$class.'.php');
if ( ! class_exists($class, FALSE) OR $method[0] === '_' OR method_exists('CI_Controller', $method))
{
$e404 = TRUE;
}
elseif (method_exists($class, '_remap'))
{
$params = array($method, array_slice($URI->rsegments, 2));
$method = '_remap';
}
elseif ( ! method_exists($class, $method))
{
$e404 = TRUE;
}
/**
* DO NOT CHANGE THIS, NOTHING ELSE WORKS!
*
* - method_exists() returns true for non-public methods, which passes the previous elseif
* - is_callable() returns false for PHP 4-style constructors, even if there's a __construct()
* - method_exists($class, '__construct') won't work because CI_Controller::__construct() is inherited
* - People will only complain if this doesn't work, even though it is documented that it shouldn't.
*
* ReflectionMethod::isConstructor() is the ONLY reliable check,
* knowing which method will be executed as a constructor.
*/
elseif ( ! is_callable(array($class, $method)))
{
$reflection = new ReflectionMethod($class, $method);
if ( ! $reflection->isPublic() OR $reflection->isConstructor())
{
$e404 = TRUE;
}
}
}
Looking over the git history, the change was introduced in 49e68de96b420a444c826995746a5f09470e76d9, with the commit message being:
Disable autoloader call from class_exists() occurences to improve performance
Note: The Driver libary tests seem to depend on that, so one occurence in CI_Loader is left until we resolve that.
So the nominal reason is performance.
If you want to ensure that the controller classes will be loaded on each request, you can add the files explicitly to the Composer autoload.files attribute, like so:
composer.json
{
"autoload": {
"files": [
"src/Foo.php"
]
},
"name": "test/64166739"
}
src/Foo.php
<?php
class Foo {}
test.php
<?php
$loader = require('./vendor/autoload.php');
var_dump(class_exists('Foo', false));
When run (via php test.php for example), we get the following output:
bool(true)
Additional
Looking over the code around that call to class_exists, it would appear that the controller files should follow a convention such that, for example with the built in Welcome controller and the default settings, the file that defines it should exist at:
application/controllers/Welcome.php
and so after require_onceing that file, the call to class_exists is a reasonably simple sanity check to ensure that the file did in fact define that class. So, based on this assumption about how controllers are added to the CodeIgniter application (ie all in the application/controllers directory and named the same as the class that they define), it's reasonable to bypass the autoloader when performing that check.
If you wanted to ensure the controllers are loaded when needed, the CodeIgniter way, they should be added to the application as listed above.
I need to know if there is a better way to avoid Call to a member function xxxx() on null
currently I'm coding as follows but it is cumbersome.
if($event->getForm()
&& $event->getForm()->getParent()
&& $event->getForm()->getParent()->getParent()
&& $event->getForm()->getParent()->getParent()->getData()
&& $event->getForm()->getParent()->getParent()->getData()->getComponente()
){
$componente = $event->getForm()->getParent()->getParent()->getData()->getComponente();
$formModifier($event->getForm(), $componente, $defaultComponente);
}
In PHP 7 this is actually a catchable Error (if you're using hhvm it's a regular Exception):
try {
$componente = $event->getForm()->getParent()->getParent()->getData()->getComponente();
} catch (\Error $e) {
$componente = null;
}
if ($componente !== null) {
$formModifier($event->getForm(), $componente, $defaultComponente);
}
In PHP 5 there is a workaround using intermediate variables and the and keyword instead of &&:
if (
$f = $event->getForm() and
$p = $f->getParent() and
$p2 = $p->getParent() and
$d = $p2->getData() and
$componente = $d->getComponente()
) {
$formModifier($f, $componente, $defaultComponente);
}
If you use && instead of and you'll get "undefined variable" notices and this workaround won't work.
Working examples: https://3v4l.org/0S6ps
no there is no way, but at least you can do some performance improvement
$form = $event->getForm();
if(!$form){
//do error handling
return;
}
$parent = $form->getParent();
if(!$parent){
//do error handling
return;
}
$p_parent = $parent->getParent();
if(!$p_parent){
//do error handling
return;
}
$data = $p_parent->getData();
if(!$data){
//do error handling
return;
}
$component = $data->getComponente();
...
this way you call each function only once and you can do better error handling
I think this is a great example of a bad code. By having a code like this you're breaking several rules and making your life much harder than it should be.
Your code is rigid, fragile, hard to understand and maintain etc.
Simpler is ALWAYS better.
If you can't make your $xx->getComponent() a proper object easily accessible without such ugly nested relationship, you should at least encapsulate the method into something appropriate and use that instead, so if anything changes, you don't have to go full mental and change it all over the place.
This class seems strange in it's creation, but if you are not extracting these methods dynamically using __call(), you can use method_exists() in a loop inside a function, something similar to:
function getMethodChain($class,$arr = ['getForm','getParent','getParent','getData','getComponente'])
{
# First check the object is set
if(!is_object($class))
return false;
# Loop intended method chain
foreach($arr as $method) {
# Check if the method exists in the current class or passed already
$useClass = (!isset($classPass))? $class : $classPass;
# Check if the method exists in the current class
if(is_object($useClass) && method_exists($useClass,$method)) {
# Assign this class/method to use next in the loop
$classPass = $useClass->{$method}();
}
else
return false;
}
# Just send back
return (isset($classPass))? $classPass : false;
}
The use would be something like:
# This will either be the data you expect or false
$componente = getMethodChain($event);
I am trying to design a Database($db) Mock with Atoum that would return different values depending on previous method calls (and arguments).
I'm using PHP 5.6 and Atoum 3.2
Here is what I tried:
$this->calling($db)->select = function($table, array $bind, $boolOperator = "AND") use ($permissionClientMapper, $db, $permissionsClientRaw){
if($table === $permissionClientMapper->getTableName()){
$this->calling($db)->fetchAll = function() use ($bind, $permissionsClientRaw){
if(array_key_exists('type_service', $bind) && array_key_exists('id_service', $bind) && $bind['type_service'] === 'mutu' && $bind['id_service'] === 4012){
return EXPECTED_RETURN_VALUE;
}
return null;
};
}
};
I would except the code to return the EXECTED_RETURN_VALUE when I call (with arguments):
1/ $db->select() -> This method is called as expected
2/ $db->fetchAll() -> This one is never called
I didn't find any example of this in the Atoum documentation.
Can someone confirm this is the correct way to mock successive method calls ?
I also tried to use a reference to the database in the closure
$this->calling($db)->select = function($table, array $bind, $boolOperator = "AND") use ($permissionClientMapper, &$db, $permissionsClientRaw){
if($table === $permissionClientMapper->getTableName()){
$this->calling($db)->fetchAll = function() use ($bind, $permissionsClientRaw){
if(array_key_exists('type_service', $bind) && array_key_exists('id_service', $bind) && $bind['type_service'] === 'mutu' && $bind['id_service'] === 4012){
return EXPECTED_RETURN_VALUE;
}
return null;
};
}
};
But this doesn't work either.
Edit: One workaround would probably be to use the atoum call order to return different values for each call, and then to test the mock to check it was called with the correct arguments.
I will give you some insight about your questions and hope give you some clue to find a way to solve it.
So to validate that a mock method is not called, you can use 'call' with 'never'
$this->mock($mock)->call('fetchAll')->never();
And to be called :
$this->mock($mock)->call('select')->once();
To deal with you mock answer, you can use several things, like this
$this->calling($db)->fetchAll[0] = null; // default answer
$this->calling($db)->fetchAll[1] = function () {....} // first call to method
If you want something like a chain : when use the mocked method select, and inside it we call fetchAll method then the answer is ... atoum doesn't offer yet this behavior. The best is to create an issue exposing your case.
When you use 'calling' you define the behavior of the mock. It's only when the method is called, that atoum will grab everything and resolve it.
So for me, if I understand correctly your question, I will write it like that :
$this->calling($db)->fetchAll = function() use ($bind){
if(array_key_exists('type_service', $bind) && array_key_exists('id_service', $bind) && $bind['type_service'] === 'mutu' && $bind['id_service'] === 4012){
return EXPECTED_RETURN_VALUE;
}
return null;
};
$this->calling($db)->select = function($table, array $bind, $boolOperator = "AND") use ($permissionClientMapper, $db){
if($table === $permissionClientMapper->getTableName()){
return $db->fetchAll();
}
};
// this is the same as your code. But It a bit more readable
$this->newTestedInstance;
$this->testedInstance->setDb($db);
$this->variable($this->testedInstance->doTheCallThatReturnNull())
->isEqualTo(null);
// do some change in the vars to be in the value
$this->variable($this->testedInstance->doTheCallThatReturnValue())
->isEqualTo(EXPECTED_RETURN_VALUE);
ps : to help you going further you can read http://docs.atoum.org/en/latest/asserters.html#mock and http://docs.atoum.org/en/latest/mocking_systems.html
and you can also tag the question with 'atoum'.
Is this always safe or could it cause errors in some cases?
if(isset($myVar) && $myVar->myProp !== 'error') {
...
This seems to be a case of defining properties on the fly. While it's possible (and valid) to use property_exists(), it would be much better to actually enforce the existance of the property in the class definition:
Class someExample {
public $myProp = false; // now it will ALWAYS exist for any instance of someExample
}
Yes, it will cause an error if the property doesn't exist. Check it exists with property_exists
$myVar = new myVar();
if( (isset($myVar) && property_exists('myVar', 'myProp'))
&& $myVar->myProp !== 'error' ) {
}
is there a class to handle $_REQUEST that makes the life of a php developer easier?
I want to handle the client requests easier.
I dont want to test with if(is_set($_REQUEST['blabla'])) {makesomthing();}
I wish there could be a solution like this.
class rpclike
{
public function getMember()
{
$memberid = $this->inputhandler['memberid'];
$member = $this->memberclass->getmember($memberid);
foreach($member as $mem)
{
echo $mem->id;
}
}
}
$rpc = new rpclike();
then if i call the rpclike from a javascript like this
Get member
Which class can do something like that?
It's not recommended that you use $_REQUEST as it poses security concerns. You should be using one of $_GET, $_POST, or $_COOKIE depending on what global request var you are trying to retrieve. Your best bet would be to have something like the following:
class input {
public static function get($key, $value = false) {
return (!empty($_GET[$key])) ? $_GET[$key] : $value;
}
public static function post($key, $value = false) {
return (!empty($_POST[$key])) ? $_POST[$key] : $value;
}
public static function cookie($key, $value = false) {
return (!empty($_COOKIE[$key])) ? $_COOKIE[$key] : $value;
}
}
You could then use the class like:
if (input::post('field', null) != null) {
}
or
if (input::get('field', false) != false) {
}
Although this still requires testing, you can explicitly set the return values in the event no data was set for the global variable.
PHP doesn't really have a default class structure that you can utilize in that kind of manner, as it's origins are in procedural-based programming.
It would be fairly trivial for you to create a class like that if you felt the need for it. However, you would really just be adding overhead. If the convenience of it is worth it for you, then you could utilize the __get() and __set() methods to handle existence checks for you.
The fact that you want to use this for handling client requests in an easier fashion is probably a good indicator that you should move to something like an MVC framework, which usually handle URLs and route them to appropriate methods for you automatically. Most PHP frameworks will do this for you already. For a nice overview on how the process commonly works, you could see how CodeIgniter does it.
Aside from the obvious security risks involved in this, it is feasible. It's a common pattern to use for steering requests in an MVC system.
Say you request index.php?class=User&method=ViewProfile
$module = new $_GET['class']();
if(!method_exists($module,$_GET['method']))
$module->$eventName();
I don't think so. Being able to invoke an arbitrary method would be a massive security hole.
Do something like:
url: /foo/bar?req=getMembers&memberid=22
Then you can do:
$request = $_GET['req'];
$request();
Slightly less dangerous version:
$req_methods = array(
getMembers => 'some_function',
saveMembers => 'another_function',
sendMessage => 'send_him_an_email'
);
$request = $_GET['req'];
$req_methods[$request]();