পিডিও ডাটাবেস কোয়েরিগুলি ডিবাগ করবেন কীভাবে?


140

পিডিওতে যাওয়ার আগে, আমি পিএইচপি-তে এসকিউএল কোয়েরিগুলি স্ট্রাক্ট করে স্ট্রিং করে তৈরি করেছিলাম। যদি আমার ডাটাবেস সিনট্যাক্স ত্রুটিটি পেয়ে থাকে তবে আমি কেবল চূড়ান্ত এসকিউএল কোয়েরি স্ট্রিং প্রতিধ্বনি করতে পারি, এটি ডাটাবেসে নিজেই চেষ্টা করে দেখতে পারি এবং ত্রুটিটি স্থির না করা পর্যন্ত এটি টুইট করতে পারি, তারপরে কোডটি আবার রেখে দেব।

প্রস্তুত পিডিও বিবৃতি দ্রুত এবং আরও ভাল এবং নিরাপদ, তবে একটি জিনিস আমাকে বিরক্ত করে: ডেটাবেসে প্রেরিত হওয়ার সাথে আমি চূড়ান্ত কোয়েরিটি কখনই দেখতে পাই না। আমি যখন আমার অ্যাপাচি লগ বা আমার কাস্টম লগ ফাইলের সিনট্যাক্স সম্পর্কে ত্রুটি পেয়েছি (কোনও catchব্লকের ভিতরে আমি ত্রুটিগুলি লগ করি ), তখন আমি তাদের কোয়েরিটি দেখতে পাচ্ছি না।

পিডিও দ্বারা প্রেরিত সম্পূর্ণ এসকিউএল কোয়েরিটি কি কোনও উপায়ে ডেটাবেজে প্রেরণ এবং কোনও ফাইলে লগইন করার উপায় আছে?


