How to configure and adapt Aimeos based shops as developer
Forum rules: Always add your Aimeos and PHP version as well as your environment (Linux/Mac/Win)
#2463 by aimeos
02 Feb 2016, 11:10
You could either extend the user/customer table including the item and manager (inherit from the standard classes to save code) or you can reference attribute items via the list table if you need the data in the HTML client. The list reference items itself have a "config" field (stored as JSON) too.
#5928 by mohal_04
02 Apr 2018, 06:01
obayesshelton wrote:Hi,

Is it possible and if so how do I add a new property to a customer?

Thanks


Hi,

Were you able to extend customer class? I am stuck at extending product class but having difficulties. Can you look at my code and help me?

Item/Myproject.php:

Code: Select allnamespace Aimeos\MAdmin\Product\Item;
 
class Myproject extends Standard
{
    private $myvalues;
 
    public function __construct( array $values, ... )
    {
        parent::__construct( $values, ... )
        $this->myvalues = $values;
    }
 
    public function getMyId()
    {
        if( isset( $this->myvalues['myid'] ) ) {
            return (string) $this->myvalues['myid'];
        }
        return '';
    }
 
    public function setMyId( $val )
    {
        if( (string) $val !== $this->getMyId() )
        {
            $this->values['myid'] = (string) $myid;
            $this->setModified();
        }
        return $this;
    }
 
    public function fromArray( array $list )
    {
        $unknown = [];
        $list = parent::fromArray( $list );
 
        foreach( $list as $key => $value )
        {
            switch( $key )
            {
                case 'myid': $this->setMyId( $value ); break;
                default: $unknown[$key] = $value;
            }
        }
 
        return $unknown;
    }
 
    public function toArray( $private = false )
    {
        $list = parent::toArray( $private );
 
        if( $private === true ) {
            $list['myid'] = $this->getMyId();
        }
 
        return $list;
    }
}


Manager/Myproject.php

Code: Select allnamespace Aimeos\MAdmin\Product\Manager;
 
class Myproject extends Standard
{
    private $searchConfig = array(
        'product.oldcode'=> array(
            'code'=>'product.oldcode',
            'internalcode'=>'mpro."oldcode"',
            'label'=>'Product oldcode',
            'type'=> 'string', // integer, float, etc.
            'internaltype'=> \Aimeos\MW\DB\Statement\Base::PARAM_STR, // _INT, _FLOAT, etc.
        ),
    );
 
    public function saveItem( \Aimeos\MShop\Common\Item\Iface $item, $fetch = true )
    {
        // a modified copy of the code from the parent class
        // extended by a bind() call and updated bind positions (first parameter)
    }
 
    public function getSearchAttributes( $withsub = true )
    {
        $list = parent::getSearchAttributes( $withsub );
        foreach( $this->searchConfig as $key => $fields ) {
            $list[$key] = new \Aimeos\MW\Criteria\Attribute\Standard( $fields );
        }
        return $list;
    }
 
    protected function createItemBase( array $values = [] /* , ... */ )
    {
        return new \Aimeos\MShop\Product\Item\Myproject( $values /* , ... */ );
    }
}


This is the directory structure of my files:

./ext/10buckonly/lib/custom/src/MAdmin/Product/Item

Thanks!
#5933 by aimeos
03 Apr 2018, 07:47
You have to implement the saveItem() and createItemBase() methods by copying them from the Standard class and modify them accordingly for your new value. Also adapt the SQL statements for fetch and store the new value.
#5937 by mohal_04
03 Apr 2018, 09:36
aimeos wrote:You have to implement the saveItem() and createItemBase() methods by copying them from the Standard class and modify them accordingly for your new value. Also adapt the SQL statements for fetch and store the new value.


Hi,

