এক ক্যাচ ব্লকে একাধিক ব্যতিক্রমের ধরণ


243

নিম্নলিখিত ক্রিয়াকলাপটি পেতে, একটি ব্লকে ধরা AErrorও ধরার জন্য আমি একটি ক্লিনার উপায় চাই BError:

try
{
    /* something */
}
catch( AError, BError $e )
{
    handler1( $e )
}
catch( Exception $e )
{
    handler2( $e )
}

এই কাজ করতে কোন উপায় আছে কি? না কি আমাকে আলাদা করে ধরতে হবে?

AErrorএবং Berrorএকটি ভাগ করা বেস ক্লাস আছে, তবে তারা এটি অন্যান্য ধরণের সাথেও ভাগ করে নেয় যা আমি handler2পড়তে চাই, তাই আমি কেবল বেস ক্লাসটি ধরতে পারি না।


7
এটি কেবলমাত্র পার্শ্ব নোট হিসাবে যুক্ত করতে: একাধিক ব্যতিক্রম ধরার জন্য একটি আরএফসি দায়ের করা হয়েছে। আসুন দেখে নেওয়া যাক এই বৈশিষ্ট্যটি পিএইচপি ভাষায় প্রবেশ করেছে কিনা
લ્ટ

10
Feature এই বৈশিষ্ট্যটি পিএইচপি 7.1
সাবিন

উত্তর:


351

হালনাগাদ:

পিএইচপি 7.1 হিসাবে, এটি উপলব্ধ।

বাক্য গঠনটি হ'ল:

try
{
    // Some code...
}
catch(AError | BError $e)
{
    // Handle exceptions
}
catch(Exception $e)
{
    // Handle the general case
}

দস্তাবেজ: https://www.php.net/manual/en/language.exception.php#example-287

আরএফসি: https://wiki.php.net/rfc/m Multiple- catch

প্রতিশ্রুতিবদ্ধ: https://github.com/php/php-src/commit/0aed2cc2a440e7be17552cc669d71fdd24d1204a


পিএইচপি 7.1 এর আগে:

এই অন্যান্য উত্তরগুলি যা বলে তা সত্ত্বেও, আপনি একই ব্লকে ধরতে পারেন AErrorএবং BErrorআপনি ব্যতিক্রমগুলি সংজ্ঞায়িত করতে পারলে এটি কিছুটা সহজ)। এমনকি আপনি "এর মধ্য দিয়ে যেতে" চান এমন ব্যতিক্রমগুলি দেওয়া সত্ত্বেও, আপনার প্রয়োজনীয়তার সাথে মিলে যাওয়ার জন্য আপনার একটি স্তরক্রম নির্ধারণ করতে সক্ষম হওয়া উচিত।

abstract class MyExceptions extends Exception {}

abstract class LetterError extends MyExceptions {}

class AError extends LetterError {}

class BError extends LetterError {}

তারপর:

catch(LetterError $e){
    //voodoo
}

আপনি এখানে এবং এখানে দেখতে পাচ্ছেন , এমনকি SPLডিফল্ট ব্যতিক্রমগুলিরও একটি স্তরক্রম রয়েছে যা আপনি উত্সাহ অর্জন করতে পারেন। অতিরিক্ত হিসাবে, পিএইচপি ম্যানুয়াল অনুসারে :

যখন কোনও ব্যতিক্রম ছুঁড়ে ফেলা হয়, তখন বিবৃতি অনুসরণকারী কোডটি কার্যকর করা হবে না এবং পিএইচপি প্রথম ম্যাচিং ক্যাচ ব্লকটি সন্ধান করার চেষ্টা করবে।

এর অর্থ আপনারও থাকতে পারে

class CError extends LetterError {}

যা আপনাকে AErrorবা অন্যের চেয়ে আলাদাভাবে পরিচালনা করতে হবে BError, সুতরাং আপনার ক্যাচ স্টেটমেন্টটি দেখতে এইরকম হবে:

catch(CError $e){
    //voodoo
}
catch(LetterError $e){
    //voodoo
}

আপনার যদি এমন ঘটনা ঘটে থাকে যেখানে বিশ বা ততোধিক ব্যতিক্রমগুলি বৈধভাবে একই সুপারক্লাসের অন্তর্গত ছিল এবং আপনাকে তাদের পাঁচটি (বা যে কোনও বৃহত্তর-ইশ গ্রুপ) একটি উপায়ে পরিচালনা করতে হবে এবং অন্যটি, অন্যথায় আপনি এটি করতে পারেন।

interface Group1 {}

class AError extends LetterError implements Group1 {}

class BError extends LetterError implements Group1 {}

এবং তারপর:

catch (Group1 $e) {}

ব্যতিক্রমগুলির ক্ষেত্রে OOP ব্যবহার করা খুব শক্তিশালী। হ্যাকের মতো get_classবা ব্যবহৃত জিনিসগুলি ব্যবহার করা instanceofএবং সম্ভব হলে এড়ানো উচিত।

আমি আরও একটি সমাধান যুক্ত করতে চাই তার নিজস্ব পদ্ধতিতে ব্যতিক্রম হ্যান্ডলিং কার্যকারিতা স্থাপন করা।

আপনি থাকতে পারে

function handleExceptionMethod1(Exception $e)
{
    //voodoo
}

function handleExceptionMethod2(Exception $e)
{
    //voodoo
}

ধরে নেওয়া যাক একেবারে কোন ভাবে আপনি ব্যতিক্রম বর্গ শ্রেণীবিন্যাসের বা ইন্টারফেসগুলি নিয়ন্ত্রণ করতে পারেন (এবং সেখানে প্রায় সবসময় হয় হবে একটি উপায় হতে), আপনি নিম্নলিখিতগুলি করতে পারেন:

try
{
    stuff()
}
catch(ExceptionA $e)
{
    $this->handleExceptionMethod1($e);
}
catch(ExceptionB $e)
{
    $this->handleExceptionMethod1($e);
}
catch(ExceptionC $e)
{
    $this->handleExceptionMethod1($e);
}
catch(Exception $e)
{
    $this->handleExceptionMethod2($e);
}

এইভাবে, আপনার ব্যতিক্রম হ্যান্ডলিং পদ্ধতিটি পরিবর্তন করতে হবে এবং আপনি ওওপির সাধারণ কনস্ট্রাক্টের মধ্যে কাজ করছেন, তবে আপনার এখনও একটিমাত্র একক কোড অবস্থান রয়েছে you


4
সঠিক উত্তর হিসাবে এটির জন্য এখানে আরও একটি ভোট। দুর্ভাগ্যক্রমে স্টাফ গ্রহণযোগ্য উত্তরে যা বলা হয় এবং এটি সঠিক উত্তর হিসাবে গৃহীত হয় তা সত্যই পিএইচপিটিকে উন্মাদ করে তোলে it
বর্ফস্ট

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

@ ওয়াফলস স্টিলার 654 আপনি ফাইলগুলি সরাসরি সম্পাদনা করতে না পারলেও আপনি ফাইলগুলি সাবক্লাস করতে পারেন এবং সেগুলি আপনার গ্রুপ বাস্তবায়িত করতে পারেন। এটি ধরে নেবে যে আপনি ব্যতিক্রমগুলি ছুঁড়ে ফেলতে পারেন, তবে আপনি কেবল সর্বাধিক বেস-স্তরের প্রক্রিয়াটি গুটিয়ে রাখতে পারেন যেখানে ব্যতিক্রমটি ছুঁড়ে ফেলা হবে এবং তারপরে এটি ধরুন এবং আপনার মোড়ানো ব্যতিক্রমটি ছুঁড়ে ফেলবেন।
মিররফেট