4
এটা তোলে হয় একটি ফাইলে লগ: /var/log/mysql/*। PDO বাউন্ড প্যারামিটারগুলি সিনট্যাক্স ত্রুটি সৃষ্টি করতে পারে না তাই আপনার প্রয়োজনীয় সমস্ত প্রস্তুত এসকিউএল কোয়েরি।
শিওনক্রস

1
স্ট্যাকওভারফ্লো / প্রশ্নগুলি / ২১০৫64৪/২ (স্বীকৃত উত্তরে নয়) কোডটি দেখুন । কিছু আপডেট পোস্ট করা হয়েছে তা নয়।
মাওগ বলছেন মনিকা

1
: সরল রচয়িতা মাধ্যমে এক-লাইন github.com/panique/pdo-debug
Sliq

2
জিওনক্রসের উত্তর আমাকে সাহায্য করেছিল। এই বৈশিষ্ট্যটি কীভাবে চালু করবেন সে সম্পর্কে এখানে একটি নিবন্ধ দেওয়া হয়েছে। এটি সার্ভারের অনেকগুলি ইনস্টলেশনতে ডিফল্ট হতে পারে। pontikis.net/blog/how-and-when-to-enable-mysql-logs
mrbinky3000

2
দিয়ে চেষ্টা করুনvar_dump($pdo_instance->debugDumpParams())
ড্যানিয়েল পেট্রোভালিয়েভ

উত্তর:


99

আপনি এটি বলুন:

এটি চূড়ান্ত কোয়েরিটি কখনই ডেটাবেজে প্রেরণ করা হয় না

ভাল, আসলে, প্রস্তুত বিবৃতি ব্যবহার করার সময়, " চূড়ান্ত ক্যোয়ারী " বলে কোনও জিনিস নেই :

  • প্রথমে ডিবিতে একটি বিবৃতি প্রেরণ করা হয়, এবং সেখানে প্রস্তুত করা হয়
    • ডাটাবেস ক্যোয়ারিকে পার্স করে এবং এর অভ্যন্তরীণ উপস্থাপনা তৈরি করে
  • এবং, আপনি যখন ভেরিয়েবলগুলি বাঁধেন এবং বিবৃতিটি কার্যকর করেন, কেবলমাত্র ভেরিয়েবলগুলি ডাটাবেসে প্রেরণ করা হয়
    • এবং ডাটাবেসটি বিবৃতিটির অভ্যন্তরীণ উপস্থাপনায় মানগুলিকে "ইনজেক্ট" করে


সুতরাং, আপনার প্রশ্নের উত্তর দিতে:

পিডিও দ্বারা প্রেরিত সম্পূর্ণ এসকিউএল কোয়েরিটি কি কোনও উপায়ে ডেটাবেজে প্রেরণ এবং কোনও ফাইলে লগইন করার উপায় আছে?

না: যেহেতু কোনও " সম্পূর্ণ এসকিউএল কোয়েরি " নেই তাই এটি ক্যাপচার করার কোনও উপায় নেই।


ডিবাগিংয়ের উদ্দেশ্যে আপনি যে সর্বোত্তম কাজটি করতে পারেন তা হ'ল স্টেটমেন্টের এসকিউএল স্ট্রিংয়ে মানগুলি ইনজেকশনের মাধ্যমে "রিয়েল" নির্মাণ "সত্য" এসকিউএল কোয়েরি।

আমি সাধারণত এই ধরণের পরিস্থিতিতে যা করি তা হ'ল:

  • স্থানধারকগুলির সাথে বিবৃতিটির সাথে সম্পর্কিত এসকিউএল কোডটি প্রতিধ্বনিত করুন
  • এবং প্যারামিটারগুলির মানগুলি প্রদর্শন করার ঠিক পরে var_dump (বা সমতুল্য) ব্যবহার করুন
  • এটি সম্ভবত কোনও ত্রুটি দেখতে যথেষ্ট, এমনকি যদি আপনার চালানোর জন্য কোনও "আসল" ক্যোয়ারী না থাকে।

ডিবাগিংয়ের ক্ষেত্রে এটি দুর্দান্ত নয় - তবে এটি প্রস্তুত বিবৃতিগুলির দাম এবং তারা যে সুবিধা নিয়ে আসে bring


1
দুর্দান্ত ব্যাখ্যা - ধন্যবাদ। স্পষ্টতই আমি কেবল এটি কীভাবে কাজ করে তা সম্পর্কে অস্পষ্ট ধারণা ছিল। আমি মনে করি যখন বিবৃতিটি প্রস্তুত করা হয়, ফলস্বরূপ বস্তুটিতে একটি হ্যাশ বা সংখ্যাসূচক আইডি থাকে যা প্লাগ ইন করার জন্য প্যারামিটারগুলি দিয়ে ডাটাবেসে ফিরে পাঠানো যায়
নাথান লং

আপনাকে স্বাগতম :-) ;;; এটি কীভাবে বিশদভাবে প্রয়োগ করা হয় তা আমি জানি না, তবে আমি মনে করি এটি এরকম কিছু - ফলাফল যাইহোক, ঠিক তেমনই; এটি প্রস্তুত বিবৃতি সহ দুর্দান্ত জিনিসগুলির মধ্যে একটি: যদি আপনাকে একই প্রশ্নটি অনেক সময় চালাতে হয় তবে তা কেবল ডিবিতে পাঠানো হবে এবং একবার প্রস্তুত করা হবে: প্রতিটি মৃত্যুদন্ড কার্যকর করার জন্য কেবলমাত্র ডেটা প্রেরণ করা হবে।
পাস্কাল মার্টিন

1
আপডেট: অ্যারন প্যাটারসন ২০১২ সালে রেইলসনফ-এ উল্লেখ করেছিলেন যে তিনি রেলগুলিতে আরও প্রস্তুত বিবৃতি যুক্ত করেছেন, তবে মাইএসকিউএল-এর চেয়ে পোস্টগ্র্যাস এসকিউএল-তে সুবিধাটি অনেক বেশি ভারী। তিনি বলেছিলেন যে এটি তৈরির প্রশ্নটি কার্যকর না করা পর্যন্ত মাইএসকিউএল আসলে ক্যোয়ারী প্ল্যান তৈরি করে না।
নাথান লং

85

ডাটাবেস লগ খুঁজছেন

যদিও পাস্কাল মার্টিন সঠিক যে পিডিও একবারে ডেটাবেজে সম্পূর্ণ কোয়েরি প্রেরণ করে না, রাইগুয়ের ডিবি'র লগিং ফাংশনটি ব্যবহার করার পরামর্শটি আমাকে সম্পূর্ণ জিজ্ঞাসাটি ডেটাবেস দ্বারা একত্রিত ও সম্পাদিত হিসাবে দেখতে পেয়েছিল

এখানে কীভাবে রয়েছে: (উইন্ডোজ মেশিনে এই নির্দেশাবলী মাইএসকিউএলের জন্য রয়েছে - আপনার মাইলেজটি ভিন্ন হতে পারে)

  • ইন my.ini, [mysqld]বিভাগের অধীনে , একটি যোগ করুনlog কমান্ড মতlog="C:\Program Files\MySQL\MySQL Server 5.1\data\mysql.log"
  • মাইএসকিউএল পুনরায় চালু করুন।
  • এটি সেই ফাইলের প্রতিটি ক্যোয়ারী লগ করা শুরু করবে।

এই ফাইলটি দ্রুত বাড়বে, সুতরাং এটি পরীক্ষা করে মুছে ফেলা এবং লগিং বন্ধ করে দেওয়ার বিষয়ে নিশ্চিত হন।


1
কেবল একটি নোট - আমার my.ini এর স্ল্যাশগুলি থেকে বাঁচতে হয়েছিল। সুতরাং, আমার এন্ট্রিতে লগ = "সি: \\ টেম্পের \\ মাইএসকিউএল \\ মাইএসকিএল.লগ" এর মতো কিছু লাগছিল।
জিম

4
এটি সেটিং এর উপর নির্ভর করে কাজ করতে পারেPDO::ATTR_EMULATE_PREPARES । : আরও তথ্যের জন্য এই উত্তরটি দেখুন stackoverflow.com/questions/10658865/#answer-10658929
webbiedave

23
আমি এর কারণে পিডিওকে ঘৃণা করি।
সালমান

1
@ ওয়েবিবিদেভে - ওহ, বাহ! আপনার লিঙ্কযুক্ত উত্তরটি বোঝায় যে আমার উত্তর কেবল তখনই কার্যকর হয় যখন PDO অনুকূলভাবে কাজ করে না, বরং মাইএসকিউএল বা পুরাতন ড্রাইভারের পুরানো সংস্করণের সাথে পিছনে সামঞ্জস্যের জন্য পুরো ক্যোয়ারী প্রেরণ করে। মজাদার.
নাথান লং

13
মাইএসকিউএল 5.5+ এর general_logপরিবর্তে আপনার প্রয়োজন logDev.mysql.com/doc/refman/5.5/en/query-log.html
অ্যাড্রিয়ান

17

নিশ্চিত যে আপনি এই মোডটি ব্যবহার করে ডিবাগ করতে পারেন {{ PDO::ATTR_ERRMODE }} আপনার ক্যোয়ারির আগে কেবল নতুন লাইন যুক্ত করুন তবে আপনি ডিবাগ লাইনগুলি দেখিয়ে দেবেন।

$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$db->query('SELECT *******');  

আপনি ->queryপ্রস্তুত বিবৃতি ব্যবহার করার সময় কল করা হবে না ?
EoghanM

17

সম্ভবত আপনি যা করতে চান তা হল স্টেটমেন্ট হ্যান্ডলে ডিবাগডাম্পপ্যারাম () ব্যবহার করা । প্রস্তুত ক্যোয়ারিতে মানগুলি আবদ্ধ করার পরে আপনি যে কোনও সময় এটি চালাতে পারেন (প্রয়োজন নেইexecute() বিবৃতিতে )।

এটি আপনার জন্য প্রস্তুত বিবৃতি তৈরি করে না, তবে এটি আপনার পরামিতিগুলি দেখায়।


2
একমাত্র সমস্যা হ'ল এটি 'প্রতিধ্বনি' না করে এটি অভ্যন্তরীণভাবে সঞ্চয় করার পরিবর্তে ডিবাগটিকে আউটপুট করে। আমি এইভাবে এটি লগ না।
রিকার্ডো মার্টিনস

3
আউটপুট সংরক্ষণ এবং লগ করতে আপনি আউটপুট বাফারিং (ob_start () ...) ব্যবহার করতে পারেন।
ক্র্যানিও

bugs.php.net/bug.php?id=52384 7.1 এ স্থির আপনি মানগুলি দেখতে পারেন :) কিছুটা দেরি হলেও এটি পিএইচপি
স্যান্ডার ভিজার

12

একটি পুরানো পোস্ট তবে সম্ভবত কেউ এটি দরকারী খুঁজে পেতে পারেন;

function pdo_sql_debug($sql,$placeholders){
    foreach($placeholders as $k => $v){
        $sql = preg_replace('/:'.$k.'/',"'".$v."'",$sql);
    }
    return $sql;
}

1
অনুরূপ ফাংশনের জন্য যা সংখ্যার পরামিতিগুলিও পরিচালনা করতে পারে, আমার উত্তরটি দেখুন (php.net- তে একজন মন্তব্যকারীকে ধন্যবাদ)।
ম্যাট ব্রাউন

9

এখানে তা দেখতে কার্যকর এসকিউএল হতে হবে একটি ফাংশন এ "মার্ক" দ্বারা একটি মন্তব্য থেকে adpated এর php.net :

function sql_debug($sql_string, array $params = null) {
    if (!empty($params)) {
        $indexed = $params == array_values($params);
        foreach($params as $k=>$v) {
            if (is_object($v)) {
                if ($v instanceof \DateTime) $v = $v->format('Y-m-d H:i:s');
                else continue;
            }
            elseif (is_string($v)) $v="'$v'";
            elseif ($v === null) $v='NULL';
            elseif (is_array($v)) $v = implode(',', $v);

            if ($indexed) {
                $sql_string = preg_replace('/\?/', $v, $sql_string, 1);
            }
            else {
                if ($k[0] != ':') $k = ':'.$k; //add leading colon if it was left out
                $sql_string = str_replace($k,$v,$sql_string);
            }
        }
    }
    return $sql_string;
}

"মার্ক" কেন $ কে ইন করার আগে কোলন ব্যবহার করে str_replace(":$k" ....? সহযোগী সূচকগুলি ইতিমধ্যে এটি $ প্যারাম অ্যারেতে রয়েছে।
অ্যালান

ভাল প্রশ্ন ... এটি এটি ব্যাখ্যা করতে পারে: stackoverflow.com/questions/9778887/… । ব্যক্তিগতভাবে আমি এই ফাংশনটি ডক্ট্রিন কোয়েরিগুলি ডিবাগ করার জন্য ব্যবহার করেছি এবং আমি মনে করি যে ডক্ট্রাইন নামক পরামিতিগুলির পরিবর্তে সংখ্যাযুক্ত ব্যবহার করে তাই আমি এই সমস্যাটি লক্ষ্য করিনি। আমি ফাংশনটি আপডেট করেছি যাতে এটি এখন নেতৃত্বাধীন কলোনগুলির সাথে বা ছাড়াই কাজ করবে।
ম্যাট ব্রাউন

দ্রষ্টব্য, এই সমাধানটি প্রতিস্থাপন :name_longকরে :name। কমপক্ষে যদি :nameআগে আসে :name_long। মাইএসকিউএল প্রস্তুত বিবৃতি এটিকে সঠিকভাবে পরিচালনা করতে পারে, সুতরাং এটি আপনাকে বিভ্রান্ত না করে।
জিম 84

8

নং PDO প্রশ্নগুলি ক্লায়েন্টের পক্ষে প্রস্তুত করা হয়নি। পিডিও সহজেই এসকিউএল কোয়েরি এবং প্যারামিটারগুলি ডাটাবেস সার্ভারে প্রেরণ করে। ডাটাবেসের কি (এর প্রতিকল্পন নেই ?'গুলি)। আপনার দুটি বিকল্প রয়েছে:

  • আপনার ডিবির লগিং ফাংশনটি ব্যবহার করুন (তবে তারপরেও এটি সাধারণত দুটি পৃথক স্টেটমেন্ট হিসাবে দেখানো হয় (কমপক্ষে পোস্টগ্রিসের সাথে "চূড়ান্ত নয়"))
  • এসকিউএল ক্যোয়ারী এবং পরামিতিগুলি আউটপুট করুন এবং এটিকে নিজেই টুকরো টুকরো করুন

আমি কখনই ডিবির লগ চেক করার কথা ভাবিনি। আমি মাইএসকিউএল ডিরেক্টরিতে ঘুরে বেড়াচ্ছি এবং কোনও লগ ফাইল দেখতে পাচ্ছি না তবে লগইন এমন একটি বিকল্প যা আমাকে কোথাও চালু করতে হবে।
নাথান লং

হ্যাঁ, আপনি এটি চালু করতে হবে। আমি নির্দিষ্টকরণগুলি জানি না কিন্তু ডিফল্টরূপে এটি প্রতিটি ক্যোয়ারী লগ করে না।
রাইগুয়ে

5

প্রায়শই ত্রুটি প্রদর্শন ত্রুটি লগ ব্যতীত প্রদর্শন সম্পর্কে কিছুই বলা হয়নি, তবে এর পরিবর্তে সহায়ক কার্যকারিতা রয়েছে:

<?php
/* Provoke an error -- bogus SQL syntax */
$stmt = $dbh->prepare('bogus sql');
if (!$stmt) {
    echo "\PDO::errorInfo():\n";
    print_r($dbh->errorInfo());
}
?>

