2009-05-06 9 views
56

गतिशील रूप से सभी इंस्टेंस गुणों को बनाने का कोई तरीका है? उदाहरण के लिए, मैं कन्स्ट्रक्टर में सभी विशेषताओं को उत्पन्न करने में सक्षम होना चाहता हूं और कक्षा के तुरंत बाद इसे एक्सेस करने में सक्षम होना चाहिए: $object->property। ध्यान दें कि मैं गुणों को अलग से एक्सेस करना चाहता हूं, और सरणी का उपयोग नहीं करना चाहता हूं; यहाँ मैं क्या कर का एक उदाहरण है नहीं हैं:क्या आप पीएचपी में गतिशील रूप से इंस्टेंस गुण बना सकते हैं?

class Thing { 
    public $properties; 
    function __construct(array $props=array()) { 
     $this->properties = $props; 
    } 
} 
$foo = new Thing(array('bar' => 'baz'); 
# I don't want to have to do this: 
$foo->properties['bar']; 
# I want to do this: 
//$foo->bar; 

अधिक विशिष्ट होना करने के लिए, जब मैं वर्गों गुण की एक बड़ी संख्या है के साथ काम कर रहा हूँ, मैं सभी स्तंभों का चयन करने में सक्षम होना चाहते हैं एक डेटाबेस में (जो गुणों का प्रतिनिधित्व करते हैं) और उनसे उदाहरण गुण बनाते हैं। प्रत्येक कॉलम मान को एक अलग इंस्टेंस प्रॉपर्टी में संग्रहीत किया जाना चाहिए।

+1

सरणी और __set और __get तरीकों सामान्य प्रयोजनों के लिए पर्याप्त होना चाहिए। क्या आपके पास "एक संपत्ति = एक चर" समाधान चिपकाने के लिए कोई विशेष चिंता है? बीटीडब्ल्यू, encapsulation के सिद्धांत dictates कोई अन्य वस्तु को पता होना चाहिए कि चर एक वास्तविक या एक सरणी में एक मूल्य है? इस आधार को विस्तारित करके भी वस्तुओं को नहीं बनाया गया है। –

+0

http://php.net/manual/en/language.oop5.overloading.php –

उत्तर

60

क्रमबद्ध।

class foo { 
    public function __get($name) { 
    return('dynamic!'); 
    } 
    public function __set($name, $value) { 
    $this->internalData[$name] = $value; 
    } 
} 

गतिशील मनुष्य और सेटर तरीके के लिए एक उदाहरण है कि, यह आप व्यवहार निष्पादित करने के लिए जब भी एक वस्तु संपत्ति पहुँचा जा सकता है की अनुमति देता है: वहाँ जादू तरीकों कि आप क्रम में वर्ग व्यवहार को लागू करने के लिए अपने खुद के कोड हुक करने की अनुमति देते हैं। उदाहरण के लिए

print(new foo()->someProperty); 

प्रिंट करेगा, इस मामले में, "गतिशील!" और आप एक मनमाने ढंग से नामित संपत्ति के लिए एक मूल्य भी निर्दिष्ट कर सकते हैं, जिस स्थिति में __set() विधि चुपचाप लागू की जाती है। __call ($ name, $ params) विधि ऑब्जेक्ट विधि कॉल के लिए समान होती है। विशेष मामलों में बहुत उपयोगी है। लेकिन समय के सबसे अधिक है, तो आप के साथ द्वारा मिल जाएगा:

class foo { 
    public function __construct() { 
    foreach(getSomeDataArray() as $k => $value) 
     $this->{$k} = $value; 
    } 
} 

... क्योंकि ज्यादातर, आप सभी की जरूरत तदनुसार नामित वर्ग क्षेत्रों में एक बार एक सरणी की सामग्री डंप करने के लिए है, या बहुत स्पष्ट कम से कम में निष्पादन पथ में अंक। इसलिए, जब तक आपको वास्तव में गतिशील व्यवहार की आवश्यकता न हो, तब तक अपने ऑब्जेक्ट को डेटा के साथ भरने के लिए उस अंतिम उदाहरण का उपयोग करें।

यह http://php.net/manual/en/language.oop5.overloading.php

+0

यह वही है जो मुझे चाहिए लेकिन क्या ये गुण निजी या सार्वजनिक होंगे? या क्या मैं उन्हें निजी बना सकता हूं: निजी $ - - {$ k} => $ मान; ? – Brayn

+4

वे मेरे ज्ञान के लिए सार्वजनिक होंगे, उन्हें रनटाइम पर निजी या संरक्षित करना संभव नहीं है। "निजी" दृश्यता के लिए, आप एक निजी सरणी-प्रकार फ़ील्ड घोषित कर सकते हैं और फिर उसे भर सकते हैं। "संरक्षित" के लिए भी चला जाता है। चीजों को यथासंभव सरल रखना सबसे अच्छा है, इसलिए आप केवल $-- डीएस नामक एक निजी सरणी पेश कर सकते हैं, जहां अंदर के फ़ील्ड को इस-> डीएस ['फील्डनाम'] जैसे बयानों द्वारा संबोधित किया जा सकता है। या यदि आप वास्तव में फैंसी बनना चाहते हैं, तो आप एक मिनी क्लास को कार्यान्वित करेंगे जो अनिवार्य रूप से किसी सरणी की कार्यक्षमता को लपेटता है, ताकि आप $-- myDatasetObject-> fieldname जैसे कुछ कर सकें। – Udo

+1

आप बिना किसी __get और __set के PHP5 में किसी ऑब्जेक्ट को अधिभारित कर सकते हैं, लेकिन गुण हमेशा सार्वजनिक होते हैं। अगर आपको चीजों की रक्षा करने की ज़रूरत है, तो आपको उन्हें स्पष्ट रूप से घोषित करने की आवश्यकता है। –

1

आप कर सकते हैं:

$variable = 'foo'; 
$this->$variable = 'bar'; 

वस्तु यह bar करने पर कहा जाता है की विशेषता foo सेट होगा। bar को

$this->{strtolower('FOO')} = 'bar'; 

यह भी foo स्थापित करेगा (नहीं FOO):

तुम भी कार्यों का उपयोग कर सकते हैं।

+0

पहला उदाहरण मेरे लिए काम नहीं करता है। क्या आप वाकई वैध हैं? – yanis

+0

यह काम करता है। बस इसे फिर से परीक्षण किया। – Koraktor

23

यह वही निर्भर करता है जो आप चाहते हैं। क्या आप कक्षा गतिशील रूप से संशोधित कर सकते हैं? ज़रुरी नहीं। लेकिन क्या आप ऑब्जेक्ट गुणों को गतिशील रूप से बना सकते हैं, जैसा कि उस वर्ग के एक विशेष उदाहरण में? हाँ।

class Test 
{ 
    public function __construct($x) 
    { 
     $this->{$x} = "dynamic"; 
    } 
} 

$a = new Test("bar"); 
print $a->bar; 

आउटपुट:

गतिशील

तो एक वस्तु संपत्ति "बार" नामित निर्माता में गतिशील रूप से बनाया गया था।

+1

यह भी दिखाता है कि गतिशील गुण सार्वजनिक हैं। –

7

आप मनमाने ढंग से मूल्यों के लिए एक धारक के रूप में कार्य करने के लिए एक उदाहरण चर का उपयोग और फिर उन्हें नियमित रूप से गुण के रूप में पुन: प्राप्त करने __get जादू विधि का उपयोग कर सकते हैं:

class My_Class 
{ 
    private $_properties = array(); 

    public function __construct(Array $hash) 
    { 
     $this->_properties = $hash; 
    } 

    public function __get($name) 
    { 
     if (array_key_exists($name, $this->_properties)) { 
      return $this->_properties[$name]; 
     } 
     return null; 
    } 
} 
+0

मैं व्यक्तिगत रूप से आपके समाधान को पसंद करता हूं क्योंकि आपके पास इस पर अधिक नियंत्रण है कि किस प्रकार चर के आधार पर चर का उपयोग किया जाता है और आपने क्या किया है, लेकिन उसने अभी इसे पोस्ट किया है। संपादित करें: क्षमा करें, उल्लेख करना भूल गया: गुणों को पकड़ने के लिए सरणी का उपयोग किए बिना, प्रत्येक संपत्ति एक अलग 'चर' में होती है। –

+0

टिप्पणी के लिए धन्यवाद - मुझे लगता है कि यह समस्या के बारे में जाने का प्राकृतिक तरीका है। मुझे डर है कि मुझे समझ में नहीं आता कि ब्रायन का अर्थ उनके संपादन से क्या है - और नए होने के नाते मेरे पास पूछने के लिए टिप्पणी पोस्ट करने के लिए पर्याप्त प्रतिष्ठा अंक नहीं हैं। ओह ठीक है ... –

+0

हाय, मुझे वाकई यह जवाब पसंद है। मैंने इसे ठीक करने के लिए इसे संपादित करने का प्रयास किया लेकिन स्टैक ओवरफ्लो परिवर्तन को अस्वीकार कर देता है क्योंकि यह एक एकल वर्ण संपादित करता है: 'इसे वापस करें -> _ गुण [$ name];' शायद यह $ - $ _ गुण [$ name] वापस आना चाहिए; ' – Iain

7

हाँ, आप कर सकते हैं।

class test 
{ 
    public function __construct() 
    { 
     $arr = array 
     (
      'column1', 
      'column2', 
      'column3' 
     ); 

     foreach ($arr as $key => $value) 
     { 
      $this->$value = ''; 
     } 
    } 

    public function __set($key, $value) 
    { 
     $this->$key = $value; 
    } 

    public function __get($value) 
    { 
     return 'This is __get magic '.$value; 
    } 
} 

$test = new test; 

// Results from our constructor test. 
var_dump($test); 

// Using __set 
$test->new = 'variable'; 
var_dump($test); 

// Using __get 
print $test->hello; 

आउटपुट

object(test)#1 (3) { 
    ["column1"]=> 
    string(0) "" 
    ["column2"]=> 
    string(0) "" 
    ["column3"]=> 
    string(0) "" 
} 
object(test)#1 (4) { 
    ["column1"]=> 
    string(0) "" 
    ["column2"]=> 
    string(0) "" 
    ["column3"]=> 
    string(0) "" 
    ["new"]=> 
    string(8) "variable" 
} 
This is __get magic hello 

