php - पीडीओ खाली संपत्ति नाम लौट रहा है




pdo odbc (2)

मुझे pdo_odbc और PDO :: FETCH_OBJ (और पीडीओ :: FETCH_CLASS) के साथ एक अजीब समस्या है जिसके परिणामस्वरूप निम्न त्रुटि संदेश होता है:

PHP Fatal error:  Cannot access empty property

यहां कोड है:

$dbh = new PDO("odbc:FOO");

$sth = $dbh->query("
  SELECT rolename
  FROM dbc.allrolerights
  WHERE databasename = 'BAR'
");

$result = $sth->fetch(PDO::FETCH_OBJ);

संदर्भ के लिए, खाद्य डीएसएन, tdodbc पैकेज द्वारा प्रदान किए गए tdata.so ड्राइवर का उपयोग कर टेराडाटा डेटास्रोत है।

मेरा मानना ​​है कि यह हो रहा है क्योंकि फ़ील्ड नाम (ओडीबीसी क्वेरी से लौटाया गया है) जब पीडीओ stdClass ऑब्जेक्ट को तुरंत चालू करने के लिए zend_API.h: object_init_ex () को कॉल करता है। यदि मैं पीडीओ :: FETCH_LAZY और var_dump () पंक्ति पर स्विच करता हूं, तो मुझे निम्न मिलता है:

object(PDORow)#3 (2) {
  ["queryString"]=>
  string(95) "
  SELECT rolename
  FROM dbc.allrolerights
  WHERE databasename = 'BAR'
"
  [""]=>
  string(30) "FNAR                          "
}

जो इसे वापस करने लगता है। मैंने समस्या के आसपास काम करने के लिए कई अलग-अलग पीडीओ विशेषता संयोजन और विभिन्न कोणों का गुच्छा करने की कोशिश की है। एक समाधान एक सहयोगी सरणी लाने और इसे कक्षा कन्स्ट्रक्टर को पास करना है। हालांकि, यह दृश्यों के पीछे सीधे पीडीओ :: FETCH_CLASS का उपयोग कर रहे कुछ ढांचे और ओआरएम के लिए काम नहीं करता है।

मैं जोड़ना चाहता हूं कि अन्य fetch विधियां सही चीज़ करने लगती हैं, उदाहरण के लिए, पीडीओ :: FETCH_NAMED:

array(1) {
  ["RoleName"]=>
  string(30) "FNAR                          "
}

मैं इस समस्या को हल करने के लिए पीडीओ डीबीएच या एसएचएच परिभाषा में, या odbc.ini या odbcinst.ini में डाल सकता हूं। पहले ही, आपका बहुत धन्यवाद।

अद्यतन: odbc_fetch_object () (यानी पीडीओ नहीं) एक ही सटीक सब कुछ के साथ महान काम करता है। बस इसका जिक्र करना चाहता था। PHP, यूनिक्सोडबीसी, या ओडीबीसी ड्राइवर के साथ स्पष्ट रूप से कोई गंभीर समस्या प्रतीत नहीं होती है। यह पीडीओ कोड में कुछ है। एक बग रिपोर्ट खोलने का समय ... opened

$dbh = odbc_connect("FOO", NULL, NULL)
  or die(odbc_error_msg());

$sth = odbc_exec($dbh, "
  SELECT rolename
  FROM dbc.allrolerights
  WHERE databasename = 'BAR'
");

$result = odbc_fetch_object($sth);
var_dump($result);

और आउटपुट:

object(stdClass)#1 (1) {
  ["RoleName"]=>
  string(30) "FNAR                          "
}

अद्यतन 2: स्थिति अधिक से अधिक विचित्र बढ़ती जा रही है। मैं एक पीडीओ :: FETCH_LAZY कर सकता हूं और उपरोक्त var_dump () में देखे गए खाली कॉलम नाम को देख सकता हूं, लेकिन अगर मैं नाम से संपत्ति तक पहुंचने का प्रयास करता हूं (उदाहरण के लिए $ परिणाम-> रोलनाम), यह काम करता है! ये fetch विधियां इतनी अलग तरीके से क्या कर रही हैं कि उनमें से कुछ कभी-कभी फ़ील्ड नामों तक पहुंच सकते हैं, और अन्य नहीं कर सकते हैं?

ओडीबीसी निशान ("काम कर रहे" सीएफ "काम नहीं कर रहे" की साइड-बाय-साइड तुलना) कोई मतभेद नहीं दिखाता है (विभिन्न सूचक पते के अलावा)। पीडीओ :: FETCH_BOUND क्रमांकित और नामित कॉलम दोनों के साथ काम करता है। पीडीओ :: FETCH_INTO एक रोलनाम संपत्ति वाला ऑब्जेक्ट नहीं है।


