هل من الممكن لكسب استدعاءات الأسلوب في PHP؟

StackOverflow https://stackoverflow.com/questions/1609985

  •  05-07-2019
  •  | 
  •  

سؤال

ولدي SoapClient المثال المتولدة عن ملف WSDL. كل ما عدا واحدة من الدعاء طريقة تتطلب اسم المستخدم وكلمة المرور لتمريرها الهوية.

هل هناك أي طريقة لالتمشيط المكالمات طريقة حتى أستطيع أن حذف اسم المستخدم وكلمة المرور؟

هل كانت مفيدة؟

المحلول

وكما فب 5.3 يمكنك تخزين وظيفة مجهول في متغير. هذه الوظيفة مجهولة يمكن استدعاء الدالة "الأصلي" مع بعض المعلمات محددة مسبقا.

function foo($x, $y, $z) {
  echo "$x - $y - $z";
}

$bar = function($z) {
  foo('A', 'B', $z);
};

$bar('C');

وتحرير: يمكنك أيضا استخدام إغلاق لparametrise إنشاء وظيفة مجهول

function foo($x, $y, $z) {
  echo "$x - $y - $z";
}

function fnFoo($x, $y) {
  return function($z) use($x,$y) {
    foo($x, $y, $z);
  };
}

$bar = fnFoo('A', 'B');
$bar('C');

وedit2: هذا يعمل أيضا مع كائنات

class Foo {
  public function bar($x, $y, $z) {
    echo "$x - $y - $z";
  }
}

function fnFoobar($obj, $x, $z) {
  return function ($y) use ($obj,$x,$z) {
    $obj->bar($x, $y, $z);
  };
}

$foo = new Foo;
$bar = fnFoobar($foo, 'A', 'C');
$bar('B');

ولكن الاقتراحات الأخرى التي تستخدم __call () وفئة المجمع قد يكون من الأفضل إذا كنت ترغب في "تعزيز" فئة كاملة.

نصائح أخرى

وهنا هي فئة تنفذ الضمادة التلقائي والتطبيق الجزئي:

class lambda
{
    private $f;
    private $args;
    private $count;
    public function __construct($f, $args = [])
    {
        if ($f instanceof lambda) {
            $this->f = $f->f;
            $this->count = $f->count;
            $this->args = array_merge($f->args, $args);
        }
        else {
            $this->f = $f;
            $this->count = count((new ReflectionFunction($f))->getParameters());
            $this->args = $args;
        }
    }

    public function __invoke()
    {
        if (count($this->args) + func_num_args() < $this->count) {
            return new lambda($this, func_get_args());
        }
        else {
            $args = array_merge($this->args, func_get_args());
            $r = call_user_func_array($this->f, array_splice($args, 0, $this->count));
            return is_callable($r) ? call_user_func(new lambda($r, $args)) : $r;
        }
    }
}
function lambda($f)
{
    return new lambda($f);
}

مثال:

$add = lambda(function($a, $b) { 
    return $a + $b; 
});
$add1 = $add(1);
echo $add1(2); // 3

وحتى يمكنك القيام بذلك:

$int1 = lambda(function($f, $x) {
    return $f($x);
});

$successor = lambda(function($p, $f, $x) {
    return $f($p($f, $x));
}); 

$add = lambda(function($p, $q, $f, $x) {
    return $p($f, $q($f, $x));
}); 

$mul = lambda(function($p, $q, $x) {
    return $p($q($x));
}); 

$exp = lambda(function($m, $n) {
    return $n($m);
});

$int2 = $successor($int1);
$int3 = $add($int1, $int2);
$int6 = $mul($int3, $int2);
$int8 = $exp($int2, $int3);

وPHP لم يكن لديك التمشيط في حد ذاته، ولكن يمكنك أن تفعل شيئا من هذا القبيل في عدة طرق. في الحالة الخاصة بك، شيئا من هذا القبيل قد تعمل:

class MySoapClient extends SoapClient {
  ...
  public function __call($meth,$args) {
    if (substr($method,0,5) == 'curry') {
      array_unshift($args,PASSWORD);
      array_unshift($args,USERNAME);
      return call_user_func_array(array($this,substr($meth,5)),$args);
    } else {
      return parent::__call($meth,$args);
    }
  }
}
$soapClient = new MySoapClient();
...
// now the following two are equivalent
$soapClient->currysomeMethod($additionalArg);
$soapClient->someMethod(USERNAME,PASSWORD,$additionalArg);

وعلى الرغم من هنا هو حل أكثر عمومية لالتمشيط في PHP> = 5.3:

$curriedMethod = function ($additionalArg) use ($soapClient) { return $soapClient->method(USERNAME,PASSWORD,$additionalArg); }

$result = $curriedMethod('some argument');

وفعلت بعض البحوث ذات الصلة في هذا اليوم. هذا هو أقرب ما أتمكن من الحصول على:

function curryAdd($x)
{
  return function($y = null) use ($x)
  {
    if (is_null($y)) return $x;
    else return curryAdd($x + $y);
  };
}

// echo curryAdd(1)(2)(3)(4);
echo curryAdd(1)
  ->__invoke(2)
  ->__invoke(3)
  ->__invoke(4)
  ->__invoke();

والمشكلة الرئيسية هي أن PHP لن تسمح لك تنفيذ الإغلاق مباشرة على قيمة الإرجاع (بكثير بنفس الطريقة سوف PHP عدم السماح تنفيذ أسلوب على كائن غير منضم). ومع ذلك، منذ الاغلاق كائن من نوع الإغلاق، التي بنيت في __invoke طريقة ()، وفوق ستعمل.

وعلى الرغم من عدم التوصل إلى حل جيد جدا، ويمكن أن تكتب فئة مجمع الأساسية التي تستخدم PHPs <لأ href = "http://php.net/manual/en/language.oop5.magic.php" يختلط = "نوفولو noreferrer "> طرق السحر (وعلى وجه التحديد __call) لاستدعاء الدالة الفعلية ولكن إلحاق اسم المستخدم وكلمة المرور إلى قائمة الوسائط.

والمثال الأساسي:

class SC
{
    private $user;
    private $pass;

    public function __construct($user, $pass)
    {
        $this->user = $user;
        $this->pass = $pass;
    }

    public function __call($name, $arguments) 
    {
        $arguments = array_merge(array($this->user, $this->pass), $arguments);  
        call_user_func_array($name, $arguments);
    }
}

ويمكنك استخدام تطبيق جزئي و <لأ href = "HTTPS: // جيثب كوم / ايهور / Nspl # curriedfunction-withoptionalargs - كاذبة "يختلط =" "> وظائف الكاري نوفولو من غير القياسية مكتبة PHP .

وكما مينتيونيد التي كتبها ايهور، ومكتبة PHP غير القياسية هي مثيرة للاهتمام. لقد نفذت بالفعل بنفس الطريقة، كان مختلفا قليلا من وظيفة curried() ايهور ل

function curryfy($f, $args = []) {
    $reflexion = new ReflectionFunction($f);
    $nbParams = $reflexion->getNumberOfParameters();

    return function (...$arguments) use ($f, $reflexion, $nbParams, $args) {
        if (count($args) + count($arguments) >= $nbParams) {
            return $reflexion->invokeArgs(array_merge($args, $arguments));
        }

        return curryfy($f, array_merge($args, $arguments));
    };
}

والاستعمال:

function display4 ($a, $b, $c, $d) {
    echo "$a, $b, $c, $d\n";
};
$curry4 = curryfy('display4');
display4(1, 2, 3, 4);
$curry4(1)(2)(3)(4);

الجواب هل من الممكن لكسب استدعاءات الأسلوب في PHP؟ لا تظهر الضمادة. هذا الجواب يظهر التطبيق الجزئي. وهناك أمثلة توضيحية لطيف وهو ما يفسر الفرق بين هذه المفاهيم يمكن أن ينظر إليه هنا: <لأ href = "http://allthingsphp.blogspot.com/2012/02/currying-vs-partial-application.html" يختلط = "نوفولو noreferrer" > http://allthingsphp.blogspot.com/2012/02/currying-vs-partial-application.html

وهذا هو الضمادة:

function sum3($x, $y, $z) {
    return $x + $y + $z;
}

// The curried function    
function curried_sum3($x) {
    return function ($y) use ($x) {
        return function ($z) use ($x, $y) {
            return sum3($x, $y, $z);
        };
    };
}

واستدعاء وظيفة بالكاري في PHP 7

$result = curried_sum3(1)(2)(3); 
var_dump($result); // int 6

واستدعاء وظيفة بالكاري في PHP 5

$f1 = curried_sum3(6);
$f2 = $f1(6);
$result = $f2(6);
var_dump($result);

//OUTPUT:
int 18

وهذا هو التطبيق الجزئي:

function sum3($x, $y, $z) {
    return $x + $y + $z;
}

function partial_sum3($x) {
    return function($y, $z) use($x) {
        return sum3($x, $y, $z);
    };
}

//create the partial
$f1 = partial_sum3(6);
//execute the partial with the two remaining arguments
$result = $f1(6, 6);

var_dump($result);

//OUTPUT:
int 18
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top