इस कोड निर्माता जो तब $ this-> स्तंभ के साथ पहुँचा जा सकता है में गतिशील गुण सेट हो जाएगा। वर्ग के भीतर परिभाषित संपत्तियों से निपटने के लिए __get और __set जादू विधियों का उपयोग करना भी अच्छा अभ्यास है। अधिक जानकारी उन्हें यहां मिल सकती है।

http://www.tuxradar.com/practicalphp/6/14/2

की

http://www.tuxradar.com/practicalphp/6/14/3

0

अधिक भार यह वास्तव में जटिल तरीके से तेजी से विकास के इस प्रकार को संभालने के लिए है कहा जाता है। मुझे जवाब और जादू विधियां पसंद हैं लेकिन मेरी राय में कोडस्मिथ जैसे कोड जनरेटर का उपयोग करना बेहतर है।

मैंने टेम्पलेट बनाया है जो डेटाबेस से कनेक्ट होता है, सभी कॉलम और उनके डेटा प्रकारों को पढ़ता है और तदनुसार पूरी कक्षा उत्पन्न करता है।

इस तरह से मुझे त्रुटि मुक्त (कोई टाइपो) पठनीय कोड नहीं है। और यदि आपका डेटाबेस मॉडल फिर से जनरेटर को बदलता है ... यह मेरे लिए काम करता है।

