如何处理AJAX请求和Sessions和Db连接?

时间:2011-12-30 10:19:06

标签: php mysql ajax session

好的,我所知道的描述场景的最好方法是首先举例:

假设我有一个名为index.php的页面;

<html> 标记之前的最顶部,可以找到;

<?php session_start();
 $_SESSION['user_id'] = 1234;
 require_once "db.con.php";
?>

<body> 标记内,可以找到:

<div id="div_ajax">
<?php require_once "ajax.php"; ?>
</div>

现在在ajax.php页面中,有一个按钮,点击后会发出一个ajax请求。发出请求后,将生成一个简单的Db查询语句,用于根据user_id选择用户信息。问题是,在AJAX请求之后,似乎user_id会话和已经包含的Db连接“丢失”。

我知道我可以使用条件语句检查AJAX请求,只需添加行......

session_start();
require_once "db.con.php";

..在ajax.php页面的顶部,但我想知道是否有更好的方法来做到这一点?我不想总是将这两行添加到每个名为PHP页面的ajax中。它有点挫败了主页(index.php)上的行开头的目的。我想我可以使用一个名为page的ajax并且只包含一堆case语句,但仍然想知道是否有更好的方法。

非常感谢。

3 个答案:

答案 0 :(得分:0)

我不认为有更好的方法,但这并不意味着没有。

阅读问题时只需注意几点: 1)为所有标题信息使用包装文件。因此,在页面的开头,添加:

require_once('package.php'); // that's what I call mine

然后在包装中,我有:

require_once('session.start.php');
require_once('db.con.php');

这样,你所有的页面都在访问同一个东西。如果你需要改变它,那就容易多了。

require_once,include_once,include和require之间存在速度差异。我不知道它有多重要。

表示框架在制作页面时包含60多个文件,所以我总是认为它不是太糟糕。

会话信息存储在服务器上的文件夹中。 PHP将其默认为/ tmp(您应将其更改为私人文件夹/不可访问Web)。

确保您正在验证发送给AJAX的任何信息。请记住,它就像它自己的网页一样,因此任何权限或数据库敏感信息都应该受到同样的保护。

  

“我想我可以使用一个名为page的ajax,只包含一堆case语句,但仍然想知道是否有更好的方法。”

控制器模式对于这类事物非常有用。在一个文件中包含大量case语句很难维护。当你切换到只有1或2个函数的文件时,你的生活将变得如此简单。

根据项目的大小,您可能希望实现框架。查看MVC框架。如果我没有实现框架,我仍然实现控制器模式。

我从博客中解除了这个问题。我现在使用的东西看起来都不像这样,但它从这里开始:

  

在Presentation层中,我正在确定要实现哪些元素。对于我想要实现的每个元素,我启动控制器,如下所示:

    $controller = new Controller();
    $context = $controller->getContext();
    $context->addParam('action', 'login');
    $template->setContent( $controller->process() ); 
  

我正在使用Matt Zandstra的PHP Objects,Patterns和Practice 3rd Ed中的Controller进行自己的修改。

