How do I create a Magento session outside of Magento?

10,323

Solution 1

Well, I've figured it out. Although I must admit it's not the cleanest solution, it works exactly as I had hoped. For anyone else who's looking to do this, I've pasted my code excerpt below:

require 'app/Mage.php';
$mageRunCode = isset ( $_SERVER ['MAGE_RUN_CODE'] ) ? $_SERVER ['MAGE_RUN_CODE'] : '';
$mageRunType = isset ( $_SERVER ['MAGE_RUN_TYPE'] ) ? $_SERVER ['MAGE_RUN_TYPE'] : 'store';
$app = Mage::app ( $mageRunCode, $mageRunType );
$core_session = Mage::getSingleton ( 'core/session', array ('name' => 'frontend' ) );
$write = Mage::getSingleton ( 'core/resource' )->getConnection ( 'core_write' );

$url = Mage::getUrl ( '*/*/*', array ('_current' => true ) );

Mage::getSingleton ( 'core/session' )->setLastUrl ( $url );

$visitor_id = $_SESSION ['core'] ['visitor_data'] ['visitor_id'];

if (! empty ( $visitor_id )) {
    Mage::getSingleton ( 'log/visitor' )->setId ( $visitor_id );
} else {
    Mage::getSingleton ( 'customer/session' )->setWishlistItemCount ( 0 );
    Mage::getSingleton ( 'catalog/session' )->setCatalogCompareItemsCount ( 0 );

    $write->query ( "INSERT INTO log_url_info (url, referer) VALUES (?, ?)", array ($url, Mage::helper ( 'core/http' )->getHttpReferer ( true ) ) );
    $url_id = $write->lastInsertId ();
    $log_visitor = Mage::getSingleton ( 'log/visitor' )->initServerData ()->setFirstVisitAt ( now () )->setIsNewVisitor ( true )->setLastVisitAt ( now () )->setLastUrlId ( $url_id )->save ();
    $write->query ( "INSERT INTO log_url (url_id, visitor_id, visit_time) VALUES (?, ?, ?)", array ($url_id, $log_visitor->getId (), now () ) );
    $core_session->setVisitorData ( $log_visitor->getData () );

    $visitor_id = $log_visitor->getId ();
}

I hope this helps someone else so they're not ripping their hair out like I was.

Solution 2

Actually these answers didn't work because I was running code in a subdirectory of Magento. Magento looks at the dirname of your SCRIPT_NAME variable, and sets it there. So if you're setting the session from /foo/test.php then the cookie will only be valid for /foo/, if magento is at "/", it won't see the cookie.

In this case, if your script is the one initially creating the cookie, you have to force the cookie to be valid for "/".

The symptoms is that your changes don't take affect, and you can see two sessions in "/var/session". It seems unpredictable, but the different is if Magento creates the session first, its valid for all paths. If your script creates it first, its not valid for Magento, the browser omits it, and Magento creates a new session.

Example working code:

<?php
ini_set('display_errors', 1);
require_once $_SERVER['DOCUMENT_ROOT'] . '/app/Mage.php';

Mage::app('mystore', 'website');

$session = Mage::getSingleton('core/session', array('name' => 'frontend'));
$sessionName = $session->getSessionName();
$sessionId = $session->getSessionId();

/**
 * Magento sets the cookie valid for the path "/recommend", but we need it available always (path "/")
 */
setcookie($sessionName, $sessionId, null, '/');

(The reason I used DOCUMENT_ROOT is because I'm using a modman mapping from this module, which runs the code through a symlink). The important part is the setcookie(). You'll see from examining the http headers two cookies are set. One for "/foo" and one for "/". Without the call to setCookie, only the first session is created, which isn't visible to Magento when accessed through "/index.php" instead of "/foo/test.php"

Solution 3

Not sure if this helps, but here's a bit of code to help load magento a little more accurately via the app() bootstrap method. By dispatching some events, it instantiates the visitor object and loads some other helpful objects/resources that make it function similar to native Magento's run():

<?php
require_once $_SERVER['DOCUMENT_ROOT'].'/app/Mage.php';
umask(0);
//Scope
$scope = 'frontend';
// Initialize Mage_Core_Model_App object
$app = Mage::app('', 'store');
// Grab the front controller
$frontController = $app->getFrontController();
// Load configuration
Mage::getConfig()->init();
// Load event observers for specified scope
Mage::getConfig()->loadEventObservers($scope);
// Set the theme (not sure if needed, appears it falls back to whats set in the admin)
//Mage::getdesign()->setTheme('morris-v2');
// Add event area for event dispatching
$app->addEventArea($scope);
//Init the session by calling singleton
Mage::getSingleton('core/session', array('name'=>$scope));
//dispatch  layout load before event, this is useful for observing in case of ab testing etc
Mage::dispatchEvent('controller_action_layout_load_before', array('action'=>$frontController, 'layout'=>Mage::getSingleton('core/layout')));
//dispatch action predispatch, this has some observers which instantiate needed variables such as log/visitor
Mage::dispatchEvent('controller_action_predispatch', array('controller_action'=>$frontController));
Share:
10,323
Admin
Author by

Admin

Updated on June 05, 2022

Comments

  • Admin
    Admin almost 2 years

    I am able to access an existing session outside of Magento perfectly fine using the popular method below.

    require 'app/Mage.php';
    $mageRunCode = isset ( $_SERVER ['MAGE_RUN_CODE'] ) ? $_SERVER ['MAGE_RUN_CODE'] : '';
    $mageRunType = isset ( $_SERVER ['MAGE_RUN_TYPE'] ) ? $_SERVER ['MAGE_RUN_TYPE'] : 'store';
    $app = Mage::app ( $mageRunCode, $mageRunType );
    Mage::getSingleton ( 'core/session', array ('name' => 'frontend' ) );
    

    This works great, but how do I actually create a Magento session outside of Magento that would populate the log_url, log_visitor, etc. tables as well as assigning the visitor data to the session?

    Currently, the user arrives at a page on my site directly from another website. This specific page is outside of Magento but I need to access their Visitor ID using the following code:

    Mage::getSingleton ( 'log/visitor' )->getId()
    

    This works fine if the user has previously been to my Magento store, but if not, it just returns a boolean false. What I would like to do is check to see if there is a value set for the Visitor ID and if not, create the visitor on this first page which is outside of Magento so I can use the Visitor ID right on this page. It is also important that as soon as the user enters my Magento store, the same Visitor ID will be applied throughout their navigation of my catalog, i.e. the same session. Any ideas?