3

क्लास सदस्यों को सार्वजनिक किए बिना ऑब्जेक्ट सदस्यों को पॉप्युलेट करने के लिए यहां सरल कार्य है। यह आपके स्वयं के उपयोग के लिए कन्स्ट्रक्टर छोड़ देता है, बिना कन्स्ट्रक्टर का आविष्कार किए ऑब्जेक्ट का नया उदाहरण बना देता है! तो, आपका डोमेन ऑब्जेक्ट डेटाबेस पर निर्भर नहीं है!


/** 
* Create new instance of a specified class and populate it with given data. 
* 
* @param string $className 
* @param array $data e.g. array(columnName => value, ..) 
* @param array $mappings Map column name to class field name, e.g. array(columnName => fieldName) 
* @return object Populated instance of $className 
*/ 
function createEntity($className, array $data, $mappings = array()) 
{ 
    $reflClass = new ReflectionClass($className); 
    // Creates a new instance of a given class, without invoking the constructor. 
    $entity = unserialize(sprintf('O:%d:"%s":0:{}', strlen($className), $className)); 
    foreach ($data as $column => $value) 
    { 
     // translate column name to an entity field name 
     $field = isset($mappings[$column]) ? $mappings[$column] : $column; 
     if ($reflClass->hasProperty($field)) 
     { 
      $reflProp = $reflClass->getProperty($field); 
      $reflProp->setAccessible(true); 
      $reflProp->setValue($entity, $value); 
     } 
    } 
    return $entity; 
} 