I have rewritten my code 3 times and now the situation is this... I am able to display value in my extra field but it is not saving in the DB and there are no errors :(. Please, look at my code and guide me!

./ext/myextension/lib/custom/setup/default/schema/product.php
Code: Select allreturn array(
   'table' => array(
      'mshop_product' => function ( \Doctrine\DBAL\Schema\Schema $schema ) {

         // $table = $schema->createTable( 'mshop_price' );
         $table = $schema->getTable( 'mshop_product' );

         $table->addColumn( 'oldcode', 'string', array( 'length' => 32 ) );

         $table->addIndex( array( 'siteid', 'oldcode' ), 'idx_msproty_sid_oldcode' );

         return $schema;
      }
   )
);


./ext/myextension/lib/custom/src/MShop/Product/Item/Myproject.php
Code: Select allnamespace Aimeos\MShop\Product\Item;
 
class Myproject extends Standard
{
    private $myvalues;
 
    public function __construct(array $values)
    {
        parent::__construct($values);
        $this->myvalues = $values;
    }
 
    public function getOldCode()
    {
        if( isset( $this->myvalues['product.oldcode'] ) ) {
            return (string) $this->myvalues['product.oldcode'];
        }
        return '';
    }
 
    public function setOldCode( $oldcode )
    {
        if ((string) $oldcode !== $this->getOldCode()) {
            // exit("<br />616");
            $this->myvalues['product.oldcode'] = (string) $oldcode;
            $this->setModified();
        }
        return $this;
    }
 
    public function fromArray(array $list)
    {
        $unknown = [];
        $list = parent::fromArray($list);

        foreach ($list as $key => $value) {
            switch ($key) {
                case 'product.oldcode':
                    $this->setOldCode($value);
                    break;
                default:
                    $unknown[$key] = $value;
            }
        }
        // exit("<br />617");
        return $unknown;
    }
 
    public function toArray( $private = false )
    {
        $list = parent::toArray( $private );
 
        if( $private === true ) {
            $list['product.oldcode'] = $this->getOldCode();
        }
 
        return $list;
    }
}


./ext/myextension/lib/custom/src/MShop/Product/Manager/Myproject.php
Code: Select allnamespace Aimeos\MShop\Product\Manager;
 
class Myproject extends Standard
{
    private $searchConfig = array(
        'product.oldcode'=> array(
            'code'=>'product.oldcode',
            'internalcode'=>'mpro."oldcode"',
            'label'=>'Product oldcode',
            'type'=> 'string', // integer, float, etc.
            'internaltype'=> \Aimeos\MW\DB\Statement\Base::PARAM_STR, // _INT, _FLOAT, etc.
        ),
    );
 
    public function saveItem(\Aimeos\MShop\Common\Item\Iface $item, $fetch = true)
    {
        $iface = '\\Aimeos\\MShop\\Product\\Item\\Iface';
        if (! ($item instanceof $iface)) {
            throw new \Aimeos\MShop\Product\Exception(sprintf('Object is not of required type "%1$s"', $iface));
        }

        if (!$item->isModified()) {
            return $item;
        }

        $context = $this->getContext();

        $dbm = $context->getDatabaseManager();
        $dbname = $this->getResourceName();
        $conn = $dbm->acquire( $dbname );

        try {
            $id = $item->getId();
            $date = date('Y-m-d H:i:s');
            if ($id === null) {
                $path = 'mshop/product/manager/standard/insert';
            } else {
                $path = 'mshop/product/manager/standard/update';
            }
            $stmt = $this->getCachedStatement($conn, $path);

            $stmt->bind(1, $item->getTypeId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT);
            $stmt->bind(2, $context->getLocale()->getSiteId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT);
            $stmt->bind(3, $item->getCode());
            $stmt->bind(4, $item->getLabel());
            $stmt->bind(5, json_encode($item->getConfig()));
            $stmt->bind(6, $item->getDateStart());
            $stmt->bind(7, $item->getDateEnd());
            $stmt->bind(8, $item->getStatus(), \Aimeos\MW\DB\Statement\Base::PARAM_INT);
            $stmt->bind(9, $date); // mtime
            $stmt->bind(10, $context->getEditor());
            $stmt->bind(11, $item->getTarget());
            $stmt->bind(12, $item->getOldCode());

            if( $id !== null ) {
                $stmt->bind( 13, $id, \Aimeos\MW\DB\Statement\Base::PARAM_INT );
                $item->setId( $id ); //so item is no longer modified
            } else {
                $stmt->bind( 13, $date ); // ctime
            }

            $stmt->execute()->finish();

            if( $id === null && $fetch === true )
            {
                $path = 'mshop/product/manager/standard/newid';
                $item->setId( $this->newId( $conn, $path ) );
            }

            $dbm->release( $conn, $dbname );

        } catch (\Exception $e) {
            $dbm->release( $conn, $dbname );
            throw $e;
        }
        return $item;
    }
 
    public function getSearchAttributes( $withsub = true )
    {
        $list = parent::getSearchAttributes( $withsub );
        foreach( $this->searchConfig as $key => $fields ) {
            $list[$key] = new \Aimeos\MW\Criteria\Attribute\Standard( $fields );
        }
        return $list;
    }
 
    protected function createItemBase(array $values = [], array $listitems = [],
        array $refItems = [], array $propertyItems = [])
    {
        return new \Aimeos\MShop\Product\Item\Myproject($values, $listitems, $refItems, $propertyItems);
    }
}


and

./ext/myextension/lib/custom/config/mshop.php
Code: Select allreturn [
    'product' => [
        'manager' => [
            'name' => 'Myproject',
            'standard' => [
            'insert' => array(
               'ansi' => '
                  INSERT INTO "mshop_product" (
                     "typeid", "siteid", "code", "label", "config", "start", "end",
                     "status", "mtime", "editor", "target", "ctime", "oldcode"
                  ) VALUES (
                     ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
                  )
               '
            ),
            'update' => array(
               'ansi' => '
                  UPDATE "mshop_product"
                  SET "typeid" = ?, "code" = ?, "label" = ?, "status" = ?,
                     "start" = ?, "end" = ?, "config" = ?, "mtime" = ?, "editor" = ?, "target" = ?, "oldcode" = ?
                  WHERE "siteid" = ? AND "id" = ?
               '
            ),
            'search' => array(
               'ansi' => '
                  SELECT mpro."id" AS "product.id", mpro."siteid" AS "product.siteid",
                     mpro."typeid" AS "product.typeid", mpro."code" AS "product.code",
                     mpro."label" AS "product.label", mpro."config" AS "product.config",
                     mpro."start" AS "product.datestart", mpro."end" AS "product.dateend",
                     mpro."status" AS "product.status", mpro."ctime" AS "product.ctime",
                     mpro."mtime" AS "product.mtime", mpro."editor" AS "product.editor",
                     mpro."target" AS "product.target",
                     mpro."oldcode" AS "product.oldcode"
                  FROM "mshop_product" AS mpro
                  :joins
                  WHERE :cond
                  GROUP BY mpro."id", mpro."siteid", mpro."typeid", mpro."code",
                     mpro."label", mpro."config", mpro."start", mpro."end",
                     mpro."status", mpro."ctime", mpro."mtime", mpro."editor",
                     mpro."target", mpro."oldcode"
                     /*-columns*/ , :columns /*columns-*/
                  /*-orderby*/ ORDER BY :order /*orderby-*/
                  LIMIT :size OFFSET :start
               '
            ),
            'count' => array(
               'ansi' => '
                  SELECT COUNT(*) AS "count"
                  FROM (
                     SELECT DISTINCT mpro."id"
                     FROM "mshop_product" AS mpro
                     :joins
                     WHERE :cond
                     LIMIT 10000 OFFSET 0
                  ) AS list
               '
            ),
            'newid' => array(
               'db2' => 'SELECT IDENTITY_VAL_LOCAL()',
               'mysql' => 'SELECT LAST_INSERT_ID()',
               'oracle' => 'SELECT mshop_product_seq.CURRVAL FROM DUAL',
               'pgsql' => 'SELECT lastval()',
               'sqlite' => 'SELECT last_insert_rowid()',
               'sqlsrv' => 'SELECT SCOPE_IDENTITY()',
               'sqlanywhere' => 'SELECT @@IDENTITY',
            ),
            ],
        ],
    ],
];


Everything seems fine but still I am unable to save value for my custom field, i.e. oldcode.

Thanks!
#5939 by mohal_04
03 Apr 2018, 11:49
Finally, I have done it! Thanks to Almighty Allah! Writing my full code here for others like me.

./ext/myextension/lib/custom/setup/default/schema/product.php
Code: Select allreturn array(
   'table' => array(
      'mshop_product' => function ( \Doctrine\DBAL\Schema\Schema $schema ) {

         // $table = $schema->createTable( 'mshop_price' );
         $table = $schema->getTable( 'mshop_product' );

         $table->addColumn( 'oldcode', 'string', array( 'length' => 32 ) );

         $table->addIndex( array( 'siteid', 'oldcode' ), 'idx_msproty_sid_oldcode' );

         return $schema;
      }
   )
);


./ext/myextension/lib/custom/src/MShop/Product/Item/Myproject.php
Code: Select allnamespace Aimeos\MShop\Product\Item;
 
class Myproject extends Standard
{
    private $myvalues;
 
    public function __construct(array $values)
    {
        parent::__construct($values);
        $this->myvalues = $values;
    }
 
    public function getOldCode()
    {
        if( isset( $this->myvalues['product.oldcode'] ) ) {
            return (string) $this->myvalues['product.oldcode'];
        }
        return '';
    }
 
    public function setOldCode( $oldcode )
    {
        if ((string) $oldcode !== $this->getOldCode()) {
            // exit("<br />616");
            $this->myvalues['product.oldcode'] = (string) $oldcode;
            $this->setModified();
        }
        return $this;
    }
 
    public function fromArray(array $list)
    {
        $unknown = [];
        $list = parent::fromArray($list);

        foreach ($list as $key => $value) {
            switch ($key) {
                case 'product.oldcode':
                    $this->setOldCode($value);
                    break;
                default:
                    $unknown[$key] = $value;
            }
        }
        // exit("<br />617");
        return $unknown;
    }
 
    public function toArray( $private = false )
    {
        $list = parent::toArray( $private );
 
        if( $private === true ) {
            $list['product.oldcode'] = $this->getOldCode();
        }
 
        return $list;
    }
}


./ext/myextension/lib/custom/src/MShop/Product/Manager/Myproject.php
Code: Select allnamespace Aimeos\MShop\Product\Manager;
 
class Myproject extends Standard
{
    private $searchConfig = array(
        'product.oldcode'=> array(
            'code'=>'product.oldcode',
            'internalcode'=>'mpro."oldcode"',
            'label'=>'Product oldcode',
            'type'=> 'string', // integer, float, etc.
            'internaltype'=> \Aimeos\MW\DB\Statement\Base::PARAM_STR, // _INT, _FLOAT, etc.
        ),
    );
 
    public function saveItem(\Aimeos\MShop\Common\Item\Iface $item, $fetch = true)
    {
        $iface = '\\Aimeos\\MShop\\Product\\Item\\Iface';
        if (! ($item instanceof $iface)) {
            throw new \Aimeos\MShop\Product\Exception(sprintf('Object is not of required type "%1$s"', $iface));
        }

        if (!$item->isModified()) {
            return $item;
        }

        $context = $this->getContext();

        $dbm = $context->getDatabaseManager();
        $dbname = $this->getResourceName();
        $conn = $dbm->acquire( $dbname );

        try {
            $id = $item->getId();
            $date = date('Y-m-d H:i:s');
            if ($id === null) {
                $path = 'mshop/product/manager/standard/insert';
            } else {
                $path = 'mshop/product/manager/standard/update';
            }
            $stmt = $this->getCachedStatement($conn, $path);

            $stmt->bind(1, $item->getOldCode());
            $stmt->bind( 2, $item->getTypeId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
            $stmt->bind( 3, $item->getCode() );
            $stmt->bind( 4, $item->getLabel() );
            $stmt->bind( 5, $item->getStatus(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
            $stmt->bind( 6, $item->getDateStart() );
            $stmt->bind( 7, $item->getDateEnd() );
            $stmt->bind( 8, json_encode( $item->getConfig() ) );
            $stmt->bind( 9, $date ); // mtime
            $stmt->bind( 10, $context->getEditor() );
            $stmt->bind( 11, $item->getTarget() );
            $stmt->bind( 12, $context->getLocale()->getSiteId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );

            if( $id !== null ) {
                $stmt->bind( 13, $id, \Aimeos\MW\DB\Statement\Base::PARAM_INT );
                $item->setId( $id ); //so item is no longer modified
            } else {
                $stmt->bind( 13, $date ); // ctime
            }
            $stmt->execute()->finish();
            if( $id === null && $fetch === true )
            {
                $path = 'mshop/product/manager/standard/newid';
                $item->setId( $this->newId( $conn, $path ) );
            }

            $dbm->release( $conn, $dbname );
        } catch (\Exception $e) {
            $dbm->release( $conn, $dbname );
            throw $e;
        }
        return $item;
    }
 
    public function getSearchAttributes( $withsub = true )
    {
        $list = parent::getSearchAttributes( $withsub );
        foreach( $this->searchConfig as $key => $fields ) {
            $list[$key] = new \Aimeos\MW\Criteria\Attribute\Standard( $fields );
        }
        return $list;
    }
 
    protected function createItemBase(array $values = [], array $listitems = [],
        array $refItems = [], array $propertyItems = [])
    {
        return new \Aimeos\MShop\Product\Item\Myproject($values, $listitems, $refItems, $propertyItems);
    }
}


and

./ext/myextension/lib/custom/config/mshop.php
Code: Select allreturn [
    'product' => [
        'manager' => [
            'name' => 'Myproject',
            'standard' => [
            'insert' => array(
               'ansi' => '
                  INSERT INTO "mshop_product" (
                     "oldcode", "typeid", "code", "label", "status", "start", "end",
                     "config", "mtime", "editor", "target", "siteid", "ctime"
                  ) VALUES (
                     ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
                  )
               '
            ),
            'update' => array(
               'ansi' => '
                  UPDATE "mshop_product"
                  SET "oldcode" = ?, "typeid" = ?, "code" = ?, "label" = ?, "status" = ?,
                     "start" = ?, "end" = ?, "config" = ?, "mtime" = ?, "editor" = ?, "target" = ?
                  WHERE "siteid" = ? AND "id" = ?
               '
            ),
            'search' => array(
               'ansi' => '
                  SELECT mpro."id" AS "product.id", mpro."siteid" AS "product.siteid",
                     mpro."typeid" AS "product.typeid", mpro."code" AS "product.code",
                     mpro."label" AS "product.label", mpro."config" AS "product.config",
                     mpro."start" AS "product.datestart", mpro."end" AS "product.dateend",
                     mpro."status" AS "product.status", mpro."ctime" AS "product.ctime",
                     mpro."mtime" AS "product.mtime", mpro."editor" AS "product.editor",
                     mpro."target" AS "product.target",
                     mpro."oldcode" AS "product.oldcode"
                  FROM "mshop_product" AS mpro
                  :joins
                  WHERE :cond
                  GROUP BY mpro."id", mpro."siteid", mpro."typeid", mpro."code",
                     mpro."label", mpro."config", mpro."start", mpro."end",
                     mpro."status", mpro."ctime", mpro."mtime", mpro."editor",
                     mpro."target", mpro."oldcode"
                     /*-columns*/ , :columns /*columns-*/
                  /*-orderby*/ ORDER BY :order /*orderby-*/
                  LIMIT :size OFFSET :start
               '
            ),
            'count' => array(
               'ansi' => '
                  SELECT COUNT(*) AS "count"
                  FROM (
                     SELECT DISTINCT mpro."id"
                     FROM "mshop_product" AS mpro
                     :joins
                     WHERE :cond
                     LIMIT 10000 OFFSET 0
                  ) AS list
               '
            ),
            'newid' => array(
               'db2' => 'SELECT IDENTITY_VAL_LOCAL()',
               'mysql' => 'SELECT LAST_INSERT_ID()',
               'oracle' => 'SELECT mshop_product_seq.CURRVAL FROM DUAL',
               'pgsql' => 'SELECT lastval()',
               'sqlite' => 'SELECT last_insert_rowid()',
               'sqlsrv' => 'SELECT SCOPE_IDENTITY()',
               'sqlanywhere' => 'SELECT @@IDENTITY',
            ),
            ],
        ],
    ],
];


OK now trick here is to keep your field at the first position. Official documentation also has it mentioned but I learned it the hard way.

public function saveItem( \Aimeos\MShop\Common\Item\Iface $item, $fetch = true )
{
// a modified copy of the code from the parent class
// extended by a bind() call and updated bind positions (first parameter)
}


So, as you can see me Manager class and configuration file, I have "oldcode" at the first position. The position does matter.

Code: Select all$stmt->bind(1, $item->getOldCode());
            $stmt->bind( 2, $item->getTypeId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
            $stmt->bind( 3, $item->getCode() );
            $stmt->bind( 4, $item->getLabel() );
            $stmt->bind( 5, $item->getStatus(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );
            $stmt->bind( 6, $item->getDateStart() );
            $stmt->bind( 7, $item->getDateEnd() );
            $stmt->bind( 8, json_encode( $item->getConfig() ) );
            $stmt->bind( 9, $date ); // mtime
            $stmt->bind( 10, $context->getEditor() );
            $stmt->bind( 11, $item->getTarget() );
            $stmt->bind( 12, $context->getLocale()->getSiteId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT );


Code: Select all'insert' => array(
               'ansi' => '
                  INSERT INTO "mshop_product" (
                     "oldcode", "typeid", "code", "label", "status", "start", "end",
                     "config", "mtime", "editor", "target", "siteid", "ctime"
                  ) VALUES (
                     ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
                  )
               '
            ),
            'update' => array(
               'ansi' => '
                  UPDATE "mshop_product"
                  SET "oldcode" = ?, "typeid" = ?, "code" = ?, "label" = ?, "status" = ?,
                     "start" = ?, "end" = ?, "config" = ?, "mtime" = ?, "editor" = ?, "target" = ?
                  WHERE "siteid" = ? AND "id" = ?
               '
            ),


Thanks!
#5952 by aimeos
04 Apr 2018, 22:07
The __construct() method of your product item is wrong because it doesn't accept the list items, ref items and property items you pass in createItemBase() of your manager. These data also have to be passed to the parent constructor in your product item class (parent::__construct( $values, $listItems, ... ))
#5955 by mohal_04
05 Apr 2018, 06:23
aimeos wrote:The __construct() method of your product item is wrong because it doesn't accept the list items, ref items and property items you pass in createItemBase() of your manager. These data also have to be passed to the parent constructor in your product item class (parent::__construct( $values, $listItems, ... ))


Thank you buddy! You saved my day!!! I almost pulled out all my hairs :)

I posted my question here https://aimeos.org/help/post5945.html#p5945 also.

It was due to same reason.

Thanks!
#5963 by mohal_04
06 Apr 2018, 03:05
aimeos wrote:The __construct() method of your product item is wrong because it doesn't accept the list items, ref items and property items you pass in createItemBase() of your manager. These data also have to be passed to the parent constructor in your product item class (parent::__construct( $values, $listItems, ... ))


Hi,

I am tired of Aimeos Laravel Package. Daily I have to fix a new issue! Anyhow, the problem now I am facing is that... I created an extension and followed this https://aimeos.org/docs/Developers/Library/Extend_managers_items document to extend Item and Manager, to add an extra field in Basic section. See screen-shot below:

new_field.jpg
Old SKU field
new_field.jpg (62.97 KiB) Viewed 640 times


It took me few days to figure out the whole thing but it is working fine now. Next, I want to do the same with Price section of Product edit form. I want to add "Minimum Advertised Price" field to Price section. See screen-shot below:

ma_price.jpg
Min Ads Price
ma_price.jpg (88.08 KiB) Viewed 640 times


And I thought the steps for this are also same. So, here is my code (after code, I have described my problem).

Item Class
./ext/myext/lib/custom/src/MShop/Price/Item/Custompricefields.php
Code: Select allnamespace Aimeos\MShop\Price\Item;
 
class Custompricefields extends Standard
{
    private $myvalues;
 
    public function __construct(array $values, array $listItems, array $refItems)
    {
        parent::__construct($values, $listItems, $refItems);
        $this->myvalues = $values;
    }
 
    public function getMinimumAdvertisedPrice()
    {
        if (isset($this->myvalues['price.minimumadvertisedprice'])) {
            return (string) $this->myvalues['price.minimumadvertisedprice'];
        }
        return '';
    }
 
    public function setMinimumAdvertisedPrice($minimumadvertisedprice)
    {
        if ((string) $minimumadvertisedprice !== $this->getMinimumAdvertisedPrice()) {
            $this->myvalues['price.minimumadvertisedprice'] = (string) $minimumadvertisedprice;
            $this->setModified();
        }
        return $this;
    }
 
    public function fromArray(array $list)
    {
        $unknown = [];
        $list = parent::fromArray($list);

        foreach ($list as $key => $value) {
            switch ($key) {
                case 'price.minimumadvertisedprice':
                    $this->setMinimumAdvertisedPrice($value);
                    break;
                default:
                    $unknown[$key] = $value;
            }
        }
        return $unknown;
    }
 
    public function toArray($private = false)
    {
        $list = parent::toArray($private);
        if ($private === true) {
            $list['price.minimumadvertisedprice'] = $this->getMinimumAdvertisedPrice();
        }
        return $list;
    }
}


Manager Class
./ext/myext/lib/custom/src/MShop/Price/Manager/Custompricefields.php
Code: Select allnamespace Aimeos\MShop\Price\Manager;
 
class Custompricefields extends Standard
{
    private $searchConfig = array(
        'price.minimumadvertisedprice' => array(
            'code' => 'price.minimumadvertisedprice',
            'internalcode' => 'mpri."minimumadvertisedprice"',
            'label' => 'Minimum Advertised Price',
            'type' => 'float', // integer, string, etc.
            'internaltype' => \Aimeos\MW\DB\Statement\Base::PARAM_FLOAT, // _INT, _STR, etc.
        )
    );
 
    public function saveItem(\Aimeos\MShop\Common\Item\Iface $item, $fetch = true)
    {
        $iface = '\\Aimeos\\MShop\\Price\\Item\\Iface';
        if( !( $item instanceof $iface ) ) {
            throw new \Aimeos\MShop\Price\Exception( sprintf( 'Object is not of required type "%1$s"', $iface ) );
        }

        if( !$item->isModified() ) {
            return $item;
        }

        $context = $this->getContext();

        $dbm = $context->getDatabaseManager();
        $dbname = $this->getResourceName();
        $conn = $dbm->acquire( $dbname );

        try
        {
            $id = $item->getId();
            $date = date( 'Y-m-d H:i:s' );

            if ($id === null) {
                $path = 'mshop/price/manager/standard/insert';
            } else {
                $path = 'mshop/price/manager/standard/update';
            }

            $stmt = $this->getCachedStatement($conn, $path);

            $stmt->bind(1, $item->getMinimumAdvertisedPrice());
            $stmt->bind(2, $item->getTypeId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT);
            $stmt->bind(3, $item->getCurrencyId());
            $stmt->bind(4, $item->getDomain());
            $stmt->bind(5, $item->getLabel());
            $stmt->bind(6, $item->getQuantity(), \Aimeos\MW\DB\Statement\Base::PARAM_INT);
            $stmt->bind(7, $item->getValue());
            $stmt->bind(8, $item->getCosts());
            $stmt->bind(9, $item->getRebate());
            $stmt->bind(10, $item->getTaxRate());
            $stmt->bind(11, $item->getStatus(), \Aimeos\MW\DB\Statement\Base::PARAM_INT);
            $stmt->bind(12, $date); //mtime
            $stmt->bind(13, $context->getEditor());
            $stmt->bind(14, $context->getLocale()->getSiteId(), \Aimeos\MW\DB\Statement\Base::PARAM_INT);
            if ($id !== null) {
                $stmt->bind(15, $id, \Aimeos\MW\DB\Statement\Base::PARAM_INT);
                $item->setId($id);
            } else {
                $stmt->bind(15, $date); //ctime
            }
            $stmt->execute()->finish();
            if ($id === null && $fetch === true) {
                $path = 'mshop/price/manager/standard/newid';
                $item->setId($this->newId($conn, $path));
            }
            $dbm->release($conn, $dbname);
        } catch(\Exception $e) {
            $dbm->release($conn, $dbname);
            throw $e;
        }
        return $item;
    }
 
    public function getSearchAttributes($withsub = true)
    {
        $list = parent::getSearchAttributes($withsub);
        foreach ($this->searchConfig as $key => $fields) {
            $list[$key] = new \Aimeos\MW\Criteria\Attribute\Standard($fields);
        }
        return $list;
    }
 
    protected function createItemBase(array $values = [], array $listitems = [], array $refItems = [])
    {
        return new \Aimeos\MShop\Price\Item\Custompricefields($values, $listitems, $refItems);
    }
}



And configuration file:

./ext/myext/lib/custom/config/mshop.php
Code: Select allreturn [
    'product' => [
        'manager' => [
            'name' => 'Myproject',
            'standard' => [
            'insert' => array(
               'ansi' => '
                  INSERT INTO "mshop_product" (
                     "countryoforigin", "oldcode", "typeid", "code", "label", "status", "start", "end",
                     "config", "mtime", "editor", "target", "siteid", "ctime"
                  ) VALUES (
                     ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
                  )
               '
            ),
            'update' => array(
               'ansi' => '
                  UPDATE "mshop_product"
                  SET "countryoforigin" = ?, "oldcode" = ?, "typeid" = ?, "code" = ?, "label" = ?, "status" = ?,
                     "start" = ?, "end" = ?, "config" = ?, "mtime" = ?, "editor" = ?, "target" = ?
                  WHERE "siteid" = ? AND "id" = ?
               '
            ),
            'search' => array(
               'ansi' => '
                  SELECT mpro."id" AS "product.id", mpro."siteid" AS "product.siteid",
                     mpro."typeid" AS "product.typeid", mpro."code" AS "product.code",
                     mpro."label" AS "product.label", mpro."config" AS "product.config",
                     mpro."start" AS "product.datestart", mpro."end" AS "product.dateend",
                     mpro."status" AS "product.status", mpro."ctime" AS "product.ctime",
                     mpro."mtime" AS "product.mtime", mpro."editor" AS "product.editor",
                     mpro."target" AS "product.target",
                     mpro."oldcode" AS "product.oldcode",
                     mpro."countryoforigin" AS "product.countryoforigin"
                  FROM "mshop_product" AS mpro
                  :joins
                  WHERE :cond
                  GROUP BY mpro."id", mpro."siteid", mpro."typeid", mpro."code",
                     mpro."label", mpro."config", mpro."start", mpro."end",
                     mpro."status", mpro."ctime", mpro."mtime", mpro."editor",
                     mpro."target", mpro."oldcode", mpro."countryoforigin"
                     /*-columns*/ , :columns /*columns-*/
                  /*-orderby*/ ORDER BY :order /*orderby-*/
                  LIMIT :size OFFSET :start
               '
            ),
            'count' => array(
               'ansi' => '
                  SELECT COUNT(*) AS "count"
                  FROM (
                     SELECT DISTINCT mpro."id"
                     FROM "mshop_product" AS mpro
                     :joins
                     WHERE :cond
                     LIMIT 10000 OFFSET 0
                  ) AS list
               '
            ),
            'newid' => array(
               'db2' => 'SELECT IDENTITY_VAL_LOCAL()',
               'mysql' => 'SELECT LAST_INSERT_ID()',
               'oracle' => 'SELECT mshop_product_seq.CURRVAL FROM DUAL',
               'pgsql' => 'SELECT lastval()',
               'sqlite' => 'SELECT last_insert_rowid()',
               'sqlsrv' => 'SELECT SCOPE_IDENTITY()',
               'sqlanywhere' => 'SELECT @@IDENTITY',
            ),
            ],
        ],
    ],
    'price' => [
        'manager' => [
            'name' => 'Custompricefields',
            'standard' => [
            'insert' => array(
               'ansi' => '
                  INSERT INTO "mshop_price" (
                     "minimumadvertisedprice", "typeid", "currencyid", "domain", "label",
                     "quantity", "value", "costs", "rebate", "taxrate",
                     "status", "mtime", "editor", "siteid", "ctime"
                  ) VALUES (
                     ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
                  )
               '
            ),
            'update' => array(
               'ansi' => '
                  UPDATE "mshop_price"
                  SET "minimumadvertisedprice" = ?, "typeid" = ?, "currencyid" = ?, "domain" = ?, "label" = ?,
                     "quantity" = ?, "value" = ?, "costs" = ?, "rebate" = ?,
                     "taxrate" = ?, "status" = ?, "mtime" = ?, "editor" = ?
                  WHERE "siteid" = ? AND "id" = ?
               '
            ),
            'search' => array(
               'ansi' => '
                  SELECT mpri."id" AS "price.id", mpri."siteid" AS "price.siteid",
                     mpri."typeid" AS "price.typeid", mpri."currencyid" AS "price.currencyid",
                     mpri."domain" AS "price.domain", mpri."label" AS "price.label",
                     mpri."quantity" AS "price.quantity", mpri."value" AS "price.value",
                     mpri."costs" AS "price.costs", mpri."rebate" AS "price.rebate",
                     mpri."taxrate" AS "price.taxrate", mpri."status" AS "price.status",
                     mpri."mtime" AS "price.mtime", mpri."editor" AS "price.editor",
                     mpri."ctime" AS "price.ctime",
                     mpri."minimumadvertisedprice" AS "price.minimumadvertisedprice"
                  FROM "mshop_price" AS mpri
                  :joins
                  WHERE :cond
                  GROUP BY mpri."id", mpri."siteid", mpri."typeid", mpri."currencyid",
                     mpri."domain", mpri."label", mpri."quantity", mpri."value",
                     mpri."costs", mpri."rebate", mpri."taxrate", mpri."status",
                     mpri."mtime", mpri."editor", mpri."ctime", mpri."minimumadvertisedprice" /*-columns*/ , :columns /*columns-*/
                  /*-orderby*/ ORDER BY :order /*orderby-*/
                  LIMIT :size OFFSET :start
               '
            ),
            'count' => array(
               'ansi' => '
                  SELECT COUNT(*) AS "count"
                  FROM (
                     SELECT DISTINCT mpri."id"
                     FROM "mshop_price" AS mpri
                     :joins
                     WHERE :cond
                     LIMIT 10000 OFFSET 0
                  ) AS list
               '
            ),
            'newid' => array(
               'db2' => 'SELECT IDENTITY_VAL_LOCAL()',
               'mysql' => 'SELECT LAST_INSERT_ID()',
               'oracle' => 'SELECT mshop_price_seq.CURRVAL FROM DUAL',
               'pgsql' => 'SELECT lastval()',
               'sqlite' => 'SELECT last_insert_rowid()',
               'sqlsrv' => 'SELECT SCOPE_IDENTITY()',
               'sqlanywhere' => 'SELECT @@IDENTITY',
            ),
            ],
        ],
    ],
];


That was all the code. Now, the problem is this that nothing happens. Value of my "Old SKU" field is saving and showing but value of "Minimum Advertised Price" field is neither saving nor showing. I am under the impression that Aimeos Package is not even registering/reading my second Manager, i.e. "Custompricefields."

Can you go through my code and see what am I doing wrong? Do I have to create separate configuration file for Price Section? BTW, I did make a separate file name "iprice.php" inside "config" directory but still same issue.

Please, help! I tried to explain my problem as much as I could but still if you need to check other stuff in the code then let me know.

Thanks!