( উত্স লিঙ্ক )

এটি স্পষ্ট যে এই কোডটি ব্যতিক্রম বার্তা বা অন্য কোনও ধরণের ত্রুটি হ্যান্ডলিং হিসাবে ব্যবহার করতে সংশোধন করা যেতে পারে


2
এটি ভুল উপায়। এই কোডটি অকেজো করার জন্য পিডিও যথেষ্ট স্মার্ট। কেবল ত্রুটিগুলিতে ব্যতিক্রম ছুঁড়ে ফেলতে বলুন। পিএইচপি এই সীমিত ফাংশনটির চেয়ে আরও ভালভাবে কাজ করবে। এছাড়াও, দয়া করে , সমস্ত ত্রুটি সরাসরি ব্রাউজারে মুদ্রণ করতে শিখুন। আরও ভাল উপায় আছে।
আপনার সাধারণ জ্ঞান

3
এটি অফিশিয়াল ডকুমেন্টেশন, এবং অবশ্যই কেউই ত্রুটিটিকে প্রডাক্টে মুদ্রণ করতে যাচ্ছিল না, এটি আবার অফিসিয়াল সাইট (php.net) থেকে একটি উদাহরণ, কোড উদাহরণের নীচে লিঙ্কটি দেখুন। এবং নিশ্চিতভাবে পিডিও ইনস্ট্যান্টিয়েশনের মধ্যে অতিরিক্ত প্যারামগুলি $ db-> setAttribute (PDO :: ATTR_ERRMODE, PDO :: ERRMODE_EXCEPTION) ব্যবহার করা আরও ভাল তবে দুর্ভাগ্যক্রমে আপনি সেই
কোডটিতে