以下是发生的事情:

  1. 我的表示层获取一个新的控制器对象。
  2. Controller对象的构造函数自动创建一个新的CommandContext对象。
  3. CommandContext 自动将请求变量作为参数加载,所以在进入逻辑层并需要验证和处理之前,我甚至不需要担心表单数据它。
  4. 在表示层中,我加载任何其他上下文参数(或我想传递给控制器​​的信息),包括最重要的是,我想要由Controller采取的操作。
  5. 要传递信息,我打电话给$ controller-&gt; process()。在逻辑层,我可以使用默认的“执行”或发出不同的命令。因此,在Presentation层中,我将操作设置为“Login”,强制登录命令和登录视图页面打开,命令默认执行,但它可以是任何内容。
  6. 当我调用process时,它会触发CommandFacotry。 CommandFactory将首先启动一个新的Template子对象,例如侧边栏div框或主体上下文。它使用可选标志进行此确定,我可以将其传递给Controller。
  7. 然后CommandFactory将打开Command文件并将模板和上下文作为对象传递给Logic层。
  8.     abstract class Command {
    
        }
    
        class CommandContext {
            private $params = array();
            private $error = "";
    
            function __construct(){
                $this->params = $_REQUEST;
            }
    
            function addParam( $key, $val ){
                $this->params[$key] = $val; 
            }
    
            function get( $key ){
                return $this->params[$key]; 
            }
    
            function issetCheck( $key ){
                if( ! empty( $this->params[$key] ) ){
                    return true;
                }
                return false;
            }
            function setError( $error ){
                $this->error = $error;  
            }
    
            function getError(){
                return $this->error;    
            }
        }
    
        class CommandNotFoundException extends Exception { }
    
        class CommandFactory {
            private static $dir = 'include/classes/command/';
    
            static function getCommand( $action = 'Default', $flag = 0 ){
    
                switch( $flag ){
                    case 1:
                        $template = new TemplateQuickViewOnly();
                        break;
                    case 2:
                        $template = new TemplateQuickViewToggle();
                        break;
                    default: 
                        $template = new TemplateMainBodyOnly();
                        break;
                }
    
                if( preg_match ( '/\W/', $action ) ){
                    throw new Exception("illegal characters in action");    
                }
    
                $class = UCFirst(strtolower($action))."Command";
                $file = ROOT_PATH."".self::$dir."{$class}.php";
                if( ! file_exists( $file ) ){
                    throw new CommandNotFoundException( "could not find '$file'" ); 
                }
                include_once( $file );
                if( ! class_exists($class) ){
                    throw new CommandNotFoundException( "no '$class' class located" );  
                }
                $cmd = new $class( $template );
    
                return array( $cmd, $template );
            }
        }
    
        class Controller {
            private $context;
    
            function __construct(){
                $this->context = new CommandContext();
            }
    
            function getContext(){
                return $this->context;  
            }
    
            function process( $method = 'execute', $flag = 0 ){
                list( $cmd, $template ) = CommandFactory::getCommand( $this->context->get('action'), $flag );
                if( ! $cmd->$method( $this->context ) ){
                    // handle failure
        //          $template->setMessage( UCFirst($this->context->get('action')).' failed to execute.');
                    return $template->getMessage();
                }else{
                    // success dispatch view
                    return $template->getMessage();
                }
            }
        }
    

    逻辑层位于固定目录中。对象的实例已经由Controller层实例化,这意味着构造函数已被触发。此外,控制器层已经调用了方法“执行”(默认)或其他方法,例如“getLoginForm”。另外,请注意,当Controller调用方法“execute”时,它也会将CommandContext传递给方法,因此我们可以使用它们。

    class LoginCommand extends Command {
    
        public function __construct( ){ }
    
        function execute ( CommandContext $context ){
    
            if( $context->get('login_user_name') == 'demo' ){
                $this->view->setMessage('Success is true!');
                return true;
            }
            return false;
        }
    
        function getLoginForm( CommandContext $context ){
            $this->view->setMessage('Second sucess is even more true!');
            return true;    
        }
    
    }
    

答案 1 :(得分:0)

你好像很困惑。

AJAX请求单独的网页请求,您在服务器端的index.php中所做的任何事情都不会在后续请求中提供(会话中的任何变量除外)。它的工作原理如下:

  1. 从浏览器发送index.php请求
  2. 服务器运行index.php(在会话中存储user_id)并在结束时将HTML输出返回给浏览器,PHP脚本完成并释放所有资源。
  3. 用户点击按钮,为另一个PHP文件创建请求,例如ajax.php
  4. 服务器运行ajax.php并返回输出到浏览器的任何内容。 PHP脚本再次完成,所有资源都被释放。
  5. 另一种思考方式:从服务器端看,AJAX请求几乎与您直接将浏览器指向ajax.php一样。

答案 2 :(得分:0)

就我的经验而言,我认为你的问题可以用FrontController pattern来解决。

基本思想是你整个应用程序总是调用相同的文件,例如index.php(也称为单一入口点)。

index.php然后执行每个页面上所需的所有任务(如启动会话或包含库类),然后调用您想要请求的页面。

这看起来像这样:(现在无法测试)

的index.php:

<?php

    session_start();
    $_SESSION['user_id'] = 1234;
    require_once("db.con.php");


    if($_REQUEST['Request_Type'] == 'website'){
        require_once("header.html");

        switch($_REQUEST['Request_Url']){
            case 'SomePage':
                require('SomePage.php');
                break;
            case 'SomeOtherPage':
                require('SomeOtherPage.php');
                break;
            default:
                require('ajax.php');
        }

        require_once("footer.html");

    }elseif($_REQUEST['Request_Type'] == 'ajax'){
        switch($_REQUEST['Ajax_Function']){
            case 'ProcessButton':
                require('ProcessButton.php');
                break;
        }
    }

?>

ajax.php

echo '<input type="button" onClick="ajaxRequest(\"index.php\",\"ProcessButton\")" Value="ClickMe!" />';

ajaxRequest()Javascript函数必须向index.php发送一个Ajax请求设置参数
   Request_Type ='ajax'
   Ajax_Function ='ProcessButton'