आपका प्रश्न दो समस्याओं का वर्णन करता है:

  1. ऐसा क्यों है कि PDO::FETCH_OBJ का उपयोग करते समय वस्तुओं को रिक्त-स्ट्रिंग नाम वाले गुणों के साथ नहीं बनाया जा सकता है, लेकिन स्पष्ट रूप से अन्य तरीकों का उपयोग करते समय कर सकते हैं?

    PHP आंतरिक पुस्तक में आंतरिक संरचनाओं और प्रत्यारोपण के तहत दस्तावेज के रूप में, " गतिशील properties " (यानी किसी ऑब्जेक्ट के सदस्य चर जो इसकी कक्षा परिभाषा में घोषित नहीं होते हैं, बल्कि रनटाइम पर बनाए जाते हैं) को हैश तालिका के रूप में लागू किया जाता है।

    यदि कोई हैश तालिका में वर्तमान में रखे गए गुणों के समूह के साथ एक नई तत्काल मानक वस्तु को पॉप्युलेट करना चाहता है, तो कोई भी उस मौजूदा हैश object_and_properties_init() PHP की object_and_properties_init() फ़ंक्शन पर ऑब्जेक्ट के properties चर को इंगित कर सकता है, जिसे odbc_fetch_object() , ठीक है कि तालिका की चाबियों पर कोई सैनिटी जांच किए बिना । नतीजतन, कोई अजीब संपत्ति नामों (जैसे रिक्त स्ट्रिंग) के साथ किसी ऑब्जेक्ट को तुरंत चालू कर सकता है।

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

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

    पीडीओ इस सब में कैसे फिट है?

    PDOStatement::fetch() पहले गंतव्य को तैयार करता है जिसमें परिणाम संग्रहीत किए जाएंगे और फिर प्रत्येक फ़ील्ड को बदले में कॉलम पर फिर से PDOStatement::fetch() जाएगा: मुझे लगता है कि यह कोडबेस को सरल बनाने के लिए करता है, क्योंकि प्रत्येक fetch शैली को उसी के भीतर कार्यान्वित किया जा सकता है संरचना। हालांकि, इसका मतलब यह है कि जब PDO::FETCH_OBJ शैली (और PDO::FETCH_CLASS और PDO::FETCH_INTO दोनों के रूप में भी देखा जाता है), एक वस्तु को तुरंत चालू किया जाता है और इसकी गुण बाद में आबादी में PDO::FETCH_INTO । नतीजतन, अजीब संपत्ति के नाम (जैसे खाली स्ट्रिंग) परिणामस्वरूप विफलता में परिणाम।

    आपके द्वारा कोशिश की जाने वाली अन्य fetch शैलियों को एक ही समस्या का अनुभव नहीं है क्योंकि:

    • PDO::FETCH_BOUND वेरिएबल में PDO::FETCH_BOUND है जो पिछले कॉल द्वारा PDOStatement::bindColumn() को निर्दिष्ट किया गया था, इसलिए PHP कभी खाली नाम वाली किसी संपत्ति को लिखने का प्रयास नहीं करता है;

    • PDO::FETCH_LAZY पूरे PDO::FETCH_LAZY छोड़ देता है और उपरोक्त odbc_fetch_object() को समान तरीके से करता है।

    इसी तरह, सरणी-आधारित fetch शैलियों को समान समस्याएं नहीं आती हैं क्योंकि खाली हैरिंग कुंजी उन हैश तालिकाओं में पूरी तरह मान्य हैं।

  2. ऐसा क्यों है कि पीडीओ सोचता है कि इस ओडीबीसी रिकॉर्डसेट में कॉलम नाम खाली तार हैं?

    इसका उत्तर मेरे लिए बहुत कम स्पष्ट है।

    हमने पहले देखा था कि, गुणों को पॉप्युलेट करने के लिए, पीडीओ संपत्ति नाम के रूप में stmt->columns[i].name का उपयोग करता है। यह पहले बिंदु पर सही ढंग से भरा जाना चाहिए था , जब pdo_stmt_describe_columns() को बुलाया गया था । बदले में इस फ़ंक्शन ने परिणाम में प्रत्येक कॉलम के लिए ड्राइवर की describer विधि कहा था : PDO_ODBC के मामले में, यह odbc_stmt_describe() जो वास्तव में उस फ़ील्ड को मान निर्दिष्ट करता है।

    तो, सब कुछ PHP पक्ष पर ठीक दिखता है। यह जानना दिलचस्प होगा कि क्या ड्राइवर के SQLDescribeCol() फ़ंक्शन पर कॉल कॉलम नाम को बफर में सही तरीके से पॉप्युलेट किया गया है, जो कि तीसरा तर्क है: एक कल्पना नहीं, जो यह सुझाव देगी कि समस्या ओडीबीसी ड्राइवर में ही है। आपने उल्लेख किया है कि आप टेराडाटा का उपयोग कर रहे हैं: लेकिन क्या आप वाकई पीडीओ_ओडीबीसी (जो काम नहीं कर रहे हैं) और ext / odbc (जो है) दोनों के लिए एक ही ड्राइवर का उपयोग कर रहे हैं?

    विशेष रूप से, विस्तार स्तर कार्यों के तहत टेराडाटा दस्तावेज़:

    डिफ़ॉल्ट रूप से, SQLDescribeCol और SQLColAttribute Teradata कॉलम शीर्षक के बजाय कॉलम नाम लौटाता है। यदि कोई एप्लिकेशन वास्तविक कॉलम नाम के बजाय कॉलम शीर्षक वापस करने के लिए टेराडाटा के लिए ओडीबीसी चालक चाहता है, तो विकल्प टेराडाटा ओडीबीसी ड्राइवर विकल्प संवाद बॉक्स में कॉलम नामों का उपयोग करें डीएसएन के लिए इस्तेमाल नहीं किया जाना चाहिए, या DontUseTitles = No को सेट नहीं करना चाहिए यूनिक्स ओएस

    वास्तविक कॉलम नाम के बजाय कॉलम शीर्षक लौटने से क्रिस्टल रिपोर्ट्स जैसे कुछ अनुप्रयोगों के लिए समस्याएं हो सकती हैं, क्योंकि वे कॉलम नाम प्राप्त करने की उम्मीद करते हैं, न कि कॉलम शीर्षक।


मुझे लगता है कि अब तक "समाधान" लाने के लिए fetch शैली PDO :: FETCH_NAMED का उपयोग किया जाएगा और फिर लौटाए गए सरणी को परिवर्तित करें और गतिशील वर्ग को पॉप्युलेट करें:

function arrayToObject(array $array){
   $obj = new stdClass();
   foreach($array as $k => $v)
      $obj->$k = $v;

   return $obj;
}






teradata