4

উদাহরণস্বরূপ আপনার এই পিডিও বিবৃতি রয়েছে:

$query="insert into tblTest (field1, field2, field3)
values (:val1, :val2, :val3)";
$res=$db->prepare($query);
$res->execute(array(
  ':val1'=>$val1,
  ':val2'=>$val2,
  ':val3'=>$val3,
));

এখন আপনি এই জাতীয় অ্যারে সংজ্ঞায়িত করে সম্পাদিত ক্যোয়ারী পেতে পারেন:

$assoc=array(
  ':val1'=>$val1,
  ':val2'=>$val2,
  ':val3'=>$val3,
);
$exQuery=str_replace(array_keys($assoc), array_values($assoc), $query);
echo $exQuery;

1
আমার জন্য কাজ করেছেন। দ্বিতীয় কোডের নমুনায় আপনার ভুল হয়েছে: ));হওয়া উচিত );(কেবলমাত্র একটি বৃত্তাকার বন্ধনী)।
জেসম ডটনেট

2

ইন্টারনেট অনুসন্ধান করে আমি এটি একটি গ্রহণযোগ্য সমাধান হিসাবে পেয়েছি। ম্যাজিক ফাংশন কলগুলির মাধ্যমে PDO এবং PDO ফাংশনের পরিবর্তে একটি পৃথক শ্রেণি ব্যবহৃত হয়। আমি নিশ্চিত নই যে এটি গুরুতর পারফরম্যান্স সমস্যা তৈরি করে। তবে এটি ব্যবহার করা যায় যতক্ষণ না পিডিওতে বুদ্ধিমান লগিং বৈশিষ্ট্য যুক্ত করা হয়।