/******** And here is example ********/ 

/** 
* Your domain class without any database specific code! 
*/ 
class Employee 
{ 
    // Class members are not accessible for outside world 
    protected $id; 
    protected $name; 
    protected $email; 

    // Constructor will not be called by createEntity, it yours! 
    public function __construct($name, $email) 
    { 
     $this->name = $name; 
     $this->emai = $email; 
    } 

    public function getId() 
    { 
     return $this->id; 
    } 

    public function getName() 
    { 
     return $this->name; 
    } 

    public function getEmail() 
    { 
     return $this->email; 
    } 
} 


$row = array('employee_id' => '1', 'name' => 'John Galt', 'email' => '[email protected]'); 
$mappings = array('employee_id' => 'id'); // Employee has id field, so we add translation for it 
$john = createEntity('Employee', $row, $mappings); 

print $john->getName(); // John Galt 
print $john->getEmail(); // [email protected] 
//... 

पी.एस. ऑब्जेक्ट से डेटा पुनर्प्राप्त करना समान है, उदा। $ reflProp-> setValue ($ इकाई, $ मान) का उपयोग करें; पी.पी.एस. यह फ़ंक्शन Doctrine2 ORM से बहुत प्रेरित है जो कि कमाल है!

1

stdClass बढ़ाएं।

class MyClass extends stdClass 
{ 
    public function __construct() 
    { 
     $this->prop=1; 
    } 
} 

मुझे उम्मीद है कि आपको यही चाहिए।

+0

की निजी पहुंच को बदलने में मदद कर सकता है यह प्रश्न में निर्दिष्ट अनुसार "गतिशील रूप से" नहीं है। –

2
class DataStore // Automatically extends stdClass 
{ 
    public function __construct($Data) // $Data can be array or stdClass 
    { 
    foreach($Data AS $key => $value) 
    { 
     $this->$key = $value;  
    } 
    } 
} 

$arr = array('year_start' => 1995, 'year_end' => 2003); 
$ds = new DataStore($arr); 

$gap = $ds->year_end - $ds->year_start; 
echo "Year gap = " . $gap; // Outputs 8 
+0

'कक्षा डेटास्टोर {} var_export (is_subclass_of (' डेटास्टोर ',' स्टड क्लास ')); '' false' है! कक्षाएं स्वचालित रूप से PHP में StdClass का विस्तार नहीं करती हैं। – Benjamin

+0

महोदय, मुझे लगा कि मैंने इसे कहीं php.net में पढ़ा है! इसके अलावा, यह कोड "123" आउटपुट करता है। । । [कोड] कक्षा foo { सार्वजनिक $ ए = 1; सार्वजनिक कार्य __construct() { $ यह-> बी = 2; } } $ बार = नया foo; $ बार-> सी = 3; echo $ bar-> a। $ Bar-> b। $ Bar-> c; [code] – Anthony

0

तुम सच में वास्तव में यह करना चाहिए, सबसे अच्छा तरीका है एक ArrayObject, कि यात्रा का समर्थन (foreach) को बनाए रखने के लिए अनुमति देता ओवरलोड है कि अभी भी अपने सभी गुण के माध्यम से लूप।

मैं ध्यान दें कि आप ने कहा, और मैं सिर्फ आपको आश्वस्त करना है कि कि जब तक तकनीकी रूप से एक सरणी पृष्ठभूमि में किया जा रहा है चाहता हूँ "एक सरणी का उपयोग किए बिना", तो आप इसे देखने के लिए कभी नहीं। आप सभी गुणों को -> properyname या foreach ($ name = $ $ value में $ वर्ग) के माध्यम से एक्सेस करते हैं।

यहां एक नमूना है जो मैं कल काम कर रहा था, ध्यान दें कि यह भी दृढ़ता से टाइप किया गया है। तो यदि आप "स्ट्रिंग" को आजमाते हैं और आपूर्ति करते हैं तो गुण "पूर्णांक" चिह्नित होते हैं तो एक त्रुटि फेंक दी जाएगी।

