Php 在应用程序和聊天服务器(Symfony和Memcache)之间共享会话

Php 在应用程序和聊天服务器(Symfony和Memcache)之间共享会话,php,symfony,session,memcached,ratchet,Php,Symfony,Session,Memcached,Ratchet,试图了解如何在我的应用程序和聊天服务器(Ratchet)之间共享我的会话数据。我原以为使用Symfony&Memcache会很容易,但我似乎无法让它工作 我试图将用户id从会话中取出,因为当有人向聊天室发送消息时,它会将用户id插入数据库(chat->onMessage) 谁能给我指一下正确的方向吗 流量: config.php包含在每个页面上 当用户登录到网站时,它会执行$login->processLogin()方法 我通过命令行启动聊天服务器(php server.php) config.

试图了解如何在我的应用程序和聊天服务器(Ratchet)之间共享我的会话数据。我原以为使用Symfony&Memcache会很容易,但我似乎无法让它工作

我试图将
用户id
从会话中取出,因为当有人向聊天室发送消息时,它会将
用户id
插入数据库(
chat->onMessage

谁能给我指一下正确的方向吗

流量:

  • config.php
    包含在每个页面上
  • 当用户登录到网站时,它会执行
    $login->processLogin()
    方法
  • 我通过命令行启动聊天服务器(
    php server.php
  • config.php

    <?php
    use MyApp\Login;
    use MyApp\Session as MySession;
    
    # Define backslash or forward slash for *NIX and IIS systems.
    define('DS', DIRECTORY_SEPARATOR);
    # Attempt to determine the full-server path to the 'root' folder in order to reduce the possibility of path problems.
    define('BASE_PATH', realpath(dirname(__FILE__)).DS);
    
    # Define the complete path to the root of the domain we are at (ie. /home/user/domain.com) (does't end in a slash)
    define('ROOT_PATH', $_SERVER['DOCUMENT_ROOT']);
    # Define where cookies may be active. ('/' means the entire domain)
    define('COOKIE_PATH', '/');
    # Name sessions. (needs to be alphanumeric with no periods[.]- can't be solely digits; must contain at least one letter)
    define('SESSIONS_NAME', 'SiteUser');
    
    # Get the Session Class.
    require_once BASE_PATH.'modules'.DS.'Session'.DS.'Session.php';
    # Check if there is a session id set the the $sesh_id variable.
    $sesh_id=((isset($sesh_id)) ? $sesh_id : NULL);
    # Create a new session object, thus starting a new session.
    $mysession=MySession::getInstance(NULL, NULL, NULL, $sesh_id);
    
    <?php
    use Ratchet\Server\IoServer;
    use Ratchet\Http\HttpServer;
    use Ratchet\WebSocket\WsServer;
    use Ratchet\Session\SessionProvider;
    use Symfony\Component\HttpFoundation\Session\Storage\Handler;
    use MyApp\Chat;
    
    $port="8080";
    
    # Change to this directory.
    chdir(dirname(__FILE__));
    
    # Need this for the database insert.
    if(!defined('DOMAIN_NAME'))
    {
        define('DOMAIN_NAME', 'example.dev');
    }
    
    require_once '../../includes/lonconfig.php';
    require_once '../../vendor/autoload.php';
    
    $memcache=new Memcache;
    $memcache->connect(DOMAIN_NAME, 11211);
    
    $session=new SessionProvider(
        new Chat,
        new Handler\MemcacheSessionHandler($memcache)
    );
    
    $server=IoServer::factory(
        new HttpServer(
            new WsServer($session)
        ),
        $port,
        DOMAIN_NAME
    );
    
    $server->run();
    

    您不应该在应用程序的所有部分上共享这些数据

    如果你打开Ratchet教程,你会发现关于pushServers的部分

    这允许您推送到某个
    频道
    $user\u id
    (在您的情况下)

    这使您能够不保存或传输这两部分中的数据,并将有助于简化工作流程

    我个人在多个渠道中使用pushServer,这些渠道分为:

    • 所有用户在线(发送广播)
    • 组中的所有用户(sendGroup)
    • 跟随标记(sendTag)的所有用户
    • 发送给其他用户(sendToUser)
    我希望这已经给了你一个如何解决你的问题的想法,否则请随便问

    <?php
    namespace MyApp;
    
    use Memcache;
    use Symfony\Component\HttpFoundation\Session\Session as SymfonySession;
    use Symfony\Component\HttpFoundation\Session\Storage\Handler;
    use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
    use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcacheSessionHandler;
    
    /**
     * Class Session
     *
     * The Session class is used to access and manipulate Sessions and data stored in them.
     */
    class Session
    {
        private static $session;
        private $message=FALSE;
        private $sessname=FALSE;
        public $symfony_session;
    
        /**
         * Session constructor.
         *
         * Safely calls session_start().
         * Also enables sessions to span sub domains. It names the session (which is necessary for
         * session_set_cookie_params() to work). If calling this class before setting.php, $sessname (the session name) AND
         * $cookiepath (the path for cookies) MUST be defined.
         *
         * @param null $sessname
         * @param null $cookiepath
         * @param bool $secure
         * @param null $sesh_id
         */
        public function __construct($sessname=NULL, $cookiepath=NULL, $secure=FALSE, $sesh_id=NULL)
        {
            require_once BASE_PATH.'vendor'.DS.'autoload.php';
            $memcache=new Memcache;
            $memcache->connect(DOMAIN_NAME, 11211);
            $storage=new NativeSessionStorage(array(), new Handler\MemcacheSessionHandler($memcache));
            $symfony_session=new SymfonySession($storage);
    
            # Check if a session ID was passed.
            if($sesh_id!==NULL)
            {
                //session_id($sesh_id);
                $symfony_session->setId($sesh_id);
            }
            # Is a session already started?
            //if(!isset($_SESSION['s_set']))
            if(!$symfony_session->has('s_set'))
            {
    
                # If we haven't been given a session name, we will give it one.
                if(empty($cookiepath))
                {
                    # Set the default cookie path be the root of the site.
                    $cookiepath=DS;
                    # Check if the cookie path was defined in settings.php.
                    if(defined('COOKIE_PATH'))
                    {
                        # Check if the defined path is blank.
                        if(COOKIE_PATH!='')
                        {
                            # If the cookie path has been defined in settings.php, we'll use that path.
                            $cookiepath=COOKIE_PATH;
                        }
                    }
                }
                //session_set_cookie_params($life, $cookiepath, '.'.DOMAIN_NAME, $secure);
    
                /*
                 * Read the current save path for the session files and append our own directory to this path.
                 * Note: In order to make that platform independent, we need to check for the file-seperator first.
                 * Now we check if the directory already has been created, if not, create one.
                 * Then we set the new path for the session files.
                 */
                # Get the session save path.
                $save_path=session_save_path();
                # Find out if our custom_session folder exists. If not, let's make it.
                if(!is_dir(BASE_PATH.'../custom_sessions'.DS.'.'))
                {
                    mkdir(BASE_PATH.'../custom_sessions', 0755);
                }
                # Is our custom_sessions folder the session save path? If not, let's make it so.
                if($save_path!==BASE_PATH.'../custom_sessions')
                {
                    //session_save_path(BASE_PATH.'../custom_sessions');
    
                    # How do I set the save path in Symfony?
                }
    
                # If we haven't been given a session name, we will give it one.
                if(empty($sessname))
                {
                    # Set the default session name.
                    $sessname='PHPSESSID';
                    # Check if the session name was defined in settings.php.
                    if(defined('SESSIONS_NAME'))
                    {
                        # Check if the defined name is blank.
                        if(SESSIONS_NAME!='')
                        {
                            # If the session name has been defined in settings.php, we'll give the session that name.
                            $sessname=SESSIONS_NAME;
                        }
                    }
                }
                $storage->setOptions(array(
                    'cookie_domain'=>'.'.DOMAIN_NAME,
                    'cookie_lifetime'=>0,
                    'cookie_path'=>$cookiepath,
                    'cookie_secure'=>$secure,
                    'name'=>$sessname
                ));
                //$this->setSessname($sessname);
                # Name the session.
                //session_name($this->getSessname());
    
                # Session must be started before anything.
                //session_start();
                //$session->setName($this->getSessname());
                $symfony_session->start();
    
                # Set the s_set session so we can tell if session_start has been called already.
                //$_SESSION['s_set']=1;
                $symfony_session->set('s_set', 1);
            }
    
            $this->symfony_session=$symfony_session;
    
            print_r($symfony_session);exit;
        }
    
        /**
         * getSessname
         *
         * Returns the data member $sessname.
         *
         * @access    public
         */
        public function getSessname()
        {
            return $this->sessname;
        }
    
        /**
         * Sets the data member $sessname. If an empty value is passed, the data member will
         * be set with FALSE. Returns the set data member value.
         *
         * @param $sessname
         * @return bool
         */
        public function setSessname($sessname)
        {
            # Clean it up...
            $sessname=trim($sessname);
            # Check if the passed value is now empty.
            if(empty($sessname))
            {
                # Explicitly set the data member to false.
                $sessname=FALSE;
            }
            # Set the data member.
            $this->sessname=$sessname;
    
            # Return the data member after it has gone through the get method.
            return $this->getSessname();
        }
    
        /**
         * Gets the singleton instance of this class.
         *
         * @param null $sessname
         * @param null $cookiepath
         * @param bool $secure
         * @param null $sesh_id
         * @return Session
         */
        public static function getInstance($sessname=NULL, $cookiepath=NULL, $secure=FALSE, $sesh_id=NULL)
        {
            if(!self::$session)
            {
                self::$session=new Session($sessname, $cookiepath, $secure, $sesh_id);
            }
    
            return self::$session;
        }
    }
    
    <?php
    use Ratchet\Server\IoServer;
    use Ratchet\Http\HttpServer;
    use Ratchet\WebSocket\WsServer;
    use Ratchet\Session\SessionProvider;
    use Symfony\Component\HttpFoundation\Session\Storage\Handler;
    use MyApp\Chat;
    
    $port="8080";
    
    # Change to this directory.
    chdir(dirname(__FILE__));
    
    # Need this for the database insert.
    if(!defined('DOMAIN_NAME'))
    {
        define('DOMAIN_NAME', 'example.dev');
    }
    
    require_once '../../includes/lonconfig.php';
    require_once '../../vendor/autoload.php';
    
    $memcache=new Memcache;
    $memcache->connect(DOMAIN_NAME, 11211);
    
    $session=new SessionProvider(
        new Chat,
        new Handler\MemcacheSessionHandler($memcache)
    );
    
    $server=IoServer::factory(
        new HttpServer(
            new WsServer($session)
        ),
        $port,
        DOMAIN_NAME
    );
    
    $server->run();
    
    <?php
    namespace MyApp;
    
    use Ratchet\MessageComponentInterface;
    use Ratchet\ConnectionInterface;
    
    class Chat implements MessageComponentInterface
    {
        protected $clients=array();
    
        public function onOpen(ConnectionInterface $conn)
        {
            # get the cookies
            $cookies=(string)$conn->WebSocket->request->getHeader('Cookie');
            # Returns only PHPSESSID (not SiteUser).
            //var_dump($cookies);exit;
    
            $this->clients[$conn->resourceId]=$conn;
            echo "New connection! ({$conn->resourceId})\n";
        }
    
        /**
         * @param ConnectionInterface $conn
         * @param string $data
         */
        public function onMessage(ConnectionInterface $conn, $data)
        {
            $database=$this->dbh;
    
            $data=json_decode($data, TRUE);
    
            if(isset($data['data']) && count($data['data'])!=0)
            {
                require_once BASE_PATH.'vendor'.DS.'autoload.php';
                $memcache=new Memcache;
                $memcache->connect(DOMAIN_NAME, 11211);
                $storage=new NativeSessionStorage(array(), new Handler\MemcacheSessionHandler($memcache));
                $session=new SymfonySession($storage);
    
                $type=$data['type'];
                $user_id=$conn->Session->get('user_id');
    
                $return=NULL;
    
                if($type=="send" && isset($data['data']['type']) && $user_name!=-1)
                {
                    $msg=htmlspecialchars($data['data']['msg']);
                    $date=new DateTime;
                    $date->setTimezone(new DateTimeZone(TIMEZONE));
    
                    if($data['data']['type']=='text')
                    {
                        echo 'test 4';exit;
                        $database->query('SELECT `id`, `user_id`, `msg`, `type` FROM `chat` ORDER BY `id` DESC LIMIT 1', array());
                        $lastMsg=$database->statement->fetch(PDO::FETCH_OBJ);
    
                        if($lastMsg->user_id==$user_id && (strlen($lastMsg->msg)<=100 || strlen($lastMsg->msg)+strlen($msg)<=100))
                        {
                            # Append message.
                            $msg=$lastMsg->msg."<br/>".$msg;
    
                            $database->query('UPDATE `chat` SET `msg`=:msg, `posted`=NOW() WHERE `id`=:lastmsg', array(
                                ':msg'=>$msg,
                                ':lastmsg'=>$lastMsg->id
                            ));
    
                            $return=array(
                                "id"=>$lastMsg->id,
                                "name"=>$user_name['staffname'],
                                "type"=>"text",
                                "msg"=>$msg,
                                "posted"=>$date->format("Y-m-d H:i:sP"),
                                "append"=>TRUE
                            );
                        }
                        else
                        {
                            $database->query('INSERT INTO `chat` (`user_id`, `msg`, `type`, `posted`) VALUES (?, ?, "text", NOW())', array(
                                $user_id,
                                $msg
                            ));
    
                            # Get last insert ID.
                            $get_chat_id=$database->lastInsertId();
                            $return=array(
                                "id"=>$get_chat_id,
                                "name"=>$user_name['staffname'],
                                "type"=>"text",
                                "msg"=>$msg,
                                "posted"=>$date->format("Y-m-d H:i:sP")
                            );
                        }
                    }
    
                    foreach($this->clients as $client)
                    {
                        $this->send($client, "single", $return);
                    }
                }
                elseif($type=="fetch")
                {
                    # Fetch previous messages.
                    $this->fetchMessages($conn, $data['data']['id']);
                }
            }
        }
    }