Developers/Library/Access custom properties

From Aimeos documentation

Developers
Other languages:
English 100%


In your customer specific project, you may need extra data e.g. in your customer/user table or in any other domain. Starting with version 2017.10, you can access all custom fields you add or join to an Aimeos table by adapting the used SQL statement only. The fields will be automatically available in the items as magic properties.

You have read-only access to these properties but can't change their values by using the managers. If you need administration capabilities too, you have to extend the existing item and manager and add the required code to get/set the property values and save them to the database!

Extend tables

If you need to store e.g. an arbitrary ID to another system in your customer/user table, you can extend the existing table by adding a new field like described in the article about modifying existing tables. Let's name the new field "someid":

return array(
  'table' => array(
    'mshop_customer' => function ( \Doctrine\DBAL\Schema\Schema $schema ) {
 
        $table = $schema->getTable( 'mshop_customer' );
        $table->addColumn(  'someid', 'varchar', array( 'length' => 32 ) ); 
        return $schema;
    },
  ),
);

Now adapt the SQL statement for retrieving the customer data to:

SELECT mcus."id" AS "customer.id", mcus."siteid" AS "customer.siteid",
	mcus."label" AS "customer.label", mcus."code" AS "customer.code",
	mcus."company" AS "customer.company", mcus."vatid" AS "customer.vatid",
	mcus."salutation" AS "customer.salutation", mcus."title" AS "customer.title",
	mcus."firstname" AS "customer.firstname", mcus."lastname" AS "customer.lastname",
	mcus."address1" AS "customer.address1", mcus."address2" AS "customer.address2",
	mcus."address3" AS "customer.address3", mcus."postal" AS "customer.postal",
	mcus."city" AS "customer.city", mcus."state" AS "customer.state",
	mcus."countryid" AS "customer.countryid", mcus."langid" AS "customer.langid",
	mcus."telephone" AS "customer.telephone", mcus."email" AS "customer.email",
	mcus."telefax" AS "customer.telefax", mcus."website" AS "customer.website",
	mcus."longitude" AS "customer.longitude", mcus."latitude" AS "customer.latitude",
	mcus."birthday" AS "customer.birthday", mcus."status" AS "customer.status",
	mcus."vdate" AS "customer.dateverified", mcus."password" AS "customer.password",
	mcus."ctime" AS "customer.ctime", mcus."mtime" AS "customer.mtime",
	mcus."editor" AS "customer.editor", mcus."someid"
FROM "mshop_customer" AS mcus
:joins
WHERE :cond
GROUP BY mcus."id", mcus."siteid", mcus."label", mcus."code",
	mcus."company", mcus."vatid", mcus."salutation", mcus."title",
	mcus."firstname", mcus."lastname", mcus."address1", mcus."address2",
	mcus."address3", mcus."postal", mcus."city", mcus."state",
	mcus."countryid", mcus."langid", mcus."telephone", mcus."email",
	mcus."telefax", mcus."website", mcus."longitude", mcus."latitude",
	mcus."birthday", mcus."status", mcus."vdate", mcus."password",
	mcus."ctime", mcus."mtime", mcus."editor", mcus."someid"
	/*-columns*/ , :COLUMNS /*columns-*/
/*-orderby*/ ORDER BY :ORDER /*orderby-*/
LIMIT :SIZE OFFSET :START

Note the mcus."someid" that have been added to the SELECT list and GROUP BY clause. Now, every time you retrieve an item from the database using findItem(), getItem() or searchItems(), it will automatically contain the property for the new field. You can access its value via the magic methods __get() and __isset():

$someid = $item->someid;
isset( $item->someid )

Laravel, Symfony and TYPO3 use their own tables for storing customer/user data. To retrieve additional data from their tables, you need to adapt different SQL statements:

Join tables

If you want to join a non-Aimeos table to the product table for example and retrieve their fields too, you only need to adapt the SQL statement for retrieving the product data:

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",
	myt."extra1", myt."extra2"
FROM "mshop_product" AS mpro
JOIN "mytable" AS myt ON mpro."id" = myt."prodid"
: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",
	myt."extra1", myt."extra2"
	/*-columns*/ , :COLUMNS /*columns-*/
/*-orderby*/ ORDER BY :ORDER /*orderby-*/
LIMIT :SIZE OFFSET :START

In this example, we've joined the table "mytable" and added two fields ("extra1" and "extra2") that will be available as properties when using findItem(), getItem() or searchItems():

$extra1 = $item->extra1;
isset( $item->extra1 )

Joining tables does only work on 1:1 relations and you need to add the extra fields in the GROUP BY clause as well. If you have a 1:n relation, you will get the same product item as often as there are records in your table for that product!