आप निश्चित रूप से इसे हटा सकते हैं।

एक एडप्रोपर्टी() सदस्य फ़ंक्शन भी है, हालांकि यह उदाहरण में प्रदर्शित नहीं होता है। इससे आपको बाद में गुण जोड़ने की अनुमति मिल जाएगी।

नमूना उपयोग:

$Action = new StronglyTypedDynamicObject("Action", 
      new StrongProperty("Player", "ActionPlayer"), // ActionPlayer 
      new StrongProperty("pos", "integer"), 
      new StrongProperty("type", "integer"), 
      new StrongProperty("amount", "double"), 
      new StrongProperty("toCall", "double")); 

    $ActionPlayer = new StronglyTypedDynamicObject("ActionPlayer", 
      new StrongProperty("Seat", "integer"), 
      new StrongProperty("BankRoll", "double"), 
      new StrongProperty("Name", "string")); 

    $ActionPlayer->Seat = 1; 
    $ActionPlayer->Name = "Doctor Phil"; 

    $Action->pos = 2; 
    $Action->type = 1; 
    $Action->amount = 7.0; 
    $Action->Player = $ActionPlayer; 

    $newAction = $Action->factory(); 
    $newAction->pos = 4; 

    print_r($Action); 
    print_r($newAction); 


    class StrongProperty { 
      var $value; 
      var $type; 
      function __construct($name, $type) { 
        $this->name = $name; 
        $this->type = $type; 
      } 

    } 

    class StronglyTypedDynamicObject extends ModifiedStrictArrayObject { 

      static $basic_types = array(
        "boolean", 
        "integer", 
        "double", 
        "string", 
        "array", 
        "object", 
        "resource", 
      ); 

      var $properties = array(
        "__objectName" => "string" 
      ); 

      function __construct($objectName /*, [ new StrongProperty("name", "string"), [ new StrongProperty("name", "string"), [ ... ]]] */) { 
        $this->__objectName = $objectName; 
        $args = func_get_args(); 
        array_shift($args); 
        foreach ($args as $arg) { 
          if ($arg instanceof StrongProperty) { 
            $this->AddProperty($arg->name, $arg->type); 
          } else { 
            throw new Exception("Invalid Argument"); 
          } 
        } 
      } 

      function factory() { 
        $new = clone $this; 
        foreach ($new as $key => $value) { 
          if ($key != "__objectName") { 
            unset($new[$key]); 
          } 
        } 

        // $new->__objectName = $this->__objectName; 
        return $new; 
      } 

      function AddProperty($name, $type) { 
        $this->properties[$name] = $type; 
        return; 

        if (in_array($short_type, self::$basic_types)) { 
          $this->properties[$name] = $type; 
        } else { 
          throw new Exception("Invalid Type: $type"); 
        } 
      } 

      public function __set($name, $value) { 
        self::sdprintf("%s(%s)\n", __FUNCTION__, $name); 
        $this->check($name, $value); 
        $this->offsetSet($name, $value); 
      } 

      public function __get($name) { 
        self::sdprintf("%s(%s)\n", __FUNCTION__, $name); 
        $this->check($name); 
        return $this->offsetGet($name); 
      } 

      protected function check($name, $value = "r4nd0m") { 
        if (!array_key_exists($name, $this->properties)) { 
          throw new Exception("Attempt to access non-existent property '$name'"); 
        } 

        $value__objectName = ""; 
        if ($value != "r4nd0m") { 
          if ($value instanceof StronglyTypedDynamicObject) { 
            $value__objectName = $value->__objectName; 
          } 
          if (gettype($value) != $this->properties[$name] && $value__objectName != $this->properties[$name]) { 
            throw new Exception("Attempt to set {$name} ({$this->properties[$name]}) with type " . gettype($value) . ".$value__objectName"); 
          } 
        } 
      } 
    } 

    class ModifiedStrictArrayObject extends ArrayObject { 
      static $debugLevel = 0; 

      /* Some example properties */ 

      static public function StaticDebug($message) { 
        if (static::$debugLevel > 1) { 
          fprintf(STDERR, "%s\n", trim($message)); 
        } 
      } 

      static public function sdprintf() { 
        $args = func_get_args(); 
        $string = call_user_func_array("sprintf", $args); 
        self::StaticDebug("D   " . trim($string)); 
      } 

      protected function check($name) { 
        if (!array_key_exists($name, $this->properties)) { 
          throw new Exception("Attempt to access non-existent property '$name'"); 
        } 
      } 

      //static public function sget($name, $default = NULL) { 
      /******/ public function get ($name, $default = NULL) { 
        self::sdprintf("%s(%s)\n", __FUNCTION__, $name); 
        $this->check($name); 
        if (array_key_exists($name, $this->storage)) { 
          return $this->storage[$name]; 
        } 
        return $default; 
      } 

      public function offsetGet($name) { 
        self::sdprintf("%s(%s)\n", __FUNCTION__, implode(",", func_get_args())); 
        $this->check($name); 
        return call_user_func_array(array(parent, __FUNCTION__), func_get_args()); 
      } 
      public function offsetSet($name, $value) { 
        self::sdprintf("%s(%s)\n", __FUNCTION__, implode(",", func_get_args())); 
        $this->check($name); 
        return call_user_func_array(array(parent, __FUNCTION__), func_get_args()); 
      } 
      public function offsetExists($name) { 
        self::sdprintf("%s(%s)\n", __FUNCTION__, implode(",", func_get_args())); 
        $this->check($name); 
        return call_user_func_array(array(parent, __FUNCTION__), func_get_args()); 
      } 
      public function offsetUnset($name) { 
        self::sdprintf("%s(%s)\n", __FUNCTION__, implode(",", func_get_args())); 
        $this->check($name); 
        return call_user_func_array(array(parent, __FUNCTION__), func_get_args()); 
      } 

      public function __toString() { 
        self::sdprintf("%s(%s)\n", __FUNCTION__, $name); 
        foreach ($this as $key => $value) { 
          $output .= "$key: $value\n"; 
        } 
        return $output; 
      } 

      function __construct($array = false, $flags = 0, $iterator_class = "ArrayIterator") { 
        self::sdprintf("%s(%s)\n", __FUNCTION__, implode(",", func_get_args())); 
        parent::setFlags(parent::ARRAY_AS_PROPS); 
      } 
    } 
