4

I have a requirement to create a number of custom reports on the magento data.

The first job I have to do is to improve on the ‘Products Viewed’ report integrated into Magento.

I have managed to work out that the data for this report is taken from the ‘report_event’ table, however there are some peculiarities with this data I need to understand.

Firstly, I assume that where event_type_id is 1 (i.e. ‘catalog_product_view’ according to the reference table), the columns object_id and subject_id store the ID of the product and the ID of the visitor respectively. However, there are a large number of entries where subject_id is zero, but object_id holds the id of a valid product.

What I need to know is how this can occur… i.e. how can we get an entry in the report_event table where the following are all true:

event_type_id = 1

object_id = [valid product id]

subject_id = 0

Many thanks in anticipation

Si

4

1 に答える 1

9

TL;DR:

A report_event.subject_id == 0 usually is the result of either an ignored user agent, or an explicitely excluded route triggering an event which normally would have been logged by Magento.

See app/code/core/Mage/Log/etc/config.xml:

<config>
    <global>
        <!-- : -->
        <ignoredModules>
            <entities>
                <install/>
                <adminhtml/>
                <admin/>
            </entities>
        </ignoredModules>
        <ignore_user_agents>
            <google1>Googlebot/1.0 (googlebot@googlebot.com http://googlebot.com/)</google1>
            <google2>Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)</google2>
            <google3>Googlebot/2.1 (+http://www.googlebot.com/bot.html)</google3>
        </ignore_user_agents>
        <!-- : -->
    </global>
</config>

Long answer

To explain why this happens, I need to go into greater detail.

When any Magento controller action is about to be dispatched, a controller_action_predispatch event will be triggered, right before the dispatching of the action actually happens.

Having another look at app/code/core/Mage/Log/etc/config.xml:

<config>
    <frontend>
        <events>
            <controller_action_predispatch>
                <observers>
                    <log>
                        <class>log/visitor</class>
                        <method>initByRequest</method>
                    </log>
                </observers>
            </controller_action_predispatch>
            <!-- : -->
        </events>
    </frontend>
</config>

shows, that the Mage_Log module defines an observer for the controller_action_predispatch event, represented by the method Mage_Log_Model_Visitor::initByRequest():

public function initByRequest($observer)
{
    if ($this->_skipRequestLogging || $this->isModuleIgnored($observer)) {
        return $this;
    }

    $this->setData($this->_getSession()->getVisitorData());
    $this->initServerData();

    if (!$this->getId()) {
        $this->setFirstVisitAt(now());
        $this->setIsNewVisitor(true);
        $this->save();
    }
    return $this;
}

The property $this->_skipRequestLogging will be true, when the user agent sending the current request matches one of the <ignored_user_agents /> (GoogleBot).

The method $this->isModuleIgnored() returns only true, if the request route matches one of the <ignoredModules /> (that is install/, adminhtml/ or admin/; in EE also api/).

The point is, if one of these both returns true, then the observer immediately exits, that is, the visitor will not be created/saved at all.

Now, to further explain using your catalog_product_view case as example, have a look at another config file, app/code/core/Mage/Reports/etc/config.xml this time:

<config>
    <frontend>
        <events>
            <catalog_controller_product_view>
                <observers>
                    <reports>
                        <class>reports/event_observer</class>
                        <method>catalogProductView</method>
                    </reports>
                </observers>
            </catalog_controller_product_view>
            <!-- : -->
        </events>
    </frontend>
</config>

which defines an observer for catalog_controller_product_view events, represented by the Mage_Reports_Model_Event_Observer::catalogProductView() method:

public function catalogProductView(Varien_Event_Observer $observer)
{
    $productId = $observer->getEvent()->getProduct()->getId();

    Mage::getModel('reports/product_index_viewed')
        ->setProductId($productId)
        ->save()
        ->calculate();

    return $this->_event(Mage_Reports_Model_Event::EVENT_PRODUCT_VIEW, $productId);
}

The last line of this observer calls the _event() method:

protected function _event($eventTypeId, $objectId, $subjectId = null, $subtype = 0)
{
    if (is_null($subjectId)) {
        if (Mage::getSingleton('customer/session')->isLoggedIn()) {
            $customer = Mage::getSingleton('customer/session')->getCustomer();
            $subjectId = $customer->getId();
        }
        else {
            $subjectId = Mage::getSingleton('log/visitor')->getId();
            $subtype = 1;
        }
    }

    $eventModel = Mage::getModel('reports/event');
    $storeId    = Mage::app()->getStore()->getId();
    $eventModel
        ->setEventTypeId($eventTypeId)
        ->setObjectId($objectId)
        ->setSubjectId($subjectId)
        ->setSubtype($subtype)
        ->setStoreId($storeId);
    $eventModel->save();

    return $this;
}

Have a look at the else block, especially this line:

$subjectId = Mage::getSingleton('log/visitor')->getId();

When a visitor doesn't gets created/saved at all, because of an ignored user agent, or an excluded route, then $subjectId will be null.

Since the table column subject_id is defined as NOT NULL (see app/code/core/Mage/Reports/sql/reports_setup SQL scripts), 0 will finally be saved.

Thats because of the Data Type Default Values of MySQL.

于 2012-06-06T17:43:52.263 に答える