সুতরাং এই থ্রেড অনুযায়ী , আপনি আপনার PDO সংযোগের জন্য একটি মোড়ক লিখতে পারেন যা লগ করতে পারে এবং কোনও ত্রুটি পেলে ব্যতিক্রম ছুঁড়ে ফেলতে পারে।

এখানে সহজ উদাহরণ:

class LoggedPDOSTatement extends PDOStatement    {

function execute ($array)    {
    parent::execute ($array);
    $errors = parent::errorInfo();
    if ($errors[0] != '00000'):
        throw new Exception ($errors[2]);
    endif;
  }

}

যাতে আপনি PDOStatement এর পরিবর্তে সেই শ্রেণিটি ব্যবহার করতে পারেন:

$this->db->setAttribute (PDO::ATTR_STATEMENT_CLASS, array ('LoggedPDOStatement', array()));

এখানে একটি উল্লিখিত পিডিও সজ্জা বাস্তবায়ন:

class LoggedPDOStatement    {

function __construct ($stmt)    {
    $this->stmt = $stmt;
}

function execute ($params = null)    {
    $result = $this->stmt->execute ($params); 
    if ($this->stmt->errorCode() != PDO::ERR_NONE):
        $errors = $this->stmt->errorInfo();
        $this->paint ($errors[2]);
    endif;
    return $result;
}

function bindValue ($key, $value)    {
    $this->values[$key] = $value;    
    return $this->stmt->bindValue ($key, $value);
}

function paint ($message = false)    {
    echo '<pre>';
    echo '<table cellpadding="5px">';
    echo '<tr><td colspan="2">Message: ' . $message . '</td></tr>';
    echo '<tr><td colspan="2">Query: ' . $this->stmt->queryString . '</td></tr>';
    if (count ($this->values) > 0):
    foreach ($this->values as $key => $value):
    echo '<tr><th align="left" style="background-color: #ccc;">' . $key . '</th><td>' . $value . '</td></tr>';
    endforeach;
    endif;
    echo '</table>';
    echo '</pre>';
}

function __call ($method, $params)    {
    return call_user_func_array (array ($this->stmt, $method), $params); 
}

}

2

WAMP- এ মাইএসকিউএল লগ ইন করতে , সম্পাদনা করতে my.ini প্রয়োজন হবে (যেমন অধীন wamp \ বিন \ মাইএসকিউএল \ mysql5.6.17 \ my.ini)

এবং এতে যুক্ত করুন [mysqld]:

general_log = 1
general_log_file="c:\\tmp\\mysql.log"

1

"সমাধান করা" পরামিতিগুলির সাথে একটি এসকিউএল কোয়েরিটি ফেরত দেওয়ার জন্য এখানে একটি ফাংশন দেওয়া হয়েছে।