7

क्यों हर उदाहरण इतनी जटिल है?

<?php namespace example; 

error_reporting(E_ALL | E_STRICT); 

class Foo 
{ 
    // class completely empty 
} 

$testcase = new Foo(); 
$testcase->example = 'Dynamic property'; 
echo $testcase->example; 
+0

@AdiCumpanasu \ error_reporting वास्तव में केवल "वैश्विक नेमस्पेस त्रुटि_ रिपोर्टिंग फ़ंक्शन" कह रहा है, यह एक बचने वाला चरित्र नहीं है; ठीक है क्योंकि सवाल पूछा गया था कि मुझे PHP में सही संस्करण लिखना अधिक परेशान करने के लिए मिला है (विशेष रूप से इस भ्रम के कारण लोगों को गैर-नामस्थान php में भी इस्तेमाल किया जाता है) फिर "php इसे समझ सकता है" संस्करण लिखना संशोधन ठीक है। – srcspider

0

@Udo's answer पढ़ने के बाद। मैं निम्नलिखित पैटर्न के साथ आया हूं, जो आपके कन्स्ट्रक्टर सरणी तर्क में जो भी आइटम है, उसके साथ क्लास इंस्टेंस को ब्लूट नहीं करता है, लेकिन फिर भी आप कक्षा में नए गुणों को कम और आसानी से टाइप करने देते हैं।

class DBModelConfig 
{ 
    public $host; 
    public $username; 
    public $password; 
    public $db; 
    public $port = '3306'; 
    public $charset = 'utf8'; 
    public $collation = 'utf8_unicode_ci'; 

    public function __construct($config) 
    { 
     foreach ($config as $key => $value) { 
      if (property_exists($this, $key)) { 
       $this->{$key} = $value; 
      } 
     } 
    } 
} 

तो फिर तुम जैसे सरणियों पारित कर सकते हैं:

[ 
    'host'  => 'localhost', 
    'driver' => 'mysql', 
    'username' => 'myuser', 
    'password' => '1234', 
    'charset' => 'utf8', 
    'collation' => 'utf8_unicode_ci', 
    'db'  => 'key not used in receiving class' 
] 
संबंधित मुद्दे