রেফারেন্স: ভেরিয়েবল স্কোপ কী, কোন ভেরিয়েবলগুলি অ্যাক্সেসযোগ্য এবং কোথা থেকে "অপরিজ্ঞাত ভেরিয়েবল" ত্রুটি রয়েছে?


167

দ্রষ্টব্য: পিএইচপি-তে পরিবর্তনশীল সুযোগের সাথে ডিল করার জন্য এটি একটি রেফারেন্স প্রশ্ন। এই প্যাটার্নটির নকল হিসাবে এই প্যাটার্ন ফিট করে এমন অনেকগুলি প্রশ্নই বন্ধ করুন।

পিএইচপিতে "ভেরিয়েবল স্কোপ" কী? এক। Php ফাইল থেকে ভেরিয়েবলগুলি কি অন্যটিতে প্রবেশযোগ্য? আমি মাঝে মাঝে "অপরিজ্ঞাত পরিবর্তনশীল" ত্রুটিগুলি পাই কেন ?


1
আপনি যদি এটিকে "অপরিজ্ঞাত পরিবর্তনশীল" হিসাবে শিরোনাম করেন তবে আপনি আরও বেশি হিট পাবেন :) ভাল কাজ যদিও
ডেল

@ ডেল, আসলে না 2 বছরে 2 কে দর্শন হ'ল ....
পেসারিয়ার 8

7
@ পেসারিয়ার ... এলোমেলো মন্তব্য করার সঠিক সময় সম্পর্কে?
ডেল

@ পেসারিয়ার আমি আসলেই নিশ্চিত নই যে আপনি এই মন্তব্যে কী বলতে চাইছেন। "কি ...." ... কি ?! : পি
ডিজেজেজ

@Dale এখন সঠিক সময় আছে: ঘেউ যদিও প্রশ্নটা 2 বছরের জন্য থেমে পর শব্দ " আড়ম্বরহীন " তার GoogleDex, তার লক্ষ্যভেদ হার মাত্র 6 মাসে আক্ষরিক 3x-ED যোগ করা হয়।
পেসারিয়ার

উত্তর:


188

"পরিবর্তনশীল সুযোগ" কী?

ভেরিয়েবলের সীমিত "সুযোগ" বা "যে জায়গাগুলি থেকে তারা অ্যাক্সেসযোগ্য" রয়েছে have শুধু কারণ আপনি লিখেছেন $foo = 'bar';একবার কোথাও আপনার অ্যাপ্লিকেশনের মধ্যে তার মানে এই নয় আপনি পাঠাতে পারেন $fooথেকে সর্বত্র আবেদন ভিতরে অন্য। ভেরিয়েবলের $fooএকটি নির্দিষ্ট সুযোগ রয়েছে যার মধ্যে এটি বৈধ এবং একই স্কোপটিতে কেবল কোডটি ভেরিয়েবলটিতে অ্যাক্সেস পায়।

পিএইচপি-তে কীভাবে একটি স্কোপ সংজ্ঞায়িত করা হয়?

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

উদাহরণ:

<?php

$foo = 'bar';

function myFunc() {
    $baz = 42;
}

$fooহয় বিশ্বব্যাপী , সুযোগ $bazএকটি হল স্থানীয় সুযোগ ভিতরে myFunc। কেবলমাত্র অভ্যন্তরের myFuncকোডটিতে অ্যাক্সেস রয়েছে $baz। কেবলমাত্র বাইরের myFunc কোডটিতে অ্যাক্সেস রয়েছে $foo। অন্যের অ্যাক্সেস নেই:

<?php

$foo = 'bar';

function myFunc() {
    $baz = 42;

    echo $foo;  // doesn't work
    echo $baz;  // works
}

echo $foo;  // works
echo $baz;  // doesn't work

স্কোপ এবং অন্তর্ভুক্ত ফাইল

ফাইলের সীমানা স্কোপকে আলাদা করে না :

a.php

<?php

$foo = 'bar';

b.php

<?php

include 'a.php';

echo $foo;  // works!

অন্যান্য নিয়মের ক্ষেত্রে প্রযোজ্য একই কোডগুলি includeডি কোডের ক্ষেত্রে প্রযোজ্য: কেবলমাত্র functionপৃথক পৃথক সুযোগ। সুযোগের উদ্দেশ্যে, আপনি অনুলিপি এবং পেস্টিং কোডের মতো ফাইলগুলি অন্তর্ভুক্ত করার বিষয়ে ভাবতে পারেন:

c.php

<?php

function myFunc() {
    include 'a.php';

    echo $foo;  // works
}

myFunc();

echo $foo;  // doesn't work!

