This article shares with you how to find bad code in PHP example code and how to fix it. Interested friends can refer to it.
I have been doing PHP development for almost a year. During this year, I learned a lot of techniques in the production environment and learned a lot of things. During this period, I also read some excellent source codes and information about Code book, I have some thoughts on writing code, and I have seen a lot of good and bad code written by others. Let me talk about my own insights and improvements here.
This blog expresses my own feelings. When writing code, I set rules for myself, which can make the code clear and readable and avoid pitfalls. Although these simple rules may not look as exciting as design patterns, with regular attention they can make your code look cleaner.
1. Do not use undeclared variables outside the object
This problem may not be easy to understand when expressed. This problem is determined by the characteristics of the PHP language itself. Since PHP is a weakly typed dynamic scripting language, in many cases, this language is given very loose conditions for developers to write code. But often these conveniences can also turn into pitfalls, so you should pay special attention when using some convenient writing methods in dynamic languages.
Let’s declare a class first. Let’s call this class the user class. The background setting of this User class is that it comes with the framework and is not allowed to be modified. It is hidden deep in the framework and is not easy to find. In fact, For examples, please refer to the Request class of the laravel framework. The code is as follows:
class User { public $username; public $password; public $otherInfo = []; public function readUserInfo() { return [ 'username' => $this->username, 'password' => $this->password, ]; } public function addAtri($info) { array_push($this->otherInfo, $info); } }
Such code seems to be quite satisfactory, but next, we need to operate this class:
$user = new User(); $user->userRealName = "hello world";
Such code can be run completely in PHP and will not report an error, but such code will interfere with some subsequent things. We now assume that the above code is an interceptor in the PHP web project, or it can be called middleware. Then we will use the instance of this class in the controller and use the variable added in the middleware. , as follows:
class WebOperate { public function doOprate(User $user) { $user->userRealName = "hello world"; next($user); } }
The scenario set here is that WebOperate is a middleware, and all Controllers will reach the Controller after passing through this middleware. After that, in Process the corresponding Controller function. Next, the Controller will inject the middleware instance for the controller to use, but the middleware developer does not care much about its existence:
class IndexController { public function index(User $user) { return $user->userRealName; } }
And such code can run perfectly. Next, the developer wants to implement another User class and add some other functions to this User class. As mentioned before, this class is deep in the framework. And it is difficult to find, and modification is not allowed, because other functions use this class, so we can only inherit and add methods. According to development experience, developers will think that the userRealName variable exists in the User class, so this is the writing method:
The first is the Teacher class derived based on this User:
class Teacher extends User { public function sayHello() { return "hello world"; } }
In this way, our Teacher can say hello, but at this time, we still want to know the teacher’s real name in our Controller, what should we do? Based on experience, we can change the injected class to Teacher and return the real name:
class IndexController { public function index(Teacher $user) { return $user->userRealName; } }
Then the question arises. In fact, there is no such thing in the User class. class, so this variable has no value at all, but according to experience, the middleware has already been assigned a value once, so we should be able to use it directly, but there is no such value. We started looking at the source code and found that this does not exist in the inherited User class. Variable, then why can this variable be used before? Because in the middleware, the user's strength is paid.
So we cannot directly use undeclared variables in a class.
We should write like this:
class WebOperate { public function doOprate(User $user) { $user->addAtri([ 'userRealName' => 'hello world', ]); next($user); } }
Such middleware can also use the same method when calling inherited classes. It is very simple. And it is very difficult to produce bad taste.
2. Class or array
In fact, this problem also derives another problem, which is the problem of function return value.
First of all, I make it clear that I personally feel that it is not good for a function to return multiple types of values. Although it is very common in dynamic languages, many native methods of PHP also have this, but in Using this method in production will cause uncertainty in function returns. We need to make a lot of judgments to prove our conclusions. However, if there is only one return value type, we can directly judge the return value.
is like the following code:
public function addNewUser() { $res = $this->addData(); if ($res) { return true; } else { return [ 'error' => 1, 'errormsg' => "没有添加成功" ]; } }
Such code will often be judged one more time by the caller, as follows:
public function index() { $res = $this->addNewUser(); if (is_array($res) && isset($res['error'])) { return isset($res['errormsg']) ? $res['errormsg'] : "未知错误"; } return "成功"; }
This kind of code will appear almost every time this function is called. Not only is the code unsightly, but it is also very bloated.
Such code needs to be improved. First, limit the return value of the function. For example, we only let this function return a bool type number:
public function addNewUser() { $res = $this->addData(); if ($res) { return true; } else { return false; } }
但是,显然,很多时候,我们要的不是简单的真价值,所以,我们会选择返回更多信息,这个时候,我们可以有三种处理方式。
1)返回int类型的数,然后通过这个int类型的数去判断处理结果,我们可以添加上映射关系:
class Operate{ public $operateRes = [ 0 => '成功', 1 => '添加失败', 2 => '未知错误', ]; public function addNewUser() { $res = $this->addData(); if ($res) { return 0; } else if ($res > 1) { return 1; } return 2; } }
这样方法的调用者就可以很简单的使用方法并给出提示了:
$opera = new Operate(); $res = $opera->addNewUser(); return $opera->operateRes[$res];
给出统一的返回值类型的时候就完全不需要判断返回值类型而且可以设置一个规范返回提示。
2)我们也可以使用数组
3)数组给人不缺定性,因为很多时候,数组里可以认为的少写一些元素,如果少写了,程序直接报错,很不好。
所以第三种方式就是建议将固定格式的返回,写成一个类,做返回的时候,使用这个类:
class Operate{ public function addNewUser() { $res = $this->addData(); $result = new Result(); if ($res) { $result->errno = 0; $result->errmsg = "成功"; } else if ($res > 1) { $result->errno = 1; $result->errmsg = "失败"; } $result->errno = 2; $result->errmsg = "未知错误"; return $result; } } class Result { public $errno; public $errmsg; }
这样的返回,保证了所有变量的存在,同样可以减少一次判断。
所以,综合以上,在我们返回结果的时候,尽量使用同种类型的变量,尽量减少使用数组返回。
The above is the detailed content of PHP skills: how to cleverly avoid some bad codes in PHP programs. For more information, please follow other related articles on the PHP Chinese website!