Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP-在类内正确使用异常进行错误处理吗?_Php_Class_Exception_Error Handling_Design Principles - Fatal编程技术网

PHP-在类内正确使用异常进行错误处理吗?

PHP-在类内正确使用异常进行错误处理吗?,php,class,exception,error-handling,design-principles,Php,Class,Exception,Error Handling,Design Principles,我在这个话题上搜索了很多,得到了很多好的(但不同的)结果。一些结果并不十分相关,最终似乎是一个偏好问题,但我感兴趣的是我是否遵循了良好的设计原则 如果这是一个太模糊的问题,请随意删除,但您能推荐我将其张贴在何处吗? 而且,这只是一个例子。这里有很多我通常会做的不同的事情,但为了简单起见,我是这样做的 代码很长,但您应该能够将其直接复制粘贴到一个新的PHP文件中,并在您的环境中运行;无需设置。 具体问题 这是使用异常并在调用方处理异常的正确方法吗 我甚至应该为此使用异常吗 我的骨架自定义异常是否

我在这个话题上搜索了很多,得到了很多好的(但不同的)结果。一些结果并不十分相关,最终似乎是一个偏好问题,但我感兴趣的是我是否遵循了良好的设计原则

如果这是一个太模糊的问题,请随意删除,但您能推荐我将其张贴在何处吗?

而且,这只是一个例子。这里有很多我通常会做的不同的事情,但为了简单起见,我是这样做的

代码很长,但您应该能够将其直接复制粘贴到一个新的PHP文件中,并在您的环境中运行;无需设置。

具体问题
  • 这是使用异常并在调用方处理异常的正确方法吗
  • 我甚至应该为此使用异常吗
  • 我的骨架自定义异常是否正确
代码 您可以在单独的窗口中查看副本。我会把它贴在这里。保存它并在您的环境中运行,它应按原样工作,无需任何修改:

注意:前面有很长的代码

*
{
字体系列:“Segoe UI”、“投石机MS”、塔荷马、Arial、Helvetica、无衬线;
}
身体
{
边缘:4em-6em;
线高:1.6em;
字体大小:较小;
}
标题
{
边框底部:2倍实心#EFEF;
边缘底部:3em;
垫底:1米;
}
h1、h2、h3、h4、h5、h6
{
字体大小:正常;
字母间距:1px;
颜色:皇家蓝;
}
h5,h6
{
字体大小:粗体;
}
收割台h1接头,收割台h1接头
{
字体大小:小;
颜色:#FF4400;
字母间距:2px;
}
部分
{
边框底部:1px点#ccc;
垫底:2米;
边缘底部:3em;
}
桌子
{
边框:1px实心#eee;
填充:1em;
右边框宽度:2px;
边框底宽:2px;
}
th
{
文本对齐:左对齐;
字体变体:小大写字母;
边框底部:1px点#ccc;
垫底:75em;
边缘底部:.75em;
字母间距:1px;
颜色:#FF4400;
}
td:悬停
{
背景色:天蓝色;
}
运输署
{
保证金:0;
显示:表格单元格;
填充:.5em;
}
之前
{
字体系列:“Droid Sans Mono”,Console,“Courier New”,Courier,单间距;
边框:1px实心#e4;
填充:1em;
线高:1米;
}
.错误
{
颜色:红色;
边框:1px点#ccc;
}
.成功
{
颜色:森林绿;
边框:1px点#e0;
}
.错误,.成功
{
填充:.75em;
背景色:#FFFFCC;
边框:1px实心#e4;
}
示例登录系统-测试异常
演示异常的简单登录系统…
不需要数据库
为了避免设置环境的时间,此测试仅使用存储帐户数组的类。
显然,这不是持久性的(此时),它实际上不会在任何地方保存任何东西,除了
脚本生存期内的数组。在下一次请求时,以前的帐户将被删除

正在创建帐户。。。 已成功创建帐户它们应该列在 下表

创建帐户时出错

帐户清单 正在尝试创建一个已存在的。。。

帐户创建成功

再次显示帐户 有效登录测试 登录用户“Daniel Elkins”&hellip

身份验证成功

无法登录;无效的用户名或密码

无效登录测试 登录用户“不存在”&hellip

身份验证成功

无法登录;无效的用户名或密码

调试信息
这是使用异常并在服务器上处理它们的正确方法吗 呼叫方

对我来说似乎是个合理的方法。您正在抛出特定于类的异常,因此很容易捕获或传播它们,并且只捕获特定的异常,而不必捕获所有异常并进行过滤