3
এটি গৃহীত উত্তর নয়, কারণ আপনি যখন তৃতীয় পক্ষের লাইব্রেরি ব্যবহার করেন তখন আপনি তা করতে পারবেন না।
ডেনিস ভি

@ ডেনিসভি আপনার উপরে আমার মন্তব্য দেখুন। এটি এন্টারপ্রাইজ সফ্টওয়্যারটিতে সর্বদা করা হয়। এনক্যাপসুলেশন দুর্দান্ত।
মিররফেটে

229

পিএইচপি> = 7.1 এ এটি সম্ভব। দেখুন উত্তর নিচে।


আপনি যদি ব্যতিক্রমগুলি সংশোধন করতে পারেন তবে এই উত্তরটি ব্যবহার করুন

যদি আপনি না করতে পারেন তবে আপনি সমস্ত কিছু ধরে দেওয়ার চেষ্টা করতে পারেন Exceptionএবং তারপরে কোন ব্যতিক্রমটি ছুঁড়েছিল তা পরীক্ষা করতে পারেন instanceof

try
{
    /* something */
}
catch( Exception $e )
{
    if ($e instanceof AError OR $e instanceof BError) {
       // It's either an A or B exception.
    } else {
        // Keep throwing it.
        throw $e;
    }
}

তবে পূর্বোক্ত উত্তরে বর্ণিত হিসাবে একাধিক ক্যাচ ব্লক ব্যবহার করা আরও ভাল ।

try
{
    /* something */
}
catch( AError $e )
{
   handler1( $e );
}
catch ( BError $b )
{
   handler2( $e );
}

6
এটাই আমার ভয় ছিল। তাদের একত্রে ধরা এবং প্রকারটি পরীক্ষা করা ভাল হবে যদি সেখানে অনেকগুলি ত্রুটি ধরণের থাকে যা একসাথে হ্যান্ডেল করা প্রয়োজন তবে কেবলমাত্র 2 এর জন্য যেমন আমার ক্ষেত্রে, তাদের পৃথকভাবে ধরা সম্ভবত ক্লিনার। ধন্যবাদ!
ডমিনিক গুর্টো

3
@ ডমিনিকগুর্তো: হ্যাঁ, আমিও তার সাথে যাব :) আমি একটি finallyবিবৃতিতে পিএইচপি-র মনোভাব নিয়ে আরও উদ্বিগ্ন হব । ;)
অ্যালেক্স

7
তবে ভুলে যাবেন না যে এটি সমস্ত ব্যাতিক্রমকে ধরেছে, তাই এর সাথে এমন কিছু হওয়া উচিত যা ... } else { throw($e); }এটি দুটির সাথে মেলে না। ভুল সিনট্যাক্সের জন্য দুঃখিত, কিছুক্ষণ পিএইচপি দেখতে পেল না।
ডালিবোর ফিলাস

11
আপনি যদি এখানে প্রথম অনুচ্ছেদটি পড়েন: php.net/manual/en/language.exferences.php আপনি দেখতে পাবেন একাধিক ক্যাচ ব্লকগুলি সম্ভব এবং পুরোপুরি বৈধ সমাধান। যদিও ওপিতে একটি ধরা বিবৃতিতে ভুল করে দুটি ব্যতিক্রম ক্লাস করা হয়েছিল। আমি মনে করি একাধিক ক্যাচ ব্লক সহ আপনার উত্তরটি অন্য একটি উদাহরণের সাথে আপডেট করা ভাল।
হারালান দোব্রেভ

4
এমন একটি সমাধানের প্রস্তাব যা আপনার অন্যান্য ব্যতিক্রমগুলি খায়, একেবারেই গ্রহণ করা উচিত ছিল না ...
স্টিভনি

88

আসছে পিএইচপি 7.1 একাধিক প্রকারের ধরা দক্ষতা।

যাতে এটি:

<?php
try {
    /* ... */
} catch (FirstException $ex) {
    $this->manageException($ex);
} catch (SecondException $ex) {
    $this->manageException($ex);
}
?>

