"ফ্লাইয়ের উপরে" কোনও অবজেক্টে কীভাবে আমি একটি নতুন পদ্ধতি যুক্ত করব?
$me= new stdClass;
$me->doSomething=function ()
{
echo 'I\'ve done something';
};
$me->doSomething();
//Fatal error: Call to undefined method stdClass::doSomething()
"ফ্লাইয়ের উপরে" কোনও অবজেক্টে কীভাবে আমি একটি নতুন পদ্ধতি যুক্ত করব?
$me= new stdClass;
$me->doSomething=function ()
{
echo 'I\'ve done something';
};
$me->doSomething();
//Fatal error: Call to undefined method stdClass::doSomething()
উত্তর:
আপনি এর __call
জন্য সদ্ব্যবহার করতে পারেন :
class Foo
{
public function __call($method, $args)
{
if (isset($this->$method)) {
$func = $this->$method;
return call_user_func_array($func, $args);
}
}
}
$foo = new Foo();
$foo->bar = function () { echo "Hello, this function is added at runtime"; };
$foo->bar();
array_unshift($args, $this);
পদ্ধতি কলের আগে একটি করুন, যাতে ফাংশনটি স্পষ্টভাবে এটির সাথে আবদ্ধ হওয়ার প্রয়োজন ছাড়াই অবজেক্টের একটি রেফারেন্স পায় ...
পিএইচপি 7 এর মাধ্যমে আপনি বেনামে ক্লাস ব্যবহার করতে পারেন, যা stdClass
সীমাবদ্ধতা দূর করে ।
$myObject = new class {
public function myFunction(){}
};
$myObject->myFunction();
রানটাইমে নতুন পদ্ধতি যুক্ত করার অনুমতি দেওয়ার জন্য কেবল __call ব্যবহারের ক্ষেত্রে প্রধান অসুবিধা রয়েছে যে এই পদ্ধতিগুলি instance এই উদাহরণটি উল্লেখটি ব্যবহার করতে পারে না। কোডটিতে এগুলি যুক্ত পদ্ধতিগুলি ব্যবহার না করা অবধি সবকিছু দুর্দান্ত কাজ করে।
class AnObj extends stdClass
{
public function __call($closure, $args)
{
return call_user_func_array($this->{$closure}, $args);
}
}
$a=new AnObj();
$a->color = "red";
$a->sayhello = function(){ echo "hello!";};
$a->printmycolor = function(){ echo $this->color;};
$a->sayhello();//output: "hello!"
$a->printmycolor();//ERROR: Undefined variable $this
এই সমস্যাটি সমাধান করার জন্য আপনি এই প্যাটার্নটি আবার লিখতে পারেন
class AnObj extends stdClass
{
public function __call($closure, $args)
{
return call_user_func_array($this->{$closure}->bindTo($this),$args);
}
public function __toString()
{
return call_user_func($this->{"__toString"}->bindTo($this));
}
}
এইভাবে আপনি নতুন পদ্ধতি যুক্ত করতে পারেন যা উদাহরণের রেফারেন্সটি ব্যবহার করতে পারে
$a=new AnObj();
$a->color="red";
$a->sayhello = function(){ echo "hello!";};
$a->printmycolor = function(){ echo $this->color;};
$a->sayhello();//output: "hello!"
$a->printmycolor();//output: "red"
আপডেট: এখানে দেখানো পদ্ধতির একটি বড় ঘাটতি রয়েছে: নতুন ফাংশনটি শ্রেণীর পুরোপুরি যোগ্যতাসম্পন্ন সদস্য নয়;
$this
এইভাবে অনুরোধ করার সময় পদ্ধতিতে উপস্থিত নেই। এর অর্থ হ'ল আপনি যদি কোনও অবজেক্টের উদাহরণ থেকে ডেটা বা ফাংশন নিয়ে কাজ করতে চান তবে আপনাকে প্যারামিটার হিসাবে ফাংশনে ফাংশনটি পাস করতে হবে! এছাড়াও, আপনি এই ক্রিয়াকলাপ থেকে ক্লাসের সদস্যদের অ্যাক্সেস করতে পারবেন নাprivate
বাprotected
সদস্য হতে পারবেন না ।
নতুন বেনামী ফাংশনগুলি ব্যবহার করে ভাল প্রশ্ন এবং চতুর ধারণা!
মজার বিষয়, এটি কাজ করে: প্রতিস্থাপন করুন
$me->doSomething(); // Doesn't work
ফাংশনে নিজেই কল_উসার_ফুনক দ্বারা :
call_user_func($me->doSomething); // Works!
যা কাজ করে না তা হ'ল "সঠিক" উপায়:
call_user_func(array($me, "doSomething")); // Doesn't work
যদি সেভাবে বলা হয়, পিএইচপি ক্লাস সংজ্ঞাতে ঘোষিত পদ্ধতি প্রয়োজন।
এটি কি private
/ public
/ protected
দৃশ্যমানতার সমস্যা?
আপডেট: না। এমনকি ক্লাসের মধ্যে থেকেই ফাংশনটিকে স্বাভাবিক উপায়ে কল করা অসম্ভব, সুতরাং এটি দৃশ্যমানতার সমস্যা নয়। আসল ফাংশনটির কাছে call_user_func()
যাওয়া কেবলমাত্র এই উপায়টিই মনে হয়।
আপনি একটি অ্যারেতে ফাংশনগুলিও সংরক্ষণ করতে পারেন:
<?php
class Foo
{
private $arrayFuncs=array();// array of functions
//
public function addFunc($name,$function){
$this->arrayFuncs[$name] = $function;
}
//
public function callFunc($namefunc,$params=false){
if(!isset($this->arrayFuncs[$namefunc])){
return 'no function exist';
}
if(is_callable($this->arrayFuncs[$namefunc])){
return call_user_func($this->arrayFuncs[$namefunc],$params);
}
}
}
$foo = new Foo();
//Save function on array variable with params
$foo->addFunc('my_function_call',function($params){
return array('data1'=>$params['num1'],'data2'=>'qwerty','action'=>'add');
});
//Save function on array variable
$foo->addFunc('my_function_call2',function(){
return 'a simple function';
});
//call func 1
$data = $foo->callFunc('my_function_call',array('num1'=>1224343545));
var_dump($data);
//call func 2
$data = $foo->callFunc('my_function_call2');
var_dump($data);
?>
ওয়াল দিয়ে এটি কীভাবে করা যায় তা দেখতে, আপনি আমার পিএইচপি মাইক্রো-ফ্রেমওয়ার্ক, হালসিওন, যা গিথুব এ উপলব্ধ তা একবার দেখে নিতে পারেন । এটি যথেষ্ট ছোট যে আপনার কোনও সমস্যা ছাড়াই এটি বের করতে সক্ষম হওয়া উচিত - হালসিওনক্লাসমঙ্গার ক্লাসে মনোনিবেশ করুন।
__call
সমাধান ছাড়াই , আপনি bindTo
এই পদ্ধতিটি পছন্দ করতে (PHP> = 5.4) ব্যবহার করতে পারেন , এটিকে পছন্দ $this
করতে বাধ্য হয়ে $me
:
call_user_func($me->doSomething->bindTo($me, null));
সম্পূর্ণ স্ক্রিপ্টটি এর মতো দেখতে পারে:
$me = new stdClass;
// Property for proving that the method has access to the above object:
$me->message = "I\'ve done something";
$me->doSomething = function () {
echo $this->message;
};
call_user_func($me->doSomething->bindTo($me)); // "I've done something"
বিকল্পভাবে, আপনি একটি ভেরিয়েবলের জন্য সীমাবদ্ধ ফাংশন নির্ধারণ করতে পারেন, এবং তারপরে এটিকে কল করুন call_user_func
:
$f = $me->doSomething->bindTo($me);
$f();
একটি আছে স্ট্যাকওভারফ্লোতে অনুরূপ পোস্ট রয়েছে যা পরিষ্কার করে দেয় যে এটি কেবল নির্দিষ্ট নকশার নিদর্শনগুলির প্রয়োগের মাধ্যমেই অর্জনযোগ্য।
ক্লাসকিট ব্যবহারের মাধ্যমে অন্য একমাত্র উপায় হ'ল একটি পরীক্ষামূলক পিএইচপি এক্সটেনশন। (পোস্টেও)
হ্যাঁ এটি নির্ধারণের পরে কোনও পিএইচপি ক্লাসে কোনও পদ্ধতি যুক্ত করা সম্ভব। আপনি ক্লাসকিটটি ব্যবহার করতে চান, এটি একটি "পরীক্ষামূলক" এক্সটেনশন। এটি প্রদর্শিত হয় যে এই এক্সটেনশনটি যদিও ডিফল্টরূপে সক্ষম করা হয়নি, তাই এটি উইন্ডোতে যদি আপনি কোনও কাস্টম পিএইচপি বাইনারি সংকলন করতে পারেন বা পিএইচপি ডিএলএলগুলি লোড করতে পারেন তা নির্ভর করে (উদাহরণস্বরূপ ড্রিমহোস্ট কাস্টম পিএইচপি বাইনারিগুলিকে অনুমতি দেয় এবং সেগুলি সেটআপ করা বেশ সহজ হয়) )।
কারিম answer৯ উত্তরটি কাজ করে তবে এটি পদ্ধতির বৈশিষ্ট্যগুলির মধ্যে বেনাম ফাংশনগুলি সংরক্ষণ করে এবং তার ঘোষণাগুলি একই নামের বিদ্যমান বৈশিষ্ট্যগুলিকে ওভাররাইট করতে পারে বা বিদ্যমান সম্পত্তি যদি private
মারাত্মক ত্রুটিযুক্ত অব্যবস্থার কারণ হয়ে থাকে তবে তা কাজ করে না বলে আমি মনে করি তাদের আলাদা অ্যারেতে সংরক্ষণ করা এবং সেটার ব্যবহার করা পরিষ্কার সমাধান solution পদ্ধতি ইনজেক্টর সেটার বৈশিষ্ট্যগুলি ব্যবহার করে প্রতিটি বস্তুতে স্বয়ংক্রিয়ভাবে যুক্ত হতে পারে ।
পিএস অবশ্যই এটি হ্যাক যা এটি ব্যবহার করা উচিত নয় কারণ এটি সলাইডের খোলা বন্ধ নীতি লঙ্ঘন করে।
class MyClass {
//create array to store all injected methods
private $anon_methods = array();
//create setter to fill array with injected methods on runtime
public function inject_method($name, $method) {
$this->anon_methods[$name] = $method;
}
//runs when calling non existent or private methods from object instance
public function __call($name, $args) {
if ( key_exists($name, $this->anon_methods) ) {
call_user_func_array($this->anon_methods[$name], $args);
}
}
}
$MyClass = new MyClass;
//method one
$print_txt = function ($text) {
echo $text . PHP_EOL;
};
$MyClass->inject_method("print_txt", $print_txt);
//method
$add_numbers = function ($n, $e) {
echo "$n + $e = " . ($n + $e);
};
$MyClass->inject_method("add_numbers", $add_numbers);
//Use injected methods
$MyClass->print_txt("Hello World");
$MyClass->add_numbers(5, 10);