News:

Support the VirtueMart project and become a member

Main Menu

Can I add a custom field in the 'short by' list?

Started by panoss, September 06, 2016, 19:31:14 PM

Previous topic - Next topic

panoss

I want to add a custom field in the 'short by' list so that I 'll be able to short the products by this field.
Is this possible? How can I do it?
Virtuemart 3.2.4 on Joomla! 3.8.0

panoss

#1
I looked into the code in model 'Product' (class VirtueMartModelProduct).
It's a nightmare, very difficult to add ordering.
A hand of help would be very useful.

Variable $orderBy in function sortSearchListQuery maybe...

Another thought:
1. modify table #__virtuemart_products (that is add my custom field).
2. follow the standard joomla component procedures (read the custom field 's value in PopulateState, set it's value in state, read it's value from the state in function sortSearchListQuery and apply it on $orderBy variable of this function).

What do you think?
Virtuemart 3.2.4 on Joomla! 3.8.0

Jumbo!

You can use "plgVmBeforeProductSearch" trigger which allows you to join new tables in the query and set your desired ordering. You will have to create plugin (vmcustom) and then pass "custom_parent_id" in the input/url to trigger the function.

Check sortSearchListQuery function in VirtueMartModelProduct carefully to learn more.

panoss

#3
Quote from: Jumbo! on September 07, 2016, 22:19:27 PM
You will have to create plugin (vmcustom)
What do you mean here? Something like the code in line 667 of class VirtueMartModelProduct?


JPluginHelper::importPlugin('vmcustom');
$dispatcher = JDispatcher::getInstance();
$dispatcher->trigger('plgVmBeforeProductSearch', array(&$select, &$joinedTables, &$where, &$groupBy, &$orderBy,&$joinLang));


I searched for 'plgVmBeforeProductSearch' in /plugins/vmcustom and I didn't find anything!
Shouldn't I find a function named 'plgVmBeforeProductSearch'?
(forgive my complete ignorance on plugins)

Or literally create a plugin? Of type 'vmcustom'?
Virtuemart 3.2.4 on Joomla! 3.8.0

panoss

Here 's what I did:
I created a plugin named 'sorter' this way:

I copied the folders and files of plugins\vmcustom\textinput.
I made some modifications: textinput.xml -> sorter.xml, textinput.php -> sorter.php etc.
In files like sorter.xml, I replaced 'textinput' with 'sorter'.

I zipped all folders - files and installed it through joomla 's extensions installer, it installed fine!

So now I have 3 plugins of type 'vmcustom':
VM Custom - Customer text input    
VM Custom - Product specification    
VMCustom - sorter

I guess that 's what you meant by 'create plugin (vmcustom)'.

In sorter.php I created a function:
public function plgVmBeforeProductSearch(){
    var_dump('plugin WORKS!!!');
}


In model 'Product' (class VirtueMartModelProduct), in function sortSearchListQuery, I put:
JPluginHelper::importPlugin('vmcustom');
$dispatcher = JDispatcher::getInstance();
$dispatcher->trigger('plgVmBeforeProductSearch', array(&$select, &$joinedTables, &$where, &$groupBy, &$orderBy,&$joinLang));


And the result: 'plugin WORKS!!!

So my plugin works, I...just...don't know how to use it :-[...

What should I do now?
Virtuemart 3.2.4 on Joomla! 3.8.0

GJC Web Design

QuoteIn model 'Product' (class VirtueMartModelProduct), in function sortSearchListQuery, I put:

BeforeProductSearch is already in products.php ~ line 666

if ($this->searchplugin !== 0) {
         JPluginHelper::importPlugin('vmcustom');
         $dispatcher = JDispatcher::getInstance();
         $dispatcher->trigger('plgVmBeforeProductSearch', array(&$select, &$joinedTables, &$where, &$groupBy, &$orderBy,&$joinLang));
      }

so now you have e.g. $groupby & $joinedtables in your plugin you can add to these arrays and return them e.g. the order by one you want etc
GJC Web Design
VirtueMart and Joomla Developers - php developers https://www.gjcwebdesign.com
VM4 AusPost Shipping Plugin - e-go Shipping Plugin - VM4 Postcode Shipping Plugin - Radius Shipping Plugin - VM4 NZ Post Shipping Plugin - AusPost Estimator
Samport Payment Plugin - EcomMerchant Payment Plugin - ccBill payment Plugin
VM2 Product Lock Extension - VM2 Preconfig Adresses Extension - TaxCloud USA Taxes Plugin - Virtuemart  Product Review Component
https://extensions.joomla.org/profile/profile/details/67210
Contact for any VirtueMart or Joomla development & customisation

panoss

#6
I added this code because of:
if ($this->searchplugin !== 0) {
Which prevents the rest of the code from being executed, as it' s always equal to 0.
         
Virtuemart 3.2.4 on Joomla! 3.8.0

GJC Web Design

yes.. was looking at that ..  I have no idea what the intention is for that var

its set in what looks like a block of experiments if group is used.. 

         //          $joinCategory    = false ; //creates error
         //          $joinMf       = false ;   //creates error
         $joinPrice = TRUE;   //Why we set this all the time?
         $this->searchplugin = FALSE;
//          $joinLang = false;

it is initiated in  function populateState ()

$this->searchplugin = vRequest::getInt ('custom_parent_id', 0);

I would try with

$this->searchplugin = TRUE;

just before the plugin call

what ever happens you are going to have to experiment because I have never built or seen a custom search plugin
GJC Web Design
VirtueMart and Joomla Developers - php developers https://www.gjcwebdesign.com
VM4 AusPost Shipping Plugin - e-go Shipping Plugin - VM4 Postcode Shipping Plugin - Radius Shipping Plugin - VM4 NZ Post Shipping Plugin - AusPost Estimator
Samport Payment Plugin - EcomMerchant Payment Plugin - ccBill payment Plugin
VM2 Product Lock Extension - VM2 Preconfig Adresses Extension - TaxCloud USA Taxes Plugin - Virtuemart  Product Review Component
https://extensions.joomla.org/profile/profile/details/67210
Contact for any VirtueMart or Joomla development & customisation

panoss

#8
Ok, I added
$this->searchplugin = true;
just before
if ($this->searchplugin !== 0) {


Quote from: GJC Web Design on September 08, 2016, 10:57:43 AM
so now you have e.g. $groupby & $joinedtables in your plugin you can add to these arrays and return them e.g. the order by one you want etc
In $joinedtables I 'll add a Left Join on the table '#__virtuemart_product_customfields'?

$joinedTables[] = 'LEFT JOIN `#__virtuemart_product_customfields` as pcflds ON p.`virtuemart_product_id` = `pcflds`.`virtuemart_product_id`';

This is tricky, table '#__virtuemart_product_customfields' doesn't have the custom fields' names as fields....
Virtuemart 3.2.4 on Joomla! 3.8.0

panoss

#9
I did it 'hard-coded' as  you can see, for testing purposes of course, and it works!

public function plgVmBeforeProductSearch($select, &$joinedTables, $where, $groupBy, &$orderBy,$joinLan){
        $joinedTables[] = 'LEFT JOIN `#__virtuemart_product_customfields` as pcflds ON p.`virtuemart_product_id` = `pcflds`.`virtuemart_product_id`';

        $orderBy = 'ORDER BY `pcflds`.customfield_value  ASC, `p`.`virtuemart_product_id` ASC';
}


Notice the ampersands: &$joinedTables, &$orderBy
Virtuemart 3.2.4 on Joomla! 3.8.0

panoss

#10
But what if we have two custom fields?
We do no where in the code clear out by which custom field (or fields) we are ordering.

Also, I don't understand the necessity of the plugin.
Why does this code have to be in a plugin and not, simply, in  a function in the model?
Virtuemart 3.2.4 on Joomla! 3.8.0

panoss

#11
BTW (and maybe off topic), in the customfields table (#__virtuemart_product_customfields), I see that fields are added as lines.
This is called Entity-attribute-value, EAV for short.

According to the guys in mySQL forum, in a related question they told me: 'Entity-attribute-value, EAV for short. Nontrivial queries perform abysmally. The only fix is to abandon EAV.'

They 're totally against EAV.

My conclusion (and this is how I finally implemented in my component) is that when you create custom fields, the best way to do it is to add real fields in your customfields table.
(end of the off-topic)
Virtuemart 3.2.4 on Joomla! 3.8.0

GJC Web Design

QuoteWhy does this code have to be in a plugin and not, simply, in  a function in the model?

because installs should be kept up to date..  VM is regularly updated with fixes and new functions..  do you really want to hack the model every time?
That's why we use a plugin structure
GJC Web Design
VirtueMart and Joomla Developers - php developers https://www.gjcwebdesign.com
VM4 AusPost Shipping Plugin - e-go Shipping Plugin - VM4 Postcode Shipping Plugin - Radius Shipping Plugin - VM4 NZ Post Shipping Plugin - AusPost Estimator
Samport Payment Plugin - EcomMerchant Payment Plugin - ccBill payment Plugin
VM2 Product Lock Extension - VM2 Preconfig Adresses Extension - TaxCloud USA Taxes Plugin - Virtuemart  Product Review Component
https://extensions.joomla.org/profile/profile/details/67210
Contact for any VirtueMart or Joomla development & customisation

panoss

I thought that maybe this was the reason, thanks for reassuring me.

I don't know, I have stuck.
How will I make the ordering if the custom fields are two? Or more?
Virtuemart 3.2.4 on Joomla! 3.8.0

panoss

#14
Finally:
$joinedTables[] = 'LEFT JOIN `#__virtuemart_product_customfields` as pcflds ON (p.`virtuemart_product_id` = `pcflds`.`virtuemart_product_id` AND `pcflds`.virtuemart_custom_id=25)';


The '25' is the custom field 's id (field virtuemart_custom_id in table #__virtuemart_customs).
And works fine!


But it 's so strange that VM does not include the custom fields in the sortable fields and I had to do all this...
Virtuemart 3.2.4 on Joomla! 3.8.0