PHP技巧和窍门来简化你的代码

举报
海拥 发表于 2022/01/22 18:11:43 2022/01/22
【摘要】 🌊 作者主页:海拥🌊 简介:🏆CSDN全栈领域优质创作者、🥇HDZ核心组成员、🥈蝉联C站周榜前十🌊 粉丝福利:粉丝群 每周送6~9本书,不定期送各种小礼品,往期获奖公布对我而言,使用PHP一直是我最有趣的经历,无论是从事大型项目还是小型项目,并在每次旅行中都学到一些新东西。我将分享一些小技巧,这些技巧可以帮助大家减少几行代码。如果您有任何想法,欢迎评论提问或者加我建的群进行讨论 ...

🌊 作者主页:海拥
🌊 简介:🏆CSDN全栈领域优质创作者、🥇HDZ核心组成员、🥈蝉联C站周榜前十
🌊 粉丝福利:粉丝群 每周送6~9本书,不定期送各种小礼品,往期获奖公布

对我而言,使用PHP一直是我最有趣的经历,无论是从事大型项目还是小型项目,并在每次旅行中都学到一些新东西。

我将分享一些小技巧,这些技巧可以帮助大家减少几行代码。如果您有任何想法,欢迎评论提问或者加我建的群进行讨论

技巧1 : (if and else)

您可能以前在教程或其他文章中已经看到过这一点,但这是我真正要提到的非常重要的一点点内容。 实际上,在代码中使用elseelse if块是没错的,但是,在某些情况下,这些块变得多余。 让我们看一个例子:

function output_gender(bool $user_is_male) {
    if ($user_is_male) {
        return "User is male";
    } else {
        return "User is female";
    }
}

在这种情况下,output_gender函数基于$ user_is_male返回的设置输出为truefalse。 当在函数中使用return时,return语句下面的任何代码都将被完全忽略,因此,如果$ user_is_maletrue,则else块将被忽略,因为返回了值。 有了这个概念,我们可以像这样摆脱else块:

function output_gender(bool $user_is_male) {
    if ($user_is_male) {
        return "User is male";
    }

    return "User is female";
}

我们知道,如果传入的条件为false,则if语句将不会运行。 这意味着它将直接跳到"User is female"部分。

技巧2 : (if blocks: less vs more)

技巧2建立在我们上面刚刚看过的技巧上,但更深入了。 在if/else甚至使用技巧1的示例中,您可能会遇到以下情况:一个块(不管为if或else)的代码少于另一个块。 在这种情况下,最好先用较少的代码处理该块。 让我们看一个真实的例子。

public function categoryWithPosts($category)
{
    $category = Category::find($category);

    if ($category) {
        $category->posts = $category->posts()->published()->get();
        return response(['data' => $category], 200);
    } else {
        return response(['error' => 'Category not found'], 404);
    }
}

上面的这段代码检查职位类别,并根据是否找到该类别来运行条件。 如果只用技巧1,我们将得到如下代码:

public function categoryWithPosts($category)
{
    $category = Category::find($category);

    if ($category) {
        $category->posts = $category->posts()->published()->get();
        // having any more code here would
        // bloat this part of the function
        return response(['data' => $category], 200);
    }

    return response(['error' => 'Category not found'], 404);
}

这段代码是正确的,但是,您可以清楚地看到我们的主要代码用{}包裹起来,并被进一步推入。 如果这段代码明显更长,那么将其全部保留在if块中将是一件痛苦的事情。 在技巧2之后,我们可以改用以下方法:

public function categoryWithPosts($category)
{
    $category = Category::find($category);

    if (!$category) {
        return response(['error' => 'Category not found'], 404);
    }

    $category->posts = $category->posts()->published()->get();
    // we can freely have more code here
    // without worrying about the code looking weird
    return response(['data' => $category], 200);
}

由于else块的代码较少,因此我们使用带有!的否定语句。 使该代码先运行。因此,我们的if就算包含if not category, 也可以运行代码。…这为我们提供了更多空间来自由处理我们的主要代码。

技巧3 : (验证多个字符串)

假设我们要查找某个变量是否为多个字符串之一,显然我们必须编写一堆条件语句来验证这一点:

$item = "candy";

switch ($item) {
    case 'candy':
        return true;
    case 'toy':
        return true;
    default:
        return false;
}
// we're not adding break because we're using return

// or
if ($item == 'candy' || $item == 'toy') {
    return true;
}

return false;

如果item变量既不是candy也不是toy,则此代码返回false。 这是完全正确的,但是,这是非常冗余的。 其实我们可以检查数组以查找要查找的字符串:

if (in_array($item, ["candy", "toy"])) {
    return true;
}