我应该吗
<?php

    error_reporting ( E_ALL | E_STRICT );




    class MemberLoginException extends Exception
    {

        public function __construct ( $message = null, $code = 0, Exception $previous = null )
        {
            parent::__construct ( $message, $code, $previous );
        }

    }




    class AccountsInsertException extends Exception
    {

        public function __construct ( $message = null, $code = 0, Exception $previous = null )
        {
            parent::__construct ( $message, $code, $previous );
        }

    }




    class AccountsManager
    {

        protected $_accounts = array ();
        protected $_lcUsernames = array ();     # all usernames in lowercase for checking if username is taken



        public function __construct ( array $accounts = null )
        {
            $this->setAllAccounts ( $accounts );
        }



        public function __destruct ()
        {
            unset ( $this->_accounts, $this->_lcUsernames );
        }



        public function __toString ()
        {
            $return = '';

            if ( count ( $this->_accounts ) > 0 ) :

                $return = '<table>';
                $return .= '<tr><th>Username</th><th>Password</th></tr>';

                foreach ( $this->_accounts as $account ) :

                    $return .= 
                    '<tr>
                        <td>'. htmlentities ( $account['username'], ENT_QUOTES, 'UTF-8' ) . '</td>
                        <td>'. htmlentities ( $account['password'], ENT_QUOTES, 'UTF-8' ) . '</td>
                    </tr>';

                endforeach;

                $return .= '</table>';

                return $return;
            endif;
        }



        public function Clear ()
        {
            $this->_accounts = array ();
            $this->_lcUsernames = array ();
        }



        public function Authenticate ( Member $member )
        {
            $username = strtolower ( $member->getUsername () );

            if ( count ( $this->_accounts ) ) :

                foreach ( $this->_accounts as $account ) :

                    if ( strtolower ( $account['username'] ) == $username )
                        return ( bool ) ( $account['password'] == $member->getPassword () );

                endforeach;

            else :
                return false;
            endif;
        }



        public function getAllAccounts ()
        {
            return $this->_accounts;
        }



        public function setAllAccounts ( array $newValue = null )
        {
            if ( is_null ( $newValue ) )
                $this->_accounts = array ();
            else
                $this->_accounts = $newValue;
                $this->_lcUsernames = array ();

                foreach ( $this->_accounts as $account )
                    $this->_lcUsernames[] = strtolower ( $account['username'] );

            return $this;
        }



        public function hasAccount ( $username )
        {
            return in_array ( strtolower ( $username ), $this->_lcUsernames, false );
        }



        public function AddAccount ( $username, $password )
        {

            /*
            Faster to be redundant by storing a lowercase copy of the username for comparison

            if ( array_key_exists ( strtolower ( $username ), array_change_key_case ( $this->_accounts ) ) )
                throw new AccountsInsertException ( 'Unable to create account; account already exists.' );
            */

            if ( $this->hasAccount ( $username ) )
                throw new AccountsInsertException ( 'Unable to create account; account already exists.' );

            $this->_accounts[] = array (
                'username' => $username,
                'password' => $password,
            );

            $this->_lcUsernames[] = strtolower ( $username );
            return $this;
        }



        public function RemoveAccount ( $username )
        {
            if ( $this->hasAccount ( $username ) ) :
                unset ( $this->_accounts[$username] );
                unset ( $this->_lcUsernames [ strtolower ( $username ) ] );
            endif;

            return $this;
        }



        public function __Debug ()
        {
            echo "\r<pre>\r";
            print_r ( $this->_accounts );
            echo "\r</pre>\r\r\r<pre>\r";
            print_r ( $this->_lcUsernames );
            echo "\r</pre>\r\r";
        }

    }




    class Member
    {

        protected $_username = '';
        protected $_password = '';



        public function __construct ( $username, $password )
        {
            $this->setUsername ( $username );
            $this->setPassword ( $password );
        }



        public function getUsername ()
        {
            return $this->_username;
        }



        public function setUsername ( $newValue )
        {
            $this->_username = ( string ) $newValue;
            return $this;
        }



        public function getPassword ()
        {
            return $this->_password;
        }



        public function setPassword ( $newValue )
        {
            $this->_password = ( string ) $newValue;
            return $this;
        }

    }


    # create a new accounts manager which stores all accounts and handles authentication
    # the Member class would be responsible for setting session variables, etc. Manager just checks user/pass.
    $manager = new AccountsManager ();

