doushishi2415 2013-12-25 21:02 采纳率: 0%
浏览 27
已采纳

重构如果地狱

TL;DR: What strategy can I follow to simplify request's if hell?

I'm refering specifically to one of my github files. It's there to deal with different possible user actions. I'm trying to refactor it, but I'm not sure what's the best way. A small fraction of the code:

// The users returned from validating
if (!empty($_SESSION['service_connect']))
  {
  // If the service is a valid one
  if (in_array($_SESSION['service'], $UMConfig->services))
    {
    // Include the needed files.
    include $UMConfig->path . "/services/" . $_SESSION['service'] . "/verify.php";
    }
  }
// One service has set an email
if (isset($_SESSION['service_email']))
  {
  // The user is already in the database
  if (Validate::is_user($_SESSION['service_email']))
    {
    // User is logged in
    $_SESSION['email'] = $_SESSION['service_email'];
    include 'actions/login.php';
    }
  // The user is not in the database and didn't submit anythign
  elseif (empty($_POST))
    {
    // !POST
    $UMLog = "We are trying to register you with a service.";
    // Check if the popup has been submited or not
    include 'actions/service_verified.php';
    }
  // The user has submitted something with POST
  else {
    include 'actions/register_service.php';
    $UMLog = "Registering with " . $_SESSION['service'] . ".";
    }
  }

// No user was in the session but there's a user in the cookies
elseif (isset($_COOKIE['email']))
  {
  // The email is in the database
  if (Validate::is_user($_COOKIE['email']))
    {
    // If there's a token
    if (isset($_COOKIE['token']))

My idea right now is to simplify the code into smaller chunks and call them individually. This is the general idea of what I intend to do:

// Get what kind of action is needed
require 'request.php';
$action = request($_POST, $_SESSION, $_COOKIE);

if (file_exists($action_path = "actions/" . $action . ".php"))
  include $action_path;
else
  throw new Exception("Action was not valid: " . $action);

However, this only simplifies it slightly, as I'm only moving the if hell to 'request.php'. It has the advantage that testing is much easier in this way.

I have read how polymorphism can simplify some ifs, however I don't think it can be applied in this case. What strategy can I follow to simplify this if hell?

EDIT: in case anyone's wondering, I have so many ifs because, besides the regular login/register, I allow users to login/register using an external service as facebook/google/etc, which requires more steps and makes it significantly more difficult.

  • 写回答

1条回答 默认 最新

  • dongzhanlian6289 2014-01-02 02:06
    关注

    I decided to follow this strategy: one function, request(), identifies what kind of request is being made in their simplest form. Only identifies the action in its simplest form and returns this.

    Then, the script calling it, include.php, includes that action from a directory containing all actions. Each of the callable actions have many methods to verify they are valid.

    request.php:

    <?php
    
    // Find if there was any action to be done with the data provided
    // Importance of requests: post > session > cookie (there're no get requests)
    
    function request($Post, $Session, $Cookie)
      {
      // The user is trying to log out
      if ($Post->logout)
        {
        return "log_user_out";
        }
    
      // The user wants to edit the profile
      if ($Post->edit)
        {
        return "edit_user_data";
        }
    
      // Someone is trying to log in
      if ($Post->login)
        {
        return "log_user_in";
        }
    
      // Someone is trying to log in
      if ($Post->recover)
        {
        return "recover_password";
        }
    
      // Someone is trying to register
      if ($Post->register)
        {
        return "register_with_form";
        }
    
      // First time the user attempts to connect with a service
      // This should be vefore register_with_service in case someone clicked
      // a service but later wants to register with another service
      if ($Post->service_connect)
        {
        return "service_connect";
        }
    
      // Someone is trying to register with a service
      if ($Post->service && $Session->service_email)
        {
        return "register_with_service";
        }
    
      // The service returned green light
      if ($Session->service_connect)
        {
        return "verify_service";
        }
    
      // The user just landed here after confirming in the service
      if ($Session->service_email)
        {
        return "service_is_verified";
        }
    
      // There's already a user logged in. Simply retrieve the user
      if ($Session->email)
        {
        return "retrieve_user";
        }
    
      // There's apparently a user in the cookies
      if (isset($Cookie['email']))
        {
        return "login_with_cookie";
        }
    
      // If nothing from the above was submitted
      return null;
      }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 网络设备配置与管理这个该怎么弄
  • ¥20 机器学习能否像多层线性模型一样处理嵌套数据
  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器