return false;

就算这样,你还可以进一步缩短,因为in_array返回一个布尔值。

return in_array($item, ["candy", "toy"]);

我们将这些行缩短为仅一行,简洁吗?这是怎么做到的的?我们有一个包含要检查的字符串的数组。然后我们将其传递给in_array。这将创建一个简单的条件,例如:

if $item is inside the array holding "candy" and "toy", return true, else false

您可能想知道,为什么不直接返回$ item是candy还是toy,因为那也只是一行,就像这样:

return ($item == 'candy' || $item == 'toy');

这将给我们相同的结果,但是假设我们正在检查10个字符串:

return ($letter == 'a' || $letter == 'b' || $letter == 'c' || $letter == 'd' ...);

与以下内容相比,您可以清楚地看到这很容易失控:

return in_array($letter, ["a", "b", "c", "d", ...]);

请注意,第一个参数in_array是我们实际上正在检查的字符串

技巧4: (??)

??这是创建没有两个部分的内联条件的最简单方法。我什么意思 让我们看一个示例,该示例将为我做所有解释。

$data = [
    "a" => 1,
    "b" => 2,
    "c" => null,
];

return $data["c"] ? $data["c"] : "No data";

此处的最后一行检查键入c的内容$data是否为真,否则返回“No data”。

我们可以用??重写最后一行 看起来像这样:

// ...
return $data["c"] ?? "No data";

在这种情况下??行为类似于其他语言中的||逻辑运算符。一个真实的例子如下:

$user = getUserFromDb($user_id) ?? trigger_error("User id is invalid");

echo $user;

getUserFromDb用于从某个地方的数据库返回用户,但是,如果找不到该用户,则不设置用户变量,而是使用trigger_error破坏应用程序。没有??我们必须改写成这样:

$user = getUserFromDb($user_id);

if (!$user) {
    trigger_error("User id is invalid");
}

echo $user;

技巧5 :(递归优先于重复)

我认为此技巧非常简单,请尝试使用递归性,而不要重复很多次。在某些情况下会让您重复一些代码,这很好,但是如果您发现要重复相同的代码,只需将其设为方法即可。递归从何而来?让我们看一个例子:这是我为Leaf框架的request对象编写的一种方法,用于返回传递到请求中的特定字段。

/**
 * Returns request data
 *
 * This methods returns data passed into the request (request or form data).
 * This method returns get, post, put patch, delete or raw faw form data or NULL
 * if the data isn't found.
 *
 * @param string|array $params The parameter(s) to return
 * @param bool $safeData Sanitize output
 */

这意味着该方法可以接受数组或字符串,并且根据输入,它将返回字符串或数组。解决方案是检查输入是否为数组,在其上循环以获取数组中的字符串,然后对这些字符串执行数据获取,如下所示。

public function get($params, bool $safeData = true)
{
    if (is_string($params)) return $this->body($safeData)[$params] ?? null;

    $data = [];
    foreach ($params as $param) {
        $data[$param] = $this->body($safeData)[$params] ?? null;
    }
    return $data;
}

在这里,您会注意到$this->body($safeData)[$params]??null重复的过程不仅是这样,而且如果传入包含另一个数组的数组又会怎样呢。由于这是一个库,因此无法确定用户将在其中传递的内容,因此我改为这样做。

public function get($params, bool $safeData = true)
{
    if (is_string($params)) return $this->body($safeData)[$params] ?? null;

    $data = [];
    foreach ($params as $param) {
        $data[$param] = $this->get($param, $safeData); // I called the function again
    }
    return $data;
}

这样可以确保在循环值是一个字符串之前,它不会尝试获取其数据。与上述相比,这是一个小技巧,但绝对有用。请注意,此函数是类范围的,因此使用$this

技巧6 : (PHP + HTML)

当您想用HTML中的PHP或PHP中的HTML编写时。 我们通常会做类似的事情:

<?php
foreach ($items as $item) {
    echo '
        <div class="product__card">
            <h3>{$item->name}</h3>
        </div>
    ';
}
?>

尽管很好,您可以清楚地看到,我们将HTML输出为字符串。 HTML越庞大,匹配标签并准确跟踪我们正在编写的HTML的哪个部分就变得越有压力。 有一个整洁的解决方案。

<?php foreach ($items as $item): ?>
    <div class="product__card">
        <h3><?php echo $item->name; ?></h3>
    </div>
<?php endforeach; ?>

您可以清楚地看到我们如何保持HTML格式和代码对齐……不,这不是模板引擎,这只是PHP使我们变得简单。 关于PHP的一件主要事情是它如何允许以许多不同的方式完成同一件事。 在上面的示例中,我们使用:

foreach (...):
// code
endforeach;

// also works with if
if (...):
// code
endif;

// also
if (...) #one line code

while():
// ...
endwhile;

技巧7: (编写功能块)

功能块的范围可以从一个大功能到一个单独的包装器,围绕默认的PHP函数,重点只是创建该功能块。 这不仅是为了避免重复,而且还可以加快工作流程并提高代码的可读性。

您可以编写一个简单的方法来创建重定向,如下所示:

function redirectTo($route) {
    header("location: $route", true, 302);
}

因此,与其每次都写header("location: /home", true, 302),不如编写redirectTo("/home")。 这同样适用于第三方库和较长的过程,它们以开放的方式编写可重用的代码块,例如:

UserNotification::send($user_id, $notification);

显然比每次必须向用户发送通知时写一堆代码要好。另一个很小但非常有用的技巧。

技巧8: (使用类型)

另一个简单明了。这是PHP中使用最少的功能,但功能非常强大。此功能可以为您和其他开发人员减轻很多压力(如果您与团队合作)。

当然,您可以像上面技巧5中的示例一样编写函数说明,但是在大型项目中为所有函数和变量编写函数说明成为一项艰巨的任务。

让我们看看类型如何在以后拯救我们的生命:

function getItem($item) {
    // $item is expected to be an array
    // for whatever reason
    return allItems()[$item[0]];
}

如果几个星期后,另一个开发人员甚至是您自己在项目上工作,请参见getItem方法,$item显然可以看到该变量是一个字符串,但是该函数是为处理数组而编写的。

这里的危险之处在于,传递字符串不会破坏应用程序,它仍然可以完美运行。为什么?

如果将“ chair”传递到函数中,它将被评估为allItems()["c"],最终将导致错误,使您在12am😅起床。这样可以很容易避免:

function getItem(array $item) {
    return allItems()[$item[0]];
}

这将确保此处传递的内容都是所需的类型。您可以从php.net阅读更多内容

您也可以像上面这样使用is_string和方法is_array,如下所示:

function getItem($item) {
    if (!is_array($item)) throwErr("item should be array");

    return allItems()[$item[0]];
}

技巧9 : (框架/库是没有坏处的)

在这里我将是真实的,开源库会引起问题!有时,我们带来的图书馆会给我们带来更多问题,而不是帮助我们。听起来好像我完全在破坏开源软件包,不是,我自己也写开源软件包,所以显然不是!

我的观点是,您应该阅读有关引入的软件包的更多信息,阅读其文档,在GitHub上检查其问题,不要承担不必要的风险。我会建议您做一件事,这可以回溯到技巧7,为您带来的软件包编写功能包装器。这将给您带来更多的控制权,并使您的代码更整洁。

关于框架,您以前可能已经听说过,但是您应该首先熟悉PHP。PHP框架,无论使用哪种语言编写,都仍然使用PHP的原理和样式,因此第一步显然是要熟悉PHP。

接下来是选择您喜欢的东西并坚持下去。有很多选择:

  • Laravel:如果您喜欢魔术,Laravel会为您做所有事情(除非您另有决定)
  • Slim:其余的API框架,具有“自带”氛围
  • Leaf:这是我在Slim和Laravel的启发下写的,它为您提供了可以控制的魔术。 我只提到了我实际上用来避免偏见的框架。

提示10 : (不要只是为了写代码!)

好了,这是一个额外的技巧。它不仅适用于PHP,而且技术上几乎适用于您使用的每种语言/框架。我所指的不仅是代码是相对简单的。

假设您要编写一种方法来请求用户帐户付款,直接跳入编码此功能的过程可能(也可能不会)最终使您感到困惑,这时您必须停止,滚动备份,检查某处文件中的内容或类似内容。

我有什么建议?这里:

// in class scope
public function requestPayout()
{
    // parse token to get user id

    // fetch user from DB with id

    // check if the user is eligible for payouts

    // get user balance with user helper

    // check and throwErr for insufficient funds

    // ...
}

上面的内容仅允许您在实际跳入编写任何功能之前进行所有必要的思考。它还可以帮助您交叉检查正在构建的内容,因为最终您将首先列出所有流程。

谢谢阅读

这些是我在PHP之旅中发现的一些技巧和窍门,其中一些可能对您有用,而另一些则可能不起作用,请随时选择自己喜欢的并坚持使用。

说这些是做事的好方法是完全错误的,所以只能使用它们,就像我之前提到的那样,PHP是一种语言,它提供了许多做同一件事的不同方式,因此,如果您有任何想要分享的东西,新提示,做我提到的事情的更快方法,您不同意的事情,请与我联系。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。