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 微信小程序协议怎么写
  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看