Im not so experienced in php , Im using codeigniter to write my application , I have my own library and within my library there are three functions/methods that passes there arguments in one function which is in one of my models , my question is how will i manipulate/trick the method in my model to know exactly which function among the three in my library has passed the value and return the correct value ..
1st function
public function id_exist ($id) {
if(empty($id)) {
return FALSE;
}
return $this->library_model->this_exist($id);
}
2nd function
public function group_exist($group) {
if(empty($group)){
return FALSE;
}
return $this->library_model->this_exist($group);
}
with the 3rd same as the above 2
in my model
public function this_exist ($item) {
if(empty($item) || !isset($item)) {
return FALSE;
}
// here is where i need to know which function has passed the argument so that i can work with it and return the correct value from the database
}
Might be dirty, might be not sophisticated, but why not passing another argument which tells exactly the origin?
public function id_exist ($id) {
if(empty($id)) {
return FALSE;
}
return $this->library_model->this_exist('id', $id);
}
public function group_exist($group) {
if(empty($group)){
return FALSE;
}
return $this->library_model->this_exist('group', $group);
}
Model:
public function this_exist ($origin, $item) {
if(empty($item) || !isset($item)) {
return FALSE;
}
if($origin == 'id'){
// do something
}
elseif($origin == 'group') {
// do something else
}
}
Related
I have a very simple random number generator. This number generator has a few options: you input a minimum and maximum number, form this number a random number will be generated. I store the maximum-minimum and generated number inside of a session to be used later while playing the game.
When we get redirected to the main page (the guess game) you have the option to guess the random number that is stored in the session from their one forth the game will give you feedback on how close you are etc.
My question boils down to this, an option of the game is to display all your previous guesses I had a basic idea of how I wanted to do this: I will store the current guess I did inside of an array this array will be linked to a session from which I can loop through all of the old guesses.
I have written a couple of functions to achieve this and it only stores the current guess overriding any number already stored in the array e.g. if my current guess is 6 this number will be stored inside the array, if I proceed to guess again for example 4 this number will be stored inside of the array but will override 6.
I hope my code examples will be more clear.
this function stores the old guesses inside of said array
public function Store_Old_Guesses_In_Session()
{
if (!isset($_SESSION["show_previous_guesses"])) {
return false;
}
if (isset($_POST["Guess_Button"])) {
return $_SESSION["old_guesses"] = $this->old_guesses = array(
"Old_guesses" => $this->getCurrentGuess(),
);
}
return false;
}
this function gets the current guess
public function getCurrentGuess()
{
if (isset($this->current_guess)) {
return $this->current_guess;
}
return false;
}
-
namespace Store;
use Get_Number\Get_Numbers;
require_once "Current_Guesses.php";
class Store_Numbers extends Get_Numbers
{
public array $old_guesses;
public function __construct()
{
parent::__construct();
if (isset($_SESSION["old_guesses"])) {
$this->old_guesses = $_SESSION["old_guesses"];
}
}
public function Store_Current_Number_In_Session()
{
if (empty($this->getCurrentNumber())) {
return false;
}
return $_SESSION["current_number"] = $this->getCurrentNumber();
}
public function Store_Minimum_Number_In_Session()
{
if (empty($this->getMinimumNumber())) {
return false;
}
return $_SESSION["minimum_number"] = $this->getMinimumNumber();
}
public function Store_Maximum_Number_In_Session()
{
if (empty($this->getMaximumNumber())) {
return false;
}
return $_SESSION["maximum_number"] = $this->getMaximumNumber();
}
public function Store_Checkbox_Value_In_Session()
{
if (empty($_POST["debug_options"])) {
return false;
}
return $_SESSION["debug_options"] = $_POST["debug_options"];
}
public function Store_show_previous_guesses_Checkbox_In_Session()
{
if (empty($_POST["show_previous_guesses"])) {
return false;
}
return $_SESSION["show_previous_guesses"] = $_POST["show_previous_guesses"];
}
public function Store_Current_Number_Checkbox_Value_In_Session()
{
if (empty($_POST["current_number_checkbox"])) {
return false;
}
return $_SESSION["current_number_checkbox"] = $_POST["current_number_checkbox"];
}
public function Store_Old_Guesses_In_Session()
{
if (!isset($_SESSION["show_previous_guesses"])) {
return false;
}
if (isset($_POST["Guess_Button"])) {
$this->old_guesses[] = $this->getCurrentGuess();
$_SESSION['old_guesses'] = array_push($this->old_guesses, $this->getCurrentGuess());
return $this->old_guesses;
}
return false;
}
}
I have a bunch of code examples should you need more
A few things you might need to know:
PHP = 7.4.2
The property $old_guesses is declared as an array like this public
array $old_guesses;
You need to push onto the array, not assign to it.
public function Store_Old_Guesses_In_Session()
{
if (!isset($_SESSION["show_previous_guesses"])) {
return false;
}
if (isset($_POST["Guess_Button"])) {
$this->old_guesses[] = $this->getCurrentGuess();
$_SESSION['old_guesses'] = $this->old_guesses;
return $this->old_guesses;
}
return false;
}
The constructor should initialize the variable from the session variable to make it persist and grow.
if (!isset($_SESSION['old_guesses'])) {
$_SESSION['old_guesses'] = array();
}
$this->old_guesses = $_SESSION['old_guesses'];
Say I have to similar function :
public function auth(){
return $someResponse;
}
public function collect(){
return $someOtherResponse
}
Question : When one of the response get passed to another class, is there any way to check which function returned the response ?
In a purely object-oriented way, wanting to attach information to a value is akin to wrapping it into a container possessing context information, such as:
class ValueWithContext {
private $value;
private $context;
public function __construct($value, $context) {
$this->value = $value;
$this->context = $context;
}
public value() {
return $this->value;
}
public context() {
return $this->context;
}
}
You can use it like this:
function auth()
{
return new ValueWithContext($someresponse, "auth");
}
function collect()
{
return new ValueWithContext($someotherrpesonse, "collect");
}
This forces you to be explicit about the context attached to the value, which has the benefit of protecting you from accidental renamings of the functions themselves.
As per my comment, using arrays in the return will give you a viable solution to this.
It will allow a way to see what has been done;
function auth()
{
return (array("auth" => $someresponse));
}
function collect()
{
return (array("collect" => $someotherrpesonse));
}
class myClass
{
function doSomething($type)
{
if (function_exists($type))
{
$result = $type();
if (isset($result['auth']))
{
// Auth Used
$auth_result = $result['auth'];
}
else if (isset($result['collect']))
{
// Collect used
$collect_result = $result['collect'];
}
}
}
}
It can also give you a way to fail by having a return array("fail" => "fail reason")
As comments say also, you can just check based on function name;
class myClass
{
function doSomething($type)
{
switch ($type)
{
case "auth" :
{
$result = auth();
break;
}
case "collect" :
{
$result = collect();
break;
}
default :
{
// Some error occurred?
}
}
}
}
Either way works and is perfectly valid!
Letting the two user defined functions auth() & collect() call a common function which makes a call to debug_backtrace() function should do the trick.
function setBackTrace(){
$backTraceData = debug_backtrace();
$traceObject = array_reduce($backTraceData, function ($str, $val2) {
if (trim($str) === "") {
return $val2['function'];
}
return $str . " -> " . $val2['function'];
});
return $traceObject;
}
function getfunctionDo1(){
return setBackTrace();
}
function getfunctionDo2(){
return setBackTrace();
}
class DoSomething {
static function callfunctionTodo($type){
return (($type === 1) ? getfunctionDo1() : getfunctionDo2());
}
}
echo DoSomething::callfunctionTodo(1);
echo "<br/>";
echo DoSomething::callfunctionTodo(2);
/*Output
setBackTrace -> getfunctionDo1 -> callfunctionTodo
setBackTrace -> getfunctionDo2 -> callfunctionTodo
*/
The above function would output the which function returned the response
I have 2 functions in PHP and i want to return a value to one function to another. this is my functions
public function save_payment_log_data($icasl_number, $exam_session) {
$paylog_av = $this->payment_log_exists($icasl_number, $exam_session);
}
function payment_log_exists($icasl_no, $exam_session) {
$this->db->where('icasl_no', $icasl_no);
$this->db->where('exam_session', $exam_session);
$query = $this->db->get('exm_paymentlog');
if ($query->num_rows() > 0) {
$pl = $query->row();
$pay_id = $pl->paylog_id;
return $pay_id;
} else {
return false;
}
}
I want to return $pay_id to the save_payment_log_data() function but in here $pay_id didn't return to that function. I think it's return from the function payment_log_exists()
so how can I return $pay_id to the save_payment_log_data() function
See this example it's working fine:
function save_payment_log_data() {
$paylog_av = payment_log_exists();
# print the return value
echo $paylog_av;
}
function payment_log_exists() {
return "Hello";
}
save_payment_log_data();
You can try to remove public and this form save_payment_log_data(),
and call the save_payment_log_data() function where you want.
your are only assigning a value to the $paylog_av your "save_payment_log_data" function should be:
public function save_payment_log_data($icasl_number, $exam_session) {
$paylog_av = $this->payment_log_exists($icasl_number, $exam_session);
return $paylog_av;
}
I have a validation class which uses method chaining. I would like to be able to do single checks with TRUE/FALSE like this:
if ($obj->checkSomething()) {}
But also chain methods like this:
if ($obj->checkSomething()->checkSomethingElse()) {}
The problem however is that if one method returns FALSE, it will not send back an object and thus breaks the method chaining which ends with this error:
Fatal error: Call to a member function checkSomething() on a non-object in ...
Do I have to pick either single method return calls or method chaining or is there a workaround?
One idea would be to set an internal flag to indicate success or failure, and access it via another method, while checking that flag in each method and not doing anything if it's set. E.g.:
class A {
private $valid = true;
public function check1() {
if (!$this->valid) {
return $this;
}
if (!/* do actual checking here */) {
$this->valid = false;
}
return $this;
}
public function check2() {
if (!$this->valid) {
return $this;
}
if (!/* do actual checking here */) {
$this->valid = false;
}
return $this;
}
public function isValid() {
return $this->valid;
}
}
// usage:
$a = new A();
if (!$a->check1()->check2()->isValid()) {
echo "error";
}
To minimize the boilerplate checking in each function, you could also use the magic method __call(). E.g.:
class A {
private $valid;
public function __call($name, $args) {
if ($this->valid) {
$this->valid = call_user_func_array("do" . $name, $args);
}
return $this;
}
private function docheck1() {
return /* do actual checking here, return true or false */;
}
private function docheck2() {
return /* do actual checking here, return true or false */;
}
public isValid() {
return $this->valid;
}
}
The usage would be same as above:
$a = new A();
if (!$a->check1()->check2()->isValid()) {
echo "error";
}
I believe you're looking to have an instance evaluate as true/false based on the outcome of validation.
While some languages allow you to override the boolean value of an instance, php does not (except for casting to string, that is. See PHP's Magic Methods).
Also, the booleans page in the PHP Manual has a list of things that evaluate to false, but it doesn't give any method of overriding the behavior either.
That being said, I'd suggest going with JRL's idea, and construct a chain of validation rules, then 'execute' it with a function that returns the boolean needed in your if statement.
You could wrap them up in a subclass, perhaps.
e.g. if you have
class Validate {
public function checkSomething($data) {
if ($data === $valid) {
return true;
}
return false;
}
public function checkSomethingElse($data) {
if ($data === $valid) {
return true;
}
return false;
}
}
You could do this:
class ValidateChain extends Validate {
protected $valid = true;
public function checkSomething($data) {
if (false === parent::checkSomething($data)) {
$this->valid = false;
}
return $this;
}
public function checkSomethingElse($data) {
if (false === parent::checkSomethingElse($data)) {
$this->valid = false;
}
return $this;
}
public function getIsValid() {
return $this->valid;
}
}
$v = new ValidationChain();
$valid = $v->checkSomething()->checkSomethingElse()->getIsValid();
Quick and dirty, E&OE. And you'd probably need to add a way to find out which bits weren't valid, etc.
Consider the following PHP snippet:
<?php
class Is
{
function __get($key)
{
$class = __CLASS__ . '_' . $key;
if (class_exists($class) === true)
{
return $this->$key = new $class();
}
return false;
}
function Domain($string)
{
if (preg_match('~^[0-9a-z\-]{1,63}\.[a-z]{2,6}$~i', $string) > 0)
{
return true;
}
return false;
}
}
class Is_Domain
{
function Available($domain)
{
if (gethostbynamel($domain) !== false)
{
return true;
}
return false;
}
}
$Is = new Is();
var_dump($Is->Domain('google.com')); // true
var_dump($Is->Domain->Available('google.com')); // false
?>
Is it possible to call the Available() method like this (and still return solely true or false if the Available method is not called)?
var_dump($Is->Domain('google.com')->Available()); // false
If yes, how?
EDIT: Would this do the trick?
class Is
{
function __get($key)
{
// same as before
}
function Domain($string)
{
if (preg_match('~^[0-9a-z\-]{1,63}\.[a-z]{2,6}$~i', $string) > 0)
{
return (bool) $this->Domain;
}
return false;
}
}
class Is_Domain
{
function __toString()
{
return true;
}
function Available($domain)
{
if (gethostbynamel($domain) !== false)
{
return true;
}
return false;
}
}
Thanks in Advance!
PS: This snippet is truncated, so don't expect it to make it a lot of sense just by its own.
Essentially you want a method to return either a bool or an object based on whether a subsequent method call to the result is going to occur. I don't think this will be possible without some massive hack (e.g. reading the PHP file in yourself and looking ahead), and it shouldn't be because your objects shouldn't be worrying about the context in which they are used.
Instead you could get the first call to return an object which is relevant in both cases, e.g. DomainLookupResult, which has two methods e.g. Exists() and IsAvailable(). You could then do:
$result = $Is->Domain('google.com');
$isValid = $result->Exists();
$isAvaliable = $result->IsAvailable();
//or chaining:
$isValid = $Is->Domain('google.com')->Exists();
$isAvailable = $Is->Domain('google.com')->IsAvailable();
You can only chain method calls if they return an object!
This is because you can only call methods on objects.
The problem with your code is that the methods return a non object value, either true or false. And the problem is not in any way solved better by chaining methods. You should use that where its applicable. Like chaining many setters, NOT getters which the methods you want to use essentially is.
var_dump($Is->Domain->Available('google.com')); // false
//is the same as
$res = $Is->Domain;
$res = $res->Available('google.com'));
var_dump($res);
So you see the first res is a boolean true or false, and you can not call a method on that.
edit
This might be a "solution". Not a good solution though since this is better without chaining.
class Domain
{
public $domain;
function setDomain($domain) {
$this->domain = $domain;
return $this;
}
function isDomain($domain = null) {
if (is_string($domain)) {
$this->setDomain($domain);
}
$result = gethostbynamel($this->domain) !== false;
return new Result($this, $result);
}
function isValid() {
$result = (bool) preg_match('', $this->domain);
return new Result($this, $result)
}
}
class Result
{
public $result;
public $object;
public function __construct($object, $result)
{
$this->result = $result;
$this->object = $object;
}
public function __call($method, $arguments)
{
if (is_object($this->result)) {
return call_user_func_array(array($this->result, $method), $arguments);
}
if (!$this->result) {
return $this;
}
return call_user_func_array(array($this->object, $method), $arguments);
}
}
$domain = new Domain();
var_dump($domain->isValid('google.com')->isAvailable()->result);
/edit
This will solve your problem above.
var_dump($Is->Domain('validandfreedomain.com') && $Is_Domain->Available('validandfreedomain.com')); // true
If you desperately want to chain a method for this problem you could make it more like this.
class Domain
{
public $domain;
function setDomain($domain) {
$this->domain = $domain;
return $this;
}
function isAvailable() {
return gethostbynamel($this->domain) !== false;
}
function isValid() {
return (bool) preg_match('', $this->domain);
}
}
$domain = new Domain();
$result = $domain->setDomain('validandfreedomain.com')->isValid() && $domain->isAvailable();
It is possible, if your function returns an object, you can call its method, and so on (see method chaining). The only limitation is - as far as a I know - is that you cannot chain calls from an object created by new ( new Object()->method1()->method2() ).
As for your example, I see no point in using either the dynamic class, or method chaining stuff.