উপরের উদাহরণে, a.phpভিতরে অন্তর্ভুক্ত করা হয়েছিল myFunc, অভ্যন্তরের কোনও ভেরিয়েবলের a.phpকেবল স্থানীয় ফাংশন সুযোগ রয়েছে scope শুধু কারণ তারা প্রদর্শিত বিশ্বব্যাপী সুযোগ হতে হবে a.phpঅগত্যা মানে এই নয় তারা, এটা আসলে যা প্রেক্ষাপটে যে কোড অন্তর্ভুক্ত করা হয় / মৃত্যুদন্ড কার্যকর উপর নির্ভর করে।

ফাংশন এবং ক্লাসের ভিতরে ফাংশনগুলি সম্পর্কে কী?

প্রতিটি নতুন functionঘোষণা একটি নতুন সুযোগ প্রবর্তন করে, এটি এত সহজ।

(বেনামে) ফাংশন ভিতরে ফাংশন

function foo() {
    $foo = 'bar';

    $bar = function () {
        // no access to $foo
        $baz = 'baz';
    };

    // no access to $baz
}

ক্লাস

$foo = 'foo';

class Bar {

    public function baz() {
        // no access to $foo
        $baz = 'baz';
    }

}

// no access to $baz

সুযোগ কী ভাল?

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

পালন:

function foo() {
    echo $bar;
}

সুযোগ না থাকলে উপরের কাজটি কী করবে? কোথা $barথেকে আসে? এটা কি রাষ্ট্র আছে? এটি কি আরম্ভ করা হয়? আপনার কি প্রতিবার চেক করতে হবে? এটি রক্ষণাবেক্ষণযোগ্য নয়। যা আমাদের কাছে নিয়ে আসে ...

স্কোপ সীমানা অতিক্রম করে

সঠিক উপায়: বাইরে এবং বাইরে ভেরিয়েবল পাস করা passing

function foo($bar) {
    echo $bar;
    return 42;
}

ভেরিয়েবল $barস্পষ্টত এই সুযোগে ফাংশন আর্গুমেন্ট হিসাবে উপস্থিত হয়। কেবল এই ফাংশনটি দেখলে এটি স্পষ্ট যেখানে এটির সাথে যে মানগুলি কাজ করে সেখান থেকে উদ্ভূত। এটি তখন স্পষ্টভাবে একটি মান ফেরত দেয় । কলকারীটির কী কী ভেরিয়েবলগুলি কাজ করবে এবং তার ফেরতের মানগুলি কোথা থেকে আসবে তা জানার আত্মবিশ্বাস রয়েছে:

$baz   = 'baz';
$blarg = foo($baz);

অজ্ঞাতনামা ফাংশনে ভেরিয়েবলের পরিধি বাড়ানো

$foo = 'bar';

$baz = function () use ($foo) {
    echo $foo;
};

$baz();

বেনামে ফাংশন স্পষ্টভাবে $fooএর চারপাশের সুযোগ থেকে অন্তর্ভুক্ত । নোট করুন যে এটি বিশ্বব্যাপী সুযোগ হিসাবে একই নয় ।

ভুল পথ: global

আগেই বলা হয়েছে, বৈশ্বিক সুযোগটি কিছুটা বিশেষ এবং ফাংশনগুলি এ থেকে স্পষ্টতই চলকগুলি আমদানি করতে পারে:

$foo = 'bar';

function baz() {
    global $foo;
    echo $foo;
    $foo = 'baz';
}

এই ফাংশনটি বৈশ্বিক চলকটি ব্যবহার করে এবং সংশোধন করে $fooএটা করো না! (যদি না আপনি সত্যিই সত্যই জানেন যে আপনি কী করছেন, এবং তারপরেও: করবেন না!)

এই ফাংশনটির সমস্ত কলকারী দেখেন এটি হ'ল:

baz(); // outputs "bar"
unset($foo);
baz(); // no output, WTF?!
baz(); // outputs "baz", WTF?!?!!

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

আপনার যতটা সম্ভব বৈশ্বিক সুযোগ ব্যবহার করা এড়ানো উচিত; অবশ্যই আপনার বৈশ্বিক সুযোগগুলি থেকে স্থানীয় স্কোপে "টানা" ভেরিয়েবল হওয়া উচিত নয়।


আপনি কেবল এর জন্য ভুলglobal পথটি বলেছেন , তাই দয়া করে আমাদের কখন ব্যবহার করবেন global? এবং দয়া করে ব্যাখ্যা করুন (কিছুটা) কী static..?

@ স্ট্যাক এর জন্য কোনও "সঠিক" উপায় নেই global। এটা সবসময় ভুল। ফাংশন পরামিতিগুলি পাস করা সঠিক। staticম্যানুয়ালটিতে ভালভাবে ব্যাখ্যা করা হয়েছে এবং এর সুযোগের খুব বেশি কিছু নেই। সংক্ষেপে এটি একটি "স্কোপড গ্লোবাল ভেরিয়েবল" হিসাবে ভাবা যেতে পারে। আমি এখানে ব্যবহারের জন্য খানিকটা প্রসারিত করছি কুনস্টস্টিউব . net / স্ট্যাটিক atic
ছদ্মবেশ

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

@ আর্থার সেখানে আনপ্যাক করার মতো অনেক কিছুই আছে ... ಠ_ಠ এটি এমন কোনও পন্থা নয় যা আমি সমর্থন করি।
প্রতারণা করুন

একটি আর্গুমেন্ট এখানে ঘটছে আজকের পুঁচকে বিট @deceze stackoverflow.com/q/51409392 - যেখানে ওপি উল্লেখ করেছেন যে ডুপ্লিকেট (এখানে) সম্পর্কে উল্লেখ না include_onceএবং সম্ভবত require_onceএছাড়াও কোথাও যোগ করা উচিত; কথা মাত্র. ওপি তাদের প্রশ্নটিও আবার খুলতে ভোট দিয়েছে। তাদের পোস্টটি কি একটি বিশেষ কেস হবে এবং এটি সম্পর্কে কী করা উচিত?
ফান্ক ফালিটি নাইনার

10

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

এটি 'স্ট্যাটিক ভেরিয়েবল' কী?

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

function countSheep($num) {
 static $counter = 0;
 $counter += $num;
 echo "$counter sheep jumped over fence";
}

countSheep(1);
countSheep(2);
countSheep(3);

ফলাফল:

1 sheep jumped over fence
3 sheep jumped over fence
6 sheep jumped over fence

আমরা যদি সংজ্ঞায়িত $counterনা করে থাকি staticতবে প্রতিটি সময় প্রতিধ্বনিত মানটি $numফাংশনে প্যারামিটারের মতো হয়। ব্যবহারের staticফলে অতিরিক্ত কাজ ছাড়াই এই সাধারণ কাউন্টারটি তৈরি করতে দেয়।

স্ট্যাটিক ভেরিয়েবল ব্যবহার-ক্ষেত্রে

  1. কার্যকারী কলগুলির মধ্যে মান সংরক্ষণ করতে।
  2. যখন প্যারাম হিসাবে তাদের পাস করার কোনও উপায় (বা কোনও উদ্দেশ্য) নেই তখন পুনরাবৃত্ত কলগুলির মধ্যে মান সংরক্ষণ করা।
  3. ক্যাশে মান যা সাধারণত একবার পুনরুদ্ধার করা ভাল। উদাহরণস্বরূপ, সার্ভারে অপরিবর্তনীয় ফাইল পড়ার ফলাফল।

ঠাট

স্ট্যাটিক ভেরিয়েবল কেবল স্থানীয় ফাংশন স্কোপে বিদ্যমান। এটি যে সংজ্ঞায়িত করা হয়েছে তার বাইরে এটি অ্যাক্সেস করা যাবে না So সুতরাং আপনি নিশ্চিত হতে পারেন যে এটির ফাংশনের পরবর্তী কল না হওয়া পর্যন্ত এটির মান অপরিবর্তিত থাকবে।

স্ট্যাটিক ভেরিয়েবল কেবল একটি স্কেলার হিসাবে বা স্কেলার এক্সপ্রেশন হিসাবে সংজ্ঞায়িত হতে পারে (পিএইচপি 5.6 থেকে)। এটিতে অন্যান্য মান নির্ধারণ অনিবার্যভাবে এই নিবন্ধটি লেখা হওয়ার মুহুর্তে একটি ব্যর্থতার দিকে পরিচালিত করে। তবুও আপনি নিজের কোডের পরবর্তী লাইনে এটি করতে সক্ষম হচ্ছেন:

function countSheep($num) {
  static $counter = 0;
  $counter += sqrt($num);//imagine we need to take root of our sheep each time
  echo "$counter sheep jumped over fence";
}

ফলাফল:

2 sheep jumped over fence
5 sheep jumped over fence
9 sheep jumped over fence

স্ট্যাটিক ফাংশন একই শ্রেণীর অবজেক্টের পদ্ধতির মধ্যে 'ভাগ' করা হয়। নিম্নলিখিত উদাহরণটি দেখে এটি বোঝা সহজ:

class SomeClass {
  public function foo() {
    static $x = 0;
    echo ++$x;
  }
}

$object1 = new SomeClass;
$object2 = new SomeClass;

$object1->foo(); // 1
$object2->foo(); // 2 oops, $object2 uses the same static $x as $object1
$object1->foo(); // 3 now $object1 increments $x
$object2->foo(); // 4 and now his twin brother

এটি কেবল একই শ্রেণীর অবজেক্টের সাথে কাজ করে। যদি বস্তুগুলি বিভিন্ন শ্রেণি থেকে থাকে (এমনকি একে অপরকে প্রসারিত করে) স্ট্যাটিক ওয়ারগুলির আচরণ প্রত্যাশার মতো হবে।

স্থায়ী পরিবর্তনশীল কোনও ফাংশনে কল করার মধ্যে মানগুলি রাখার একমাত্র উপায়?

ফাংশন কলগুলির মধ্যে মানগুলি রাখার আরেকটি উপায় হ'ল ক্লোজার ব্যবহার। ক্লোজারগুলি পিএইচপি 5.3 এ চালু হয়েছিল। দুটি কথায় তারা আপনাকে ফাংশন স্কোপের মধ্যে কিছু ভেরিয়েবলের অ্যাক্সেসকে অন্য বেনামী ফাংশনে সীমাবদ্ধ করতে দেয় যা তাদের অ্যাক্সেসের একমাত্র উপায় হবে। ক্লোজার ভেরিয়েবলগুলিতে থাকার কারণে কাঠামোগত প্রোগ্রামিংয়ে 'ক্লাস কনস্ট্যান্টস' (যদি তারা মান দ্বারা বন্ধ করে দেওয়া হয়) বা 'ব্যক্তিগত সম্পত্তি' (রেফারেন্স দিয়ে পাস করা হয়) মতো ওওপি ধারণাগুলি অনুকরণ করতে পারে (কমবেশি সফলভাবে) OP

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


2

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

কিন্তু এক বিষয় যে মিস হয়েছিল ছিল superglobals সহ সাধারণভাবে ব্যবহৃত $_POST, $_GET, $_SESSION, ইত্যাদি এই ভেরিয়েবল অ্যারে একটি ছাড়া কোনো সুযোগ সবসময় পাওয়া যায়, হয় globalঘোষণা।

উদাহরণস্বরূপ, এই ফাংশনটি পিএইচপি স্ক্রিপ্টটি ব্যবহারকারী ব্যবহারকারীর নাম মুদ্রণ করবে। ভেরিয়েবলটি কোনও সমস্যা ছাড়াই ফাংশনে উপলব্ধ।

<?php
function test() {
    echo $_ENV["user"];
}

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

এই ভেরিয়েবলগুলি উপস্থিত থাকার গ্যারান্টিযুক্ত নয়; প্রশাসক ব্যবহার করে তাদের কিছু বা সমস্ত অক্ষম করতে পারেনvariables_order নির্দেশ মধ্যে php.ini, কিন্তু এই নয় সাধারণ আচরণ।


বর্তমান সুপারগ্লোবালগুলির একটি তালিকা:

  • $GLOBALS - বর্তমান স্ক্রিপ্টে সমস্ত গ্লোবাল ভেরিয়েবল
  • $_SERVER - সার্ভার এবং কার্যকর করার পরিবেশ সম্পর্কে তথ্য
  • $_GET - অনুরোধের জন্য ব্যবহৃত HTTP পদ্ধতি নির্বিশেষে URL এর ক্যোয়ারী স্ট্রিংয়ে মানগুলি উত্তীর্ণ হয়েছে
  • $_POST- একটি HTTP পোষ্ট অনুরোধে application/x-www-form-urlencodedবা এর সাথে পাস করা মানmultipart/form-data মাইম টাইপের
  • $_FILES - ফাইলগুলির সাথে একটি এইচটিটিপি পোস্ট অনুরোধে পাস করা হয়েছে multipart/form-data মাইম টাইপ
  • $_COOKIE - কুকিজ বর্তমান অনুরোধের সাথে পাস করেছে
  • $_SESSION - সেশন ভেরিয়েবলগুলি পিএইচপি দ্বারা অভ্যন্তরীণভাবে সঞ্চিত
  • $_REQUEST- সাধারণত $_GETএবং $_POSTকখনও কখনও একটি সমন্বয় $_COOKIES। বিষয়বস্তু দ্বারা নির্ধারিত হয় request_orderডিরেক্টিভের মধ্যে php.ini
  • $_ENV - বর্তমান স্ক্রিপ্টের পরিবেশ পরিবর্তনশীল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.