I have the following code
public function create(){
return self::checkQuantity();
return self::checkSameLocation();
return self::someAnotherFunction();
return self::someMoreFunction();
..
..
..
}
public function checkQuantity(){
if(someCondition){
return [foo,bar];
}
}
public function checkSameLocation(){
if(someCondition){
return [foo,bar];
}
}
I would like to return function inside create() only if it function inside it returns something else continue executing the create() function.
Based on the example:
create() gets called
if checkQuantity returns nothing then continue with checkSameLocation() without returning checkQuantity() function
NOTE: There could be multiple function calls inside create() sometimes, I would like to avoid using if statement checks.
public function create(){
return self::checkQuantity()
?? self::checkSameLocation()
?? self::someAnotherFunction(); //and so on
}
See Null coalescing operator
public function create(){
$data = function1();
if ($data) {
return $data;
}
$data = function2();
if ($data) {
return $data;
}
$data = function3();
if ($data) {
return $data;
}
// ...
return function42();
}
This can lead to another solution like:
public function create(){
$functions = ['func1', 'func2', 'func3',]; // etc
foreach ($functions as $func) {
$data = $func();
if ($data) {
return $data;
}
}
}
Something like this:
(in this case, I've moved all your check code into polymorphic classes; the same could be achieved with methods in the current class per your question, but I think it's neater this way)
$checks = [new checkClass1, new checkClass2, new checkClass3, ...];
foreach ($checks as $check) {
$result = $check->runCheck();
if ($result) {
return $result;
}
}
You need an if and a temporary variable.
public function create(){
$a = self::checkQuantity();
if(empty($a)) {
return self::checkSameLocation();
} else {
return $a;
}
}
public function checkQuantity(){
if(someCondition){
return [foo,bar];
}
}
public function checkSameLocation(){
if(someCondition){
return [foo,bar];
}
}
This looks like the perfect use case for the null coalescing operator
public function create(){
return self::checkQuantity() ?? self::checkSameLocation() ?? self::someAnotherFunction() ?? return self::someMoreFunction()...
}
You can chain as many function calls as you want. That line will return the first value that's not null. Since returning nothing from a function effectively equals returning a null value, it'll work as you want.
Related
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 am having the following class:
class StuffDoer{
public function __construct(Dep1 $dep, Dep2 $dep2, array $array){
$this->dep = $dep;
$this->dep2 = $dep2;
$this->array = $array;
}
public function genericDoStuff($param){
// Do stuff here...
}
public function doStuffForMark(){
return $this->genericDoStuff('Mark');
}
public function doStuffForTim(){
return $this->genericDoStuff('Tim');
}
public function doStuffForAlice(){
return $this->genericDoStuff('Alice');
}
}
After some months, I am asked to make the method genericDoStuff($param), along with all the methods that depend on it, use an extra parameter in a single part of the application. Instead of changing the signature on every single method that depends on genericDoStuff, I ended up with the following:
class StuffDoer{
public function __construct(Dep1 $dep, Dep2 $dep2, array $array){
$this->dep = $dep;
$this->dep2 = $dep2;
$this->array = $array;
}
public function forParameter($param){
$self = clone $this;
$this->param = $param;
return $self;
}
public function genericDoStuff($param){
if($this->param !== null){
// Do stuff by taking param into account
} else {
// Do stuff stuffdoer does
}
}
public function doStuffForMark(){
return $this->genericDoStuff('Mark');
}
public function doStuffForTim(){
return $this->genericDoStuff('Tim');
}
public function doStuffForAlice(){
return $this->genericDoStuff('Alice');
}
}
That way, I am able to do this in the single point of the application:
$myStuffDoer = $serviceContainer->get('stuff_doer');
$myStuffDoer->forParameter('AAAARGHITBURNSGODHELPME')->doStuffForMark();
// Future usages of $myStuffDoer are unaffected by this!
So my question is this: Is this considered a bad practice for any reason?
Maybe I'm wrong to expressed it in the title, but I just do not understand how in the class like this.
<?php
class sample{
public $data = [];
public function pushIndex($index){
array_push($this->data, $index);
}
public function pushValue($value){
array_push($this->data["index"], $value);
// Some magic
}
public function forIndex($index){
return $this->data[$index];
// Some magic
}
}
To realize scheme like in Symfony, where will be spaghetti like this
<?php
$a = new sample;
$a->pushIndex("index")->pushValue("value");
$a->forIndex("index2")->pushValue("value2");
Maybe someone knows how to do it?
What you're talking about is called Fluent interface.
Returns the current object by using $this.
public function pushIndex($index){
array_push($this->a,$index);
return $this;
}
But what you want is to do something like this:
class sample
{
protected $a = [];
protected $currentIndex = null;
public function pushIndex($index)
{
$this->currentIndex = $index;
return $this;
}
public function pushValue($value)
{
if ($this->currentIndex === null) {
throw new LogicException('You need to call "pushIndex" or "forIndex" first.');
}
$this->a[$this->currentIndex] = $value;
return $this;
}
public function forIndex($index)
{
if (!isset($this->a[$index])) {
throw new RuntimeException(sprintf('Index "%s" doesn\'t exists', $index));
}
$this->currentIndex = $index;
return $this;
}
public function getArray()
{
return $this->a;
}
}
$a = new sample;
$a->pushIndex("index")->pushValue("value");
$a->forIndex("index2")->pushValue("value2"); // exception?
var_dump($a->getArray());
But what you want is pretty unclear.
I think what you're trying to achieve is something like this:
class sample{
public $a = [];
public $index = null;
public function pushIndex($index){
$this->index = $index;
$this->a[$index] = null;
return $this;
}
public function pushValue($value){
$this->a[$this->index] = $value;
return $this;
}
public function forIndex($index){
$this->index = $index;
return $this;
}
}
$a = new sample;
$a->pushIndex("index")->pushValue("value");
$a->forIndex("index2")->pushValue("value2");
echo "<pre>";
var_dump($a);
echo "</pre>";
This is called "method chaining". By returning a reference to the called object, you're able to perform further methods on the object, essentially "chaining" the methods.
I've had to adjust your code a little to get it the work I believe the way you want it to. It should provide a working example to help you understand method chaining.
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
}
}