function paramToString($query, $parameters) {
    if(!empty($parameters)) {
        foreach($parameters as $key => $value) {
            preg_match('/(\?(?!=))/i', $query, $match, PREG_OFFSET_CAPTURE);
            $query = substr_replace($query, $value, $match[0][1], 1);
        }
    }
    return $query;
    $query = "SELECT email FROM table WHERE id = ? AND username = ?";
    $values = [1, 'Super'];

    echo paramToString($query, $values);

ধরে নিচ্ছি আপনি এভাবে চালিত হন

$values = array(1, 'SomeUsername');
$smth->execute($values);

এই ফাংশনটি ক্যোয়ারিতে উদ্ধৃতি যোগ করে না তবে আমার কাজটি করে।


0

ডিবাগিংয়ের উদ্দেশ্যে পিডিও ছাড়গুলি ধরার সমাধানের সাথে আমার যে সমস্যাটি হয়েছিল তা হ'ল এটি কেবল পিডিও ছাড় (দুহ) কেড়ে নিয়েছিল, তবে পিএইচপি ত্রুটি হিসাবে নিবন্ধিত সিনট্যাক্স ত্রুটিগুলি ধরেনি (কেন এটি নিশ্চিত তা আমি নিশ্চিত নই, তবে " কেন "সমাধানটি অপ্রাসঙ্গিক)। আমার সমস্ত পিডিও কলগুলি একটি একক টেবিল মডেল শ্রেণীর কাছ থেকে আসে যা আমি সমস্ত টেবিলের সাথে আমার সমস্ত মিথস্ক্রিয়াটির জন্য প্রসারিত করেছিলাম ... এই জটিল জিনিসগুলি যখন আমি কোডটি ডিবাগ করার চেষ্টা করছিলাম, কারণ ত্রুটিটি পিএইচপি কোডের লাইনটি নিবন্ধিত করবে যেখানে আমার এক্সিকিউট কল ছিল was কল করা হয়েছিল, কিন্তু কলটি কোথা থেকে এসেছে তা আসলে আমাকে বলা হয়নি। আমি এই সমস্যাটি সমাধানের জন্য নিম্নলিখিত কোডগুলি ব্যবহার করেছি:

/**
 * Executes a line of sql with PDO.
 * 
 * @param string $sql
 * @param array $params
 */
class TableModel{
    var $_db; //PDO connection
    var $_query; //PDO query

    function execute($sql, $params) { 
        //we're saving this as a global, so it's available to the error handler
        global $_tm;
        //setting these so they're available to the error handler as well
        $this->_sql = $sql;
        $this->_paramArray = $params;            

        $this->_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->_query = $this->_db->prepare($sql);

        try {
            //set a custom error handler for pdo to catch any php errors
            set_error_handler('pdoErrorHandler');

            //save the table model object to make it available to the pdoErrorHandler
            $_tm = $this;
            $this->_query->execute($params);

            //now we restore the normal error handler
            restore_error_handler();
        } catch (Exception $ex) {
            pdoErrorHandler();
            return false;
        }            
    }
}

সুতরাং, উপরের কোডটি দুটি PDO ব্যতিক্রম এবং পিএইচপি সিনট্যাক্স ত্রুটিগুলি ধরে এবং তাদের সাথে একইভাবে আচরণ করে। আমার ত্রুটি হ্যান্ডলারটি এরকম কিছু দেখাচ্ছে:

function pdoErrorHandler() {
    //get all the stuff that we set in the table model
    global $_tm;
    $sql = $_tm->_sql;
    $params = $_tm->_params;
    $query = $tm->_query;

    $message = 'PDO error: ' . $sql . ' (' . implode(', ', $params) . ") \n";

    //get trace info, so we can know where the sql call originated from
    ob_start();
    debug_backtrace(); //I have a custom method here that parses debug backtrace, but this will work as well
    $trace = ob_get_clean();

    //log the error in a civilized manner
    error_log($message);

    if(admin(){
        //print error to screen based on your environment, logged in credentials, etc.
        print_r($message);
    }
}

গ্লোবাল ভেরিয়েবল হিসাবে টেবিলের মডেলটি সেট করার চেয়ে কারও কাছে যদি আমার ত্রুটি হ্যান্ডলারের কাছে প্রাসঙ্গিক তথ্য কীভাবে পাওয়া যায় সে সম্পর্কে আরও ভাল ধারণা থাকে তবে আমি এটি শুনে এবং আমার কোডটি সম্পাদনা করে খুশি হব।


0

এই কোডটি আমার পক্ষে দুর্দান্ত কাজ করে:

echo str_replace(array_keys($data), array_values($data), $query->queryString);

আপনার নাম দ্বারা ডেটা এবং $ কোয়েরি প্রতিস্থাপন করতে ভুলবেন না


0

আমি PDO ডিবাগ করার জন্য এই ক্লাসটি ব্যবহার করি (লগ 4PHP সহ )

<?php

/**
 * Extends PDO and logs all queries that are executed and how long
 * they take, including queries issued via prepared statements
 */
class LoggedPDO extends PDO
{

    public static $log = array();

    public function __construct($dsn, $username = null, $password = null, $options = null)
    {
        parent::__construct($dsn, $username, $password, $options);
    }

    public function query($query)
    {
        $result = parent::query($query);
        return $result;
    }

    /**
     * @return LoggedPDOStatement
     */
    public function prepare($statement, $options = NULL)
    {
        if (!$options) {
            $options = array();
        }
        return new \LoggedPDOStatement(parent::prepare($statement, $options));
    }
}

/**
 * PDOStatement decorator that logs when a PDOStatement is
 * executed, and the time it took to run
 * @see LoggedPDO
 */
class LoggedPDOStatement
{

    /**
     * The PDOStatement we decorate
     */
    private $statement;
    protected $_debugValues = null;

    public function __construct(PDOStatement $statement)
    {
        $this->statement = $statement;
    }

    public function getLogger()
    {
        return \Logger::getLogger('PDO sql');
    }

    /**
     * When execute is called record the time it takes and
     * then log the query
     * @return PDO result set
     */
    public function execute(array $params = array())
    {
        $start = microtime(true);
        if (empty($params)) {
            $result = $this->statement->execute();
        } else {
            foreach ($params as $key => $value) {
                $this->_debugValues[$key] = $value;
            }
            $result = $this->statement->execute($params);
        }

        $this->getLogger()->debug($this->_debugQuery());

        $time = microtime(true) - $start;
        $ar = (int) $this->statement->rowCount();
        $this->getLogger()->debug('Affected rows: ' . $ar . ' Query took: ' . round($time * 1000, 3) . ' ms');
        return $result;
    }

    public function bindValue($parameter, $value, $data_type = false)
    {
        $this->_debugValues[$parameter] = $value;
        return $this->statement->bindValue($parameter, $value, $data_type);
    }

    public function _debugQuery($replaced = true)
    {
        $q = $this->statement->queryString;

        if (!$replaced) {
            return $q;
        }

        return preg_replace_callback('/:([0-9a-z_]+)/i', array($this, '_debugReplace'), $q);
    }

    protected function _debugReplace($m)
    {
        $v = $this->_debugValues[$m[0]];

        if ($v === null) {
            return "NULL";
        }
        if (!is_numeric($v)) {
            $v = str_replace("'", "''", $v);
        }

        return "'" . $v . "'";
    }

    /**
     * Other than execute pass all other calls to the PDOStatement object
     * @param string $function_name
     * @param array $parameters arguments
     */
    public function __call($function_name, $parameters)
    {
        return call_user_func_array(array($this->statement, $function_name), $parameters);
    }
}

0

আমি ঠিক এখানে এর জন্য একটি আধুনিক সুরকার-বোঝা প্রকল্প / সংগ্রহস্থল তৈরি করেছি:

PDO-ডিবাগ

প্রকল্পের গিটহাবের হোমটি এখানে সন্ধান করুন , এটির ব্যাখ্যা দিয়ে একটি ব্লগ পোস্ট দেখুন । আপনার রচয়িতা। জসনে যোগ করার জন্য একটি লাইন এবং তারপরে আপনি এটি ব্যবহার করতে পারেন:

echo debugPDO($sql, $parameters);

$ sql হ'ল কাঁচা এসকিউএল স্টেটমেন্ট, meters প্যারামিটারগুলি আপনার প্যারামিটারগুলির একটি অ্যারে: কীটি স্থানধারকের নাম (": user_id") বা নামবিহীন প্যারামিটারের সংখ্যা ("?"), মান হয় .. ভাল, মান।

পেছনের যুক্তি: এই স্ক্রিপ্টটি কেবলমাত্র পরামিতিগুলিকে গ্রেড করবে এবং সরবরাহিত এসকিউএল স্ট্রিংগুলিতে তাদের প্রতিস্থাপন করবে। আপনার ব্যবহারের 99% ক্ষেত্রে অতি-সহজ, তবে সুপার-কার্যকর। দ্রষ্টব্য: এটি কেবলমাত্র একটি প্রাথমিক অনুকরণ, কোনও সত্য PDO ডিবাগিং নয় (পিএইচপি মাইএসকিউএল সার্ভারকে পৃথক করে কাঁচা এসকিউএল এবং প্যারামিটার প্রেরণ করায় এটি সম্ভব নয়)।

একটি বড় ধন্যবাদ করার bigwebguy এবং মাইক Stackoverflow থ্রেড থেকে PDO থেকে কাঁচা SQL কোয়েরি স্ট্রিং পথ এই স্ক্রিপ্টের পিছনে মূলত সমগ্র প্রধান ফাংশন লেখার জন্য। বড়!


0

উবুন্টুতে পিডিও মাইএসকিএল ডাটাবেস অনুসন্ধানগুলি কীভাবে ডিবাগ করা যায়

টিএল; ডিআর আপনার সমস্ত প্রশ্নের লগইন করুন এবং মাইএসকিএল লগটি লেজ করুন।

এই দিকনির্দেশগুলি আমার উবুন্টু 14.04 ইনস্টল করার জন্য। lsb_release -aআপনার সংস্করণ পেতে আদেশ কমান্ড । আপনার ইনস্টল আলাদা হতে পারে।

মাইএসকিএল-এ লগিং চালু করুন

  1. আপনার ডেভ সার্ভার সেমিডি লাইনে যান
  2. ডিরেক্টরি পরিবর্তন করুন cd /etc/mysql। আপনার কাছে একটি ফাইল বলা উচিতmy.cnf । এটি সেই ফাইল যা আমরা পরিবর্তন করব।
  3. টাইপ করে আপনি সঠিক জায়গায় আছেন কিনা তা যাচাই করুন cat my.cnf | grep general_log। এটি my.cnfআপনার জন্য ফাইলটি ফিল্টার করে । আপনি দুটি এন্ট্রি দেখতে পাবেন: #general_log_file = /var/log/mysql/mysql.log&& #general_log = 1
  4. এই দুটি লাইন কমেন্ট করুন এবং আপনার পছন্দসই সম্পাদকের মাধ্যমে সংরক্ষণ করুন।
  5. পুনর্সূচনা MySQL: sudo service mysql restart
  6. আপনার ওয়েবসারভারটিও আবার চালু করতে হবে। (আমি যে ক্রমটি ব্যবহার করেছি তা প্রত্যাহার করতে পারি না)। আমার ইনস্টল জন্য, যে nginx: sudo service nginx restart

চমৎকার কাজ! আপনি সব সেট. এখন আপনাকে যা করতে হবে তা হ'ল লগ ফাইলটি লেগেছে যাতে আপনি আপনার অ্যাপ্লিকেশনটিকে রিয়েল টাইমে তৈরি পিডিও ক্যোরিগুলি দেখতে পাবেন।

আপনার প্রশ্নগুলি দেখতে লগটি টেইল করুন

এই সেন্টিমিটার প্রবেশ করান tail -f /var/log/mysql/mysql.log

আপনার আউটপুট এইরকম কিছু দেখবে:

73 Connect  xyz@localhost on your_db
73 Query    SET NAMES utf8mb4
74 Connect  xyz@localhost on your_db
75 Connect  xyz@localhost on your_db
74 Quit 
75 Prepare  SELECT email FROM customer WHERE email=? LIMIT ?
75 Execute  SELECT email FROM customer WHERE email='a@b.co' LIMIT 5
75 Close stmt   
75 Quit 
73 Quit 

আপনার অ্যাপ্লিকেশন তৈরি করে এমন কোনও নতুন ক্যোয়ারী স্বয়ংক্রিয়ভাবে দর্শন হিসাবে পপ হবে , যতক্ষণ আপনি লগটি লেজু করা চালিয়ে যান। লেজ থেকে প্রস্থান করতে, আঘাত করুনcmd/ctrl c

মন্তব্য

  1. যত্নবান: এই লগ ফাইলটি বিশাল আকার ধারণ করতে পারে। আমি এটি কেবল আমার ডেভ সার্ভারে চালাচ্ছি।
  2. লগ ফাইল খুব বড় হচ্ছে? এটি কাটা। তার মানে ফাইলটি স্থির থাকে তবে সামগ্রীগুলি মুছে ফেলা হয়। truncate --size 0 mysql.log
  3. লগ ফাইলটি মাইএসকিএল সংযোগগুলি তালিকাভুক্ত করে। আমি জানি যে এর মধ্যে একটি আমার উত্তরাধিকারের মাইএসকিলি কোড থেকে যা থেকে আমি স্থানান্তরিত করছি। তৃতীয়টি আমার নতুন পিডিও সংযোগ থেকে। তবে, দ্বিতীয়টি কোথা থেকে আসছে তা নিশ্চিত নয়। আপনি যদি এটির সন্ধানের কোনও দ্রুত উপায় জানেন তবে আমাকে জানান।

ক্রেডিট এবং ধন্যবাদ

উসুন্টুকে এই বিষয়টি বোঝার জন্য উপরের নাথন লংয়ের উত্তরে চিৎকার করলেন । এছাড়াও থেকে dikirill নাথান এর পোস্ট যা আমাকে এই সমাধান হতে তার মন্তব্যের জন্য।

আপনাকে স্ট্যাকওভারফ্লো!


0

ডেবিয়ান এনজিআইএনএক্স পরিবেশে আমি নিম্নলিখিতগুলি করেছি।

এতে যান /etc/mysql/mysql.conf.dসম্পাদন করা mysqld.cnfআপনাকে খুঁজে যদি log-error = /var/log/mysql/error.logযোগ নিম্নলিখিত 2 লাইন এটিকে নীচে।

general_log_file        = /var/log/mysql/mysql.log
general_log             = 1

লগ এতে যান দেখার জন্য /var/log/mysqlএবং tail -f mysql.log

আপনি যদি পরিবেশের পরিবেশে থাকেন তবে mysql.logএই লগ ফাইলটি দ্রুত বৃদ্ধি পাবে এবং বিশাল আকার ধারণ করতে পারে তাই আপনি যদি ডিবাগিংয়ের সাথে কাজ শেষ করেন তবে এই লাইনগুলি মন্তব্য করতে ভুলবেন না।


প্রত্যেকে মাইএসকিএল ব্যবহার করে না।
ভয়ঙ্কর সেমিকোলন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.