?><!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />

        <style>

            *
            {
                font-family: "Segoe UI", "Trebuchet MS", Tahoma, Arial, Helvetica, sans-serif;
            }

            body
            {
                margin: 4em 6em;
                line-height: 1.6em;
                font-size: smaller;
            }

            header
            {
                border-bottom: 2px solid #efefef;
                margin-bottom: 3em;
                padding-bottom: 1em;
            }

            h1, h2, h3, h4, h5, h6
            {
                font-weight: normal;
                letter-spacing: 1px;
                color: royalblue;
            }

            h5, h6
            {
                font-weight: bold;
            }

            header h1 sub, header h1 sup
            {
                font-size: small;
                color: #FF4400;
                letter-spacing: 2px;
            }

            section
            {
                border-bottom: 1px dotted #ccc;
                padding-bottom: 2em;
                margin-bottom: 3em;
            }

            table
            {
                border: 1px solid #eee;
                padding: 1em;
                border-right-width: 2px;
                border-bottom-width: 2px;
            }

            th
            {
                text-align: left;
                font-variant: small-caps;
                border-bottom: 1px dotted #ccc;
                padding-bottom: .75em;
                margin-bottom: .75em;
                letter-spacing: 1px;
                color: #FF4400;
            }

            td:hover
            {
                background-color: skyblue;
            }

            td
            {
                margin: 0;
                display: table-cell;
                padding: .5em;
            }

            pre
            {
                font-family: "Droid Sans Mono", Consolas, "Courier New", Courier, monospaced;
                border: 1px solid #E4E4E4;
                padding: 1em;
                line-height: 1em;
            }

            .error
            {
                color: red;
                border: 1px dotted #ccc;
            }

            .success
            {
                color: forestgreen;
                border: 1px dotted #e0e0e0;
            }

            .error, .success
            {
                padding: .75em;
                background-color: #FFFFCC;
                border: 1px solid #E4E4E4;
            }

        </style>

        <title>Sample Login System - Test Exceptions</title>
    </head>

    <body>

        <header>
            <h1>Simple Login System <sup>demonstrating exceptions&hellip;</sup></h1>
        </header>



        <section>
            <h2>No database required</h2>

            <p>To avoid time setting up your environment, this test simply uses a class that stores an array of accounts.
            Obviously, this isn't persistent (at this time) and it doesn't actually save anything anywhere except in the
            array during the script's lifetime. Upon the next request, the previous accounts will be erased.</p>
        </section>



        <section>
            <h2>Creating accounts...</h2>

            <?php

                $createList =
                    array (

                        array (
                            'username' => 'Daniel Elkins',
                            'password' => 'delkins[not-pass-for-anything]',
                        ),

                        array (
                            'username' => 'Jennifer Lynn',
                            'password' => 'lilJenn',
                        ),

                        array (
                            'username'=> 'Charlie Dog',
                            'password'=> 'grrrrr',
                        ),

                    );

                if ( $manager->setAllAccounts ( $createList ) instanceof AccountsManager ) : ?>

                    <p><strong>Accounts were created successfully!</strong> They should be listed in
                    a table below.</p>

                <?php

                else :

                ?>

                    <p class="error">There was an error creating your accounts...</p>

                <?php

                endif;

            ?>

        </section>


        <section>
            <h2>List of accounts</h2>

            <?php echo $manager; ?>

        </section>


        <section>
            <h2>Trying to create one that already exists...</h2>

            <?php

            try
            {
                $manager->AddAccount ( 'Daniel Elkins', 'delkins[not-pass-for-anything]'); ?>

                <p class="success">Account created successfully!</p>

                <?php

            }
            catch ( AccountsInsertException $exception )
            {
                ?>

                <p class="error"><?= $exception->getMessage (); ?></p>

                <?php

            }

            ?>

        </section>


        <section>
            <h2>Showing accounts again</h2>

            <?php echo $manager; ?>

        </section>


        <section>
            <h2>Valid login test</h2>

            <p>Logging in user `Daniel Elkins`&hellip;</p>

            <?php

            if ( $manager->Authenticate ( new Member ( 'Daniel Elkins', 'delkins[not-pass-for-anything]' ) ) ) : ?>

                <p class="success">Authentication successful!</p>

                <?php

            else :

            ?>

                <p class="error">Unable to login; invalid username or password!</p>

                <?php

            endif;

            ?>

        </section>


        <section>
            <h2><strong>Invalid</strong> login test</h2>

            <p>Logging in user `Doesnt_Exist`&hellip;</p>

            <?php

            if ( $manager->Authenticate ( new Member ( 'Doesnt_Exist', '1234' ) ) ) : ?>

                <p class="success">Authentication successful!</p>

                <?php

            else :

            ?>

                <p class="error">Unable to login; invalid username or password!</p>

                <?php

            endif;

            ?>

        </section>


        <section>
            <h2>Debug information</h2>

            <?php $manager->__Debug (); ?>

        </section>

    </body>

</html>