Element (Mage_Sales_Model_Order) o tym samym identyfikatorze „X” już istnieje

12

Po utworzeniu przesyłki w obszarze administracyjnym Magento w var/reportfolderze (po domyślnej stronie awarii Magento) pojawia się następujący błąd podczas przeglądania strony siatki zamówień administracyjnych:

Item (Mage_Sales_Model_Order) with the same id "1234" already exist

Mogę pozbyć się tego błędu, dodając klauzulę DISTINCT do selektora obiektów varien w app/code/core/Mage/Eav/Model/Entity/Collection/Abstact.phplinii 662. Jednak tak naprawdę nie chcę tego robić z kilku powodów (śmiertelnie powolne zapytania, edycja podstawowych plików itp.).

Jaki jest najlepszy sposób na rozwiązanie tego problemu przy jednoczesnym zachowaniu integralności danych. Czy powinienem usunąć zamówienie? Byłbym wdzięczny za wszelkie konstruktywne opinie, szczególnie na temat tego, co spowodowałoby ten konflikt. Dzięki.

-- edytować --

Oto ślad pełnego stosu dla jasności / wskazania mojej głupoty:

a:5:{i:0;s:67:"Item (Mage_Sales_Model_Order) with the same id "1234" already exist";i:1;s:4829:"#0 lib/Varien/Data/Collection/Db.php(576): Varien_Data_Collection->addItem(Object(Mage_Sales_Model_Order))
#1 app/code/core/Mage/Adminhtml/Block/Widget/Grid.php(533): Varien_Data_Collection_Db->load()
#2 app/code/core/Mage/Adminhtml/Block/Sales/Order/Grid.php(61): Mage_Adminhtml_Block_Widget_Grid->_prepareCollection()
#3 app/code/core/Mage/Adminhtml/Block/Widget/Grid.php(626): Mage_Adminhtml_Block_Sales_Order_Grid->_prepareCollection()
#4 app/code/core/Mage/Adminhtml/Block/Widget/Grid.php(632): Mage_Adminhtml_Block_Widget_Grid->_prepareGrid()
#5 app/code/core/Mage/Core/Block/Abstract.php(862): Mage_Adminhtml_Block_Widget_Grid->_beforeToHtml()
#6 app/code/core/Mage/Core/Block/Abstract.php(582): Mage_Core_Block_Abstract->toHtml()
#7 app/code/core/Mage/Core/Block/Abstract.php(526): Mage_Core_Block_Abstract->_getChildHtml('grid', true)
#8 app/code/core/Mage/Adminhtml/Block/Widget/Grid/Container.php(77): Mage_Core_Block_Abstract->getChildHtml('grid')
#9 app/design/adminhtml/default/default/template/widget/grid/container.phtml(36): Mage_Adminhtml_Block_Widget_Grid_Container->getGridHtml()
#10 app/code/core/Mage/Core/Block/Template.php(241): include('/var/www/html/m...')
#11 app/code/core/Mage/Core/Block/Template.php(272): Mage_Core_Block_Template->fetchView('adminhtml/defau...')
#12 app/code/core/Mage/Core/Block/Template.php(286): Mage_Core_Block_Template->renderView()
#13 app/code/core/Mage/Adminhtml/Block/Template.php(81): Mage_Core_Block_Template->_toHtml()
#14 app/code/core/Mage/Adminhtml/Block/Widget/Container.php(308): Mage_Adminhtml_Block_Template->_toHtml()
#15 app/code/core/Mage/Core/Block/Abstract.php(863): Mage_Adminhtml_Block_Widget_Container->_toHtml()
#16 app/code/core/Mage/Core/Block/Text/List.php(43): Mage_Core_Block_Abstract->toHtml()
#17 app/code/core/Mage/Core/Block/Abstract.php(863): Mage_Core_Block_Text_List->_toHtml()
#18 app/code/core/Mage/Core/Block/Abstract.php(582): Mage_Core_Block_Abstract->toHtml()
#19 app/code/core/Mage/Core/Block/Abstract.php(526): Mage_Core_Block_Abstract->_getChildHtml('content', true)
#20 app/design/adminhtml/default/default/template/page.phtml(74): Mage_Core_Block_Abstract->getChildHtml('content')
#21 app/code/core/Mage/Core/Block/Template.php(241): include('/var/www/html/m...')
#22 app/code/core/Mage/Core/Block/Template.php(272): Mage_Core_Block_Template->fetchView('adminhtml/defau...')
#23 app/code/core/Mage/Core/Block/Template.php(286): Mage_Core_Block_Template->renderView()
#24 app/code/core/Mage/Adminhtml/Block/Template.php(81): Mage_Core_Block_Template->_toHtml()
#25 app/code/core/Mage/Core/Block/Abstract.php(863): Mage_Adminhtml_Block_Template->_toHtml()
#26 app/code/core/Mage/Core/Model/Layout.php(555): Mage_Core_Block_Abstract->toHtml()
#27 app/code/core/Mage/Core/Controller/Varien/Action.php(390): Mage_Core_Model_Layout->getOutput()
#28 app/code/core/Mage/Adminhtml/controllers/Sales/OrderController.php(95): Mage_Core_Controller_Varien_Action->renderLayout()
#29 app/code/core/Mage/Core/Controller/Varien/Action.php(419): Mage_Adminhtml_Sales_OrderController->indexAction()
#30 app/code/core/Mage/Core/Controller/Varien/Router/Standard.php(250): Mage_Core_Controller_Varien_Action->dispatch('index')
#31 app/code/core/Mage/Core/Controller/Varien/Front.php(176): Mage_Core_Controller_Varien_Router_Standard->match(Object(Mage_Core_Controller_Request_Http))
#32 app/code/core/Mage/Core/Model/App.php(354): Mage_Core_Controller_Varien_Front->dispatch()
#33 app/Mage.php(683): Mage_Core_Model_App->run(Array)
#34 index.php(71): Mage::run('base', 'website')
#35 {main}";s:3:"url";s:72:"/index.php/admin/sales_order/index/key/0b7375aca52608483edc0cf879bd4361/";s:11:"script_name";s:10:"/index.php";s:4:"skin";s:5:"admin";}
Jongosi
źródło
8
FWIW Nienawidzę tego głupiego błędu i spędziłem więcej czasu, niż chciałbym przyznać, że go debugowałem.
philwinkle
Czy możesz dołączyć zapytanie dotyczące kolekcji lub kod php?
Sukeshini

Odpowiedzi:

10

Dodano coś do kolekcji, co dodaje duplikaty do wyniku zapytania.

Magento robi z wynikiem zapytania, aby wygenerować obiekt z każdego wiersza, a następnie dodać te elementy do kolekcji. Jeśli element już istnieje, błąd jest zgłaszany.

Rozwiązanie: niezależnie od dodanego połączenia sprawdź, czy wynik jest wyraźny.

Jeśli dodasz więcej pól oprócz tych z sales_flat_order, pola te mogą się różnić, dlatego są one filtrowane za pomocą DISTINCT.

Fabian Blechschmidt
źródło
6

Dodaję odpowiedź, ponieważ nie mogłem jeszcze dodać komentarza. Zgadzam się z @fabian - jednak odradzam używanie DISTINCTi GROUP BY, zazwyczaj możesz przefiltrować swoje połączenie do jednego wyraźnego wyniku, jeśli planujesz poprawnie.

Na przykład (wiem, że to trywialny przykład):

Jeśli chcesz odebrać zamówienie za pomocą sales/flat_orderi dołączyłeś do adresu klienta, przechowywane są dwa rekordy adres rozliczeniowy i adres dostawy . Aby rozwiązać ten problem, można określić typ adresu, do którego chcą się przyłączyć.

Brzmi podobnie do twojej sytuacji, z wyjątkiem tego scenariusza.

popiół
źródło
3

Mamy również problem z naszym systemem. Przeanalizowaliśmy problem i znaleźliśmy mój Grid.php(przykład: /namespace/modulename/Block/Adminhtml/Sales/Order/Grid.php)

Znaleźliśmy _prepareCollection()funkcję w Grid.phppliku.

Kodowanie błędów to:

//Error coding
$collection->join(array('payment' => 'sales/order_payment'), 'main_table.entity_id = parent_id', 'method')
            ->getSelect()
            ->where("`payment`.`method` like '%paypal%'");

Rozwiązanie:

//Solution coding
$collection->join(array('payment' => 'sales/order_payment'), 'main_table.entity_id = parent_id', 'method')
            ->getSelect()
            ->where("`payment`.`method` like '%paypal%'")
            ->group('method');

Mamy zastosowanie ->group('value')w funkcji filtrowania. Teraz działa dobrze ... !!!

Sankar_k
źródło
3

Wiem, że to stare pytanie, na które już udzielono odpowiedzi, ale chcę dodać swoją odpowiedź, ponieważ uważam, że mogłoby to pomóc innym w obliczu podobnych problemów. Próbuję wyjaśnić ogólne przyczyny tego rodzaju błędów.

Na początek Mage_Sales_Model_Orderw standardowej instalacji Magento nigdy nie powinien dawać takiego błędu. Podejrzewam więc, że ten błąd jest spowodowany przez rozszerzenie innej firmy (obserwator, metoda przechwytująca, przepisywanie itp.) Lub niewłaściwe dostosowanie kodu, które w pierwszej kolejności uszkodziło dane. Mówiąc o podstawowych komponentach działających „dziwnie”, distinctrozwiązanie nie powinno nawet istnieć, ponieważ dane nigdy nie powinny zostać uszkodzone! Lepiej najpierw napraw dane, niż zmieniając kod.

Podobny problem napotkałem, gdy zbudowałem niestandardowy typ encji EAV i wszystko działało dobrze, dopóki nie edytowałem jednego z encji. W jakiś sposób edycja spowodowała zduplikowanie wartości jednego z atrybutów tekstowych encji, to znaczy dwóch wierszy w tabeli wartości tekstowych dla tego samego atrybutu tej samej encji. Surowe zapytania tylko tabeli custom_entity wyglądały idealnie dobrze bez duplikatów (jak to możliwe? Ograniczenie klucza podstawowego zapewniło już integralność), więc problem był gdzie indziej.

Jak można się już domyślać podczas ładowania kolekcji, z powodu sprzężeń używanych do pobierania wierszy z bazy danych i biorąc pod uwagę, że istnieją dwie takie same wartości tekstowe dla tego samego atrybutu bytu, pobrano dwa wiersze o tej samej entity_idwartości, ale różne value_id.

Zasadniczo, gdy pojawia się taki błąd, należy podejrzewać, że albo dane w bazie danych zostały już uszkodzone, albo że połączenia, które mają miejsce w końcowym zapytaniu, pobiorą z bazy danych dwa prawie dokładne wiersze, powielając unikalny identyfikator kolekcji przedmiotów.

Mam nadzieję że to pomoże.

PS: Jeśli chodzi o powieloną wartość tekstową eav w moim przypadku, sprawdź komentarz Mariusa tutaj http://inchoo.net/magento/creating-an-eav-based-models-in-magento/

adjco
źródło
0

To jest mój kod działa dobrze po tym samym problemie:

    $collection = Mage::getResourceModel('sales/order_grid_collection');
    $prefix = Mage::getConfig()->getTablePrefix();  

    $collection->getSelect()->joinleft(array('order'=> $prefix.'sales_flat_order'),'order.entity_id=main_table.entity_id',array('pdeliverydate'));   

    $collection->getSelect()->joinleft(array('address'=> $prefix.'sales_flat_order_address'),'address.parent_id=main_table.entity_id',array('telephone'))->group('entity_id');

    $this->setCollection($collection);
    return parent::_prepareCollection();

Mam add -> group ('entity_id'), aby rozwiązać problem.

Piotr
źródło
Już zaproponowano 1 rok temu ( magento.stackexchange.com/a/139898/46249 ) ... -1.
sv3n
-1

musisz spróbować zastąpić Mage_Sales_Model_Resource_Order_Grid_Collection::addItemten wyjątek:

<?php
class Fixed_Order_Grid_Collection extends Mage_Sales_Model_Resource_Order_Grid_Collection{

    public function addItem(Varien_Object $item)
    {
        $itemId = $this->_getItemId($item);

        if (!is_null($itemId)) {
            if (isset($this->_items[$itemId])) {
                //throw new Exception('Item ('.get_class($item).') with the same id "'.$item->getId().'" already exist');
            }
            $this->_items[$itemId] = $item;
        } else {
            $this->_addItem($item);
        }
        return $this;
    }
}
class MyCompony_MyExtention_Block_Adminhtml_OrderGrid extends Mage_Adminhtml_Block_Widget_Grid
{
     public function __construct()
    {
        parent::__construct();
        $this->setId('sales_order_grid');
        $this->setUseAjax(true);
        $this->setDefaultSort('created_at');
        $this->setDefaultDir('DESC');
        $this->setSaveParametersInSession(true);
    }
    protected function _getCollectionClass()
    {
        return 'sales/order_grid_collection';
    }

    protected function _prepareCollection()
    {
        $collection = new Fixed_Order_Grid_Collection();
        $select = $collection->getSelect();
        $select->join('sales_flat_order_item AS order_item', 'order_item.order_id=main_table.entity_id','quote_item_id',NULL);
        $select->distinct();
        $this->setCollection($collection);
        return parent::_prepareCollection();
    }
...
Sajjad Shirazy
źródło
1
To nie jest rozwiązanie, ale po prostu sposób na pozbycie się komunikatu o błędzie.
Niels,
1
Błędy zgniatania to nie to samo, co ich naprawianie, rozważ dodanie odrębności do wyniku kolekcji lub pogrupuj zapytanie łączenia według pola.
DWils,