Novice question but then I am a novice at this...
I have a class for registering users and I have functions for different validation. Basically, I run "mainTest" which pulls in the variables from a form and then runs each function (test1, test2). Within those functions if something doesn't validate within the function I set a variable called $error to true. What I am trying to do within the "mainTest" function check if the variable $error has been set to true in any of the other functions do something but when I echo the $error variable it just says null i.e. the functions aren't linking. (trying not to use Global Variables).
Any Ideas here is an example of how I am doing this...
class myClass {
private function test1($var1, $var2) {
if....
else {
$error = true;
return $error;
}
}
private function test2($var3, $var4) {
if....
else {
$error = true;
return $error;
}
}
public function mainTest($var1, $var2, $var3, $var4) {
$this->test1($var1, $var2);
$this->test2($var3, $var4);
if ($error == true) {
//do something
}
}
}
use an instance variable in the class ie..
class myClass {
private $error = '';
function test2()
{
//some code here
$this->error = true;
return $this->error;
}
Now you can access the error variable in other function using the $this keyword
$this->error, here's a little reading
From what you have submitted in the way of code, all of your functions return a boolean. This means that inside of your mainTest you can do something like this:
$error = test1() || test2();
This means that if either of test1 or test2 return true, error will be set to true. But if they both fail, error is false. You can use the || operator any number of times, take my trivial example for instance:
function one(){
return false;
}
function two(){
return false;
}
function three(){
return false;
}
$var = one() || two() && three();
var_dump($var);
In this example, var will be a boolean variable set to false. However, if any one of the three functions returned true, var would of corse be true.
With this, you are semantically saying "the result of one OR the result of two OR the result of three." With || true takes precedence over false, meaning that is anything is true, the end result is true.
In your example, the problem with using the class variable approach as others have suggested, is that, what if test1() sets error to true and then test2() later sets it to false. This can of corse be overcome, however it would require more logic in your mainTest function. Essentially you would need to check the value of error after each function.
Since you're returning the TRUE boolean, you can check to see each function's output to see if it's TRUE, or not:
public function mainTest($var1, $var2, $var3, $var4) {
if ($this->test1($var1, $var2) === TRUE) || $this->test2($var3, $var4) === TRUE) {
// an error occurred, because your function returned a TRUE boolean
}
}
If you'd want to re-structure your code, you can declare a public variable as part of your class and set it using your functions.
class myClass {
// ...
private $error;
private function test1($var1, $var2) {
if....
else {
$this->error = true;
}
}
// ...
public function mainTest($var1, $var2, $var3, $var4) {
$this->test1($var1, $var2);
$this->test2($var3, $var4);
if ($this->error === TRUE) {
// an error occurred
}
}
}
Related
Is there any way in PHP to tell if a function is being run from inside or outside a particular class of object?
function getToDaChoppa() {
if( "we're inside the Choppa object" ) {
$foo = "We're inside";
} else {
$foo = "We're outside";
}
echo $foo;
}
class Choppa() {
public function getStatus() {
getToDaChoppa();
}
}
Running:
getToDaChoppa();
( new Choppa )->getStatus();
should echo:
We're Outside
We're Inside
A function on it's own doesn't know, if it's called from an class or not and that for good reasons. If the function behaves different, that would lead to very unmaintainable code and hard debugging, etc.
If you need the calling function and maybe ask, if this function belongs to an class/get the instance, the only way to do this is debug_backtrace. But in general you really only should do this, for debug code (as the name tells you).
Normally you would just have two functions for each case, or pass an parameter, which stores the desired information.
You could always pass an instance of the class through on top of a default value, then evaluate on the return of a get_class().
function getToDaChoppa($that = false) {
$class = $that ? get_class($that) : '';
if($class == "Choppa") {
$foo = "We're inside";
} else {
$foo = "We're outside";
}
echo $foo;
}
class Choppa {
public function getStatus() {
getToDaChoppa($this);
}
}
getToDaChoppa(); // Would return "We're outside"
( new Choppa )->getStatus(); // Would return "We're inside"
See https://ideone.com/WWg1Hl for a working example.
You might use debug_backtrace(), go back one hop, and check if that was made from inside a class. I'm not sure I'd do this in production though...
function getToDaChoppa() {
$bt = debug_backtrace();
if (isset($bt[1]) && array_key_exists('class', $bt[1])) {
echo "called from class\n";
} else {
echo "called directly\n";
}
}
Clarification: if you want it to trigger only for one specific class:
function getToDaChoppa() {
$bt = debug_backtrace();
if (
isset($bt[1]) &&
array_key_exists('class', $bt[1]) &&
$bt[1]['class'] === 'Choppa'
) {
echo "called from class Choppa\n";
} else {
echo "called otherwise\n";
}
}
I made a irc twitch bot and i have implemented multi threading but it have caused loots of errors.
My problem is that i have functions, example:
function isMod($username){
global $mods;
if(in_array($username,$mods) !== FALSE){
return true;
}
return false;
}
But there is a problem if i call the function from a class the "global" tag seams to not work so $mods will remain null. How can i fix it?
I have tried to use
$globals['mods']
But it is not seaming to work either.
I could do it like
function isMod($username, $mods){
if(in_array($username,$mods) !== FALSE){
return true;
}
return false;
}
But i want to avoid that.
If you really want to do it with globals, try to use $GLOBALS['mods'] instead.
function isMod($username){
if(in_array($username,$GLOBALS['mods']) !== FALSE){
return true;
}
return false;
}
$GLOBALS['mods'] = array('joe');
class Test {
function foo(){
var_dump(isMod('joe'));
}
}
$test = new Test();
$test->foo();
$GLOBALS is available everywhere, just like e.g. $_GET.
I have a PHP class that can return FALSE.
For some weird reason, I am unable to detect the FALSE return.
I can detect any other return value without any trouble.
Dumbed down version....
error_reporting(E_ALL);
ini_set("display_errors", 1);
$run = new myClass();//class returns false
$response = $run->myMethod();
I've tested with the following...
!$response
!isset($response)
empty($response)
$response == false
$response === false
I'm unable to get any type of reaction for any of the conditions I'm familiar with.
If I set the return to 1 or ANYTHING other than false, $response will contain whatever the class returns.
It's not like this is my first day. (it's my 2nd).
I use return false; frequently and have never had any trouble until today.
Certainly I can fix this by returning something like 'wtf' and test for that condition, but I'd really like to figure out what I'm missing here.
Thanks for any ideas.
When you make a instance of your class it will always your return a object not the return of the construct.
<?php
class SomeClass
{
// construct function that will always return false
public function __construct()
{
return false;
}
}
class TestClass extends PHPUnit_Framework_TestCase
{
public function testReturn()
{
// check if this code returns false
$this->assertFalse(new SomeClass);
}
public function testAssert()
{
// Checks if the object return is actually of SomeClass
$this->assertInstanceOf('SomeClass', new SomeClass);
}
public function testReturnOfConstruct()
{
//checks the return of the construct
$object = new SomeClass;
$this->assertFalse($object->__construct());
}
}
Return of phpunit
phpunit --debug test3.php
PHPUnit 3.7.28 by Sebastian Bergmann.
Starting test 'TestClass::testReturn'.
F
Starting test 'TestClass::testAssert'.
.
Starting test 'TestClass::testReturnOfConstruct'.
.
Time: 7 ms, Memory: 5.25Mb
There was 1 failure:
1) TestClass::testReturn
Failed asserting that SomeClass Object () is false.
/var/www/test3.php:14
FAILURES!
Tests: 3, Assertions: 3, Failures: 1.
Are you trying to return false from within public function __construct() or public function MyClass()*? This won't work as the new MyClass() call will either trigger a PHP error, or return an instance of MyClass, which is never going to evaluate to false because it is an instance of an object and thus not false.
If your class does not need to be instantiated to function, you can create a static method to perform the logic you are trying to run like so:
<?php
class MyClass
{
const COLOUR_BLUE = 'blue';
public static function isSkyBlue()
{
if (isset($_POST['sky']) && $_POST['sky'] == self::COLOUR_BLUE) {
return true;
} else {
return false;
}
}
}
// Call doThings() statically to get its value
$response = MyClass::isSkyBlue();
if ($response === false) {
// Your logic goes here
}
Alternatively, if you are passing things to the constructor before it performs its logic, you can do the following:
<?php
class MyClass
{
const COLOUR_BLUE = 'blue';
protected $otherObject = null;
public function __construct($otherObject)
{
$this->otherObject = $otherObject;
}
public function isSkyBlue()
{
if ($this->otherObject->sky == self::COLOUR_BLUE) {
return true;
} else {
return false;
}
}
}
// Call doThings() statically to get its value
$response = new MyClass($otherObject)
if ($response->isSkyBlue() === false) {
// Your logic goes here
}
* Note that your constructor should always be called __construct() as using the class name for the constructor has been deprecated since PHP 5.
If you are using a constructor, it wont return anything...it is not a normal function
I sometimes have variables that might not be set and I would like to use a default parameter instead. Like here:
if ($p == "a") doSomething();
If $p is not defined PHP throws Notice: Undefined variable. To avoid this I often I used this construct in such a case:
$p = (isset($p) ? $p : "");
But that is ugly if you have to use it a lot. So I wrote a function for it:
function getIfSet(&$value, $default = '')
{
return isset($value) ? $value : $default;
}
// Example
if (getIfSet($p) == "a") doSomething();
I wonder if there is a PHP function for this or how you solve this.
Just a little improvement, prefer passing null value to $default, passing empty string can be confusing, cause correct value can be empty string.
function getIfSet(&$value, $default = null)
{
return isset($value) ? $value : $default;
}
$p = getIfSet($p);
isset() is about as clean as it gets. Although I must admit that I'm not too fond of defaulting to an empty string, simply because a variable could be an empty string, yet still "be set". I think that a default of bool false or null would be truer to the behavior of isset:
function getIfSet(&$value, $default = false)
{
return isset($value) ? $value : $default;
}
$p = getIfSet($p);
if($p !== false){
//insert or whatever
}
else{
header('Location: error.php');
exit;
}
Depending on what kind of values you're checking (maybe REQUEST data?), consider using classes. They are fun and they could be available anywhere.
Assuming you're checking POST data (if you don't, well, take this as an idea), create a class that checks this array:
class Post
{
public function __get($index)
{
if (isset($_POST[$index]))
return $_POST[$index];
else
return null;
}
}
As simple as that. You know that __get() will trigger when you try to access a non-existant property. In this case, if the property (actually, the index in the $_POST array) doesn't exist, null will be returned and no errors are generated.
Now you can do:
$params = new Post();
$foo = $params->name ?: ''; // of course this doesn't make much sense.
if (!$params->password) ...
// instead of
if (isset($_POST['password'])) ...
// you'll still have to use isset for cases like:
if (isset($_POST['user']['password']) ...
if (isset($params->user['password'])) ...
// but still looks neater I'd say
A problem you'll find soon is that $params isn't a super global variable, while $_POST are. How to solve this? Create it in the constructor of your controller class and use Dependency Injection for all other objects your are using.
I tried to make renocor's answer more clean and OOP when I came up with this solution:
class NiceArray implements ArrayAccess {
protected $array;
public function __construct(&$array) {
$this->array =& $array;
}
public function offsetExists($offset) {
return true;
}
public function offsetGet($offset) {
if (isset($this->array[$offset]))
{
return $this->array[$offset];
}
else
{
return null;
}
}
public function offsetSet($offset, $value) {
$this->array[$offset] = $value;
}
public function offsetUnset($offset) {
unset($this->array[$offset]);
}
}
Usage:
$get = new NiceArray($_GET);
if ($get['p'] == "a") doSomething();
I know the class is kind of big but this way you still have an array and you can easily use it for every array you want. You do not need to change any code you may had before. You can still access and change the data. It will even change the original array.
I have a class in which each function of the class have to check the exact same condition before executing its code:
class myObject
{
public function function1($argument)
{
if($condition === true)
{
//Do Something
}
}
public function function2($argument)
{
if($condition === true)
{
//Do Something
}
}
public function function3($argument)
{
if($condition === true)
{
//Do Something
}
}
public function function4($argument)
{
if($condition === true)
{
//Do Something
}
}
}
We can see that function1, function2, function3, function4 only execute their code if $condition === true.
If in the future I add another function called function5, I will have to duplicate this condition.
So my question is, what is the best way to ensure that before call ANY function in the class, a condition is true, and if the condition is false, not call the function.
My method is to use the magic function __call and make all the functions of the class private:
class myObject
{
public function __call($method,$args)
{
if($condition === true)
{
call_user_func_array(array($this,$method),$args);
}
return;
}
private function function1($argument)
{
//Do Something
}
private function function2($argument)
{
//Do Something
}
private function function3($argument)
{
//Do Something
}
private function function4($argument)
{
//Do Something
}
}
It seems to work. However, I'm unsure that it will always work and that it is a clever way of doing it.
Its pretty normal to do it your first way. But, maybe the whole design of the class is wrong? If every single one function needs the exact same condition to be true maybe you could set/check it in the constructor and treat it from there? Why recheck the condition multiple times? Can it change between function calls?
Something like that would be used this way:
try{
$myClass = new MyClass(); // if no permissions throw exception
}catch(Exception $e){
//do something
return false;
}
//we know user as permission we go on
$myClass->function1();
$myClass->function2();
The second way works but you lose some of the power of phpdoc and good editors that will autocomplete your code. This way you have to know the name of every method.