এবং

<?php
try {

} catch (FirstException | SecondException $ex) {
    $this->manageException($ex);
}
?>

কার্যত সমতুল্য।


45

পিএইচপি 7.1 হিসাবে,

catch( AError | BError $e )
{
    handler1( $e )
}

আকর্ষণীয়ভাবে, আপনি এটি করতে পারেন:

catch( AError | BError $e )
{
    handler1( $e )
} catch (CError $e){
    handler2($e);
} catch(Exception $e){
    handler3($e);
}

এবং পিএইচপি এর পূর্ববর্তী সংস্করণগুলিতে:

catch(Exception $ex){
    if($ex instanceof AError){
        //handle a AError
    } elseif($ex instanceof BError){
        //handle a BError
    } else {
       throw $ex;//an unknown exception occured, throw it further
    }
}

25

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

উদাহরণ ব্যতিক্রম

এই উদাহরণের উদ্দেশ্যগুলির জন্য সংজ্ঞায়িত কিছু ব্যতিক্রম এখানে রয়েছে:

class FooException extends Exception 
{
  public function __construct($message = null, $code = 0) 
  {
    // do something
  }
}

class BarException extends Exception 
{
  public function __construct($message = null, $code = 0) 
  {
    // do something
  }
}

class BazException extends Exception 
{
  public function __construct($message = null, $code = 0) 
  {
    // do something
  }
}

একাধিক ব্যতিক্রম পরিচালনা করছে

এটি খুব সহজ - প্রতিটি ব্যতিক্রম প্রকারের জন্য ছোঁড়া ব্লক থাকতে পারে:

try 
{
  // some code that might trigger a Foo/Bar/Baz/Exception
}

catch(FooException $e) 
{
  // we caught a foo exception
}

catch(BarException $e) 
{
  // we caught a bar exception
}

catch(BazException $e) 
{
  // we caught a baz exception
}

catch(Exception $e) 
{
  // we caught a normal exception
  // or an exception that wasn't handled by any of the above
}

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


3
এই পদ্ধতির সমস্যাটি তখনই আসে যখন আপনাকে দুটি বা আরও বেশি ব্যতিক্রমের জন্য একই কোডটি কার্যকর করতে হবে।
পার্জিফল 18

এটি বৈদ্যুতিন সরঞ্জামবক্স থেকে পুনরুদ্ধার করা হয়েছিল । ক্রেডিট দেওয়ার জন্য পোস্ট সম্পাদনা করা হচ্ছে।
কায়লা

পিএইচপি 7.x সহ আপনার catch (Throwable $e)সমস্ত ব্যতিক্রম ধরা দরকার catch আরও দেখুন: php.net/manual/en/class.throwable.php
মিক্কো রেন্টালাইনেন

21

গৃহীত উত্তরের একটি এক্সটেনশন হিসাবে, আপনি কিছুটা মূল উদাহরণের মতো এমন প্যাটার্নের ফলে ব্যতিক্রমের ধরণটি স্যুইচ করতে পারেন:

try {

    // Try something

} catch (Exception $e) {

    switch (get_class($e)) {

        case 'AError':
        case 'BError':
            // Handle A or B
            break;

        case 'CError':
            // Handle C
            break;

        case default:
            // Rethrow the Exception
            throw $e;

    }

}

6
এই সমাধানের পরিবর্তে একাধিক ক্যাচ ব্যবহার করুন।
আলেজান্দ্রো মোরেনো

5

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

$ABError = null;
try {
    // something
} catch (AError $ABError) {  // let the exception fall through
} catch (BError $ABError) {  // let the exception fall through
} catch (Exception $e) {
    handler2($e);
}
if ($ABError) {
    handler1($ABError);
}

ক্যাপ ব্লক বাস্তবায়নের মধ্যে যদি অনেক বেশি সদৃশ হয় তবে এই কিছুটা বিশ্রী চেহারা দেখতে সম্ভবত এটির পক্ষে উপযুক্ত।


3

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

<?php

class A_Error extends Exception {}
class B_Error extends Exception {}
class C_Error extends Exception {}

try {
    throw new A_Error();
} 
catch (A_Error $e) { goto abc; }
catch (B_Error $e) { goto abc; }
catch (C_Error $e) {
abc:
    var_dump(get_class($e));
    echo "Gotta Catch 'Em All\n";
}

3v4l.org


1

একটি দুর্দান্ত উপায় ব্যবহার করা হয় set_exception_handler

সতর্কতা !!! পিএইচপি 7 দিয়ে, আপনি মারাত্মক ত্রুটির জন্য মৃত্যুর সাদা পর্দা পেতে পারেন। উদাহরণস্বরূপ, আপনি যদি অ-অবজেক্টে কোনও পদ্ধতিতে কল করেন তবে আপনি সাধারণত পাবেন Fatal error: Call to a member function your_method() on nullএবং ত্রুটি প্রতিবেদন চলমান থাকলে আপনি এটি দেখার আশা করবেন।

উপরের ত্রুটিটি ধরা পড়বে না catch(Exception $e)। উপরের ত্রুটিটি কোনও কাস্টম ত্রুটি হ্যান্ডলার দ্বারা সেট করা ট্রিগার করবে না set_error_handler

আপনার অবশ্যই catch(Error $e){ }পিএইচপি 7 তে ত্রুটিগুলি ধরতে ব্যবহার করতে হবে । । এটি সাহায্য করতে পারে:

class ErrorHandler{
    public static function excep_handler($e)
    {
        print_r($e);
    }
}
set_exception_handler(array('ErrorHandler','excep_handler'));

1
... বা আপনি কেবল এটি লিখতে catch (Throwable $e) { ... }এবং এটি দিয়ে সম্পন্ন করতে পারে। আরও দেখুন: php.net/manual/en/class.throwable.php
মিক্কো রেন্টালাইনেন

0

এখানে তালিকাভুক্ত নয় এমন আরেকটি বিকল্প হ'ল codeব্যতিক্রমের বৈশিষ্ট্যটি ব্যবহার করা , যাতে আপনি এরকম কিছু করতে পারেন:

try {

    if (1 === $foo) {

         throw new Exception(sprintf('Invalid foo: %s', serialize($foo)), 1);
    }

    if (2 === $bar) {
        throw new Exception(sprintf('Invalid bar: %s', serialize($foo)), 2);
    }
} catch (Exception $e) {

    switch ($e->getCode()) {

        case 1:
            // Special handling for case 1
            break;

        case 2:
            // Special handling for case 2
            break;

        default:

            // Special handling for all other cases
    }
}

আমি ডাউনভিট করি নি, তবে ওওপি পিউরিস্টরা রাগ করেছেন যে আপনি নতুন ব্যতিক্রম ক্লাস ব্যবহার করে তৈরি করেন নি extends \Exception?
keyboardSmasher

বুঝেছি. এটাই আমার সমাধানের পুরো বিষয়টি, নির্দিষ্ট ব্যতিক্রম ছড়িয়ে দেওয়ার জন্য আপনাকে কেবল একটি নেমস্পেস স্থাপন করতে স্বেচ্ছাসেবী ক্লাস তৈরি করার দরকার নেই। আমি নিশ্চিত সে কারণেই তারা একটি কোড নির্দিষ্ট করার ক্ষমতা যুক্ত করেছিল।
মাইক পার্সেল

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

0

হুম, পিএইচপি সংস্করণে 7.1 এর চেয়ে কম সমাধানের জন্য অনেকগুলি সমাধান লেখা রয়েছে।

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

<?php
$ex = NULL
try {
    /* ... */
} catch (FirstException $ex) {
    // just do nothing here
} catch (SecondException $ex) {
    // just do nothing here
}
if ($ex !== NULL) {
    // handle those exceptions here!
}
?>
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.