Sylius: Change ordering of products/taxonomies, etc

Created on 7 Jan 2015  ยท  24Comments  ยท  Source: Sylius/Sylius

I could not find any discussion regarding this topic, but i think it would be useful to be able to device the order, products or other entities are displayed in frontend. Any thoughts?

Feature

Most helpful comment

You can now order products in taxon! ๐ŸŽ‰ ๐Ÿ’ฅ

All 24 comments

I'll have to implement this feature into a sylius project, i'm currently working on. If its appreciated, I'd prepare a PR afterwards.

This is my proposed solution:
As Sylius already uses DoctrineExtensions, i'll add a SortableInterface to the SyliusResource component. This than could be extended by all kind of models like the ProductInterface.
Output in Frontend could than be sorted according to this changes. still have to think about, how to implement this into the Backend to make it user friendly.

I have to start this feature during the next couple of days. Please provide your thought and let me know, if i should bother to prepare a PR.

@madc IMO the SortableInterface should be added in TaxonomyBundle or CoreBundle, instead of SyliusResourceBundle.

SyliusResourceBundle doesn't have dependency to DoctrineExtensions right now.

The ResourceBundle contains SoftDeletableInterface and TimestampableInterface, which sound like DoctrineExtensions to me. But you're right, there seems to be no direct relation. Do you know, how they are handled? I think, SortableInterface should be implemented quite similar.

@madc IMO I would put it in CoreBundle. Let's wait for @pjedrzejewski's feedback first, I cannot make the call. You don't even know does Sylius want this in Core or not.

I implemented sorting for OptionValue (size) but never had the need to sort taxon and products.

Do you think, any code of your implementation could help me? how did you solve the sorting in backend?

We just added a position field to OptionValue, and then let JS do the rest..

https://gist.github.com/kayue/40c189a8713e31febba9

For products we also have a position field, and the default value is the publish time in timestamp. Admin can change the ordering by changing the timestamp.

SortableInterface is too complicated.

The way i see it (after browsing through the code a bit):

  • SortableInterface in Resource component containing a position field
  • gedmo:sortable in ProductBundle product.orm.xml, TaxonomyBundle taxonomy.orm.xml,...
  • extend SortableInterface in the models
  • Frontend: Sort product and taxonomy listings by position (maybe configurable in config.yml?)
  • Backend: Up/Down arrow before/after edit & delete icon in list view (and maybe a numeric input in edit view).

I'm probably missing something, but sounds doable to me. Would be great to get some feedback from core devs.

Sorting products and taxons is doable and quite simple, sorting products within a catagory differently is a bit bigger task. But I'd be more than happy to start small and make it better as we iterate. :) @madc PR? :dancer:

I'll take some time the next couple of days and see what i've got by the end of the week.

I've started a PR at #2357 and could need some intput. Thanks.

Just writing down some thought about sorting products:

The main problem is, that products can have multiple taxons and therefor multiple positions (one per taxon). The sorting ui for the enduser could be done similar to taxons (up-/down arrows, see #2357)

What would have to be done:

  • Add a position field to the sylius_product_taxon table; use product_id and taxon_id as SortableGroup (multiple SortableGroups possible? If not, taxon_id should be enough)
  • The backend would have to be restructured, as there is currently no view that shows products grouped by taxon.
  • Sort products by taxon and position from sylius_product_taxon (in frontend and backend)

Edit: There is a product view by taxon: administration/taxonomies/{taxonomyId}/taxons/{taxonId}/products. I think the handling of taxons and products in backend should be seriously rethought.

Add a position field to the sylius_product_taxon table; use product_id and taxon_id 
as SortableGroup (multiple SortableGroups possible? If not, taxon_id should be enough)

As Doctrine doesn't allow to overwrite the relation type of a mapped super class, we have to removed this relation and create a new ProductTaxon entity with a "position" attribute to manage the sortable behavior. Have I missed something?

I've already successfully implemented the sorting for products via a TaxonProduct entity and it works quite well. The reason, I didn't prepare a PR is simple because this issue and my previous PR for sorting taxons (#2357) did not receive proper feedback.

Good news ! Could you give me some clue about how you managed the TaxonProduct and override the relation ?
Thanks

It is pretty simple actually. I just overwrite the sylius config in app/config/config.yml, which looks something like this:

sylius_product:
    classes:
        product:
            model: Shop\ExtendBundle\Entity\Product
            repository: Shop\ExtendBundle\Entity\ProductRepository

sylius_taxonomy:
    classes:
        taxon:
            model: Shop\ExtendBundle\Entity\Taxon
            repository: Shop\ExtendBundle\Doctrine\ORM\TaxonRepository

Then i'm able to connect the products and taxons via a TaxonProduct entity.

Product.php

    protected $taxons;

    /**
     * @ORM\OneToMany(targetEntity="TaxonProduct", mappedBy="product", cascade={"all"})
     *
     */
    protected $tp;

   // Followed by all the getter/setter

TaxonProduct.php

namespace Shop\ExtendBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Sylius\Component\Core\Model\Product as SyliusCoreProduct;
use Sylius\Component\Product\Model\Product as SyliusProduct;
use Gedmo\Mapping\Annotation as Gedmo;


/**
 * @ORM\Entity()
 * @ORM\Table(name="sylius_taxon_product")
 * @ORM\HasLifecycleCallbacks()
 */
class TaxonProduct
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * Taxon
     *
     * @ORM\ManyToOne(targetEntity="Shop\ExtendBundle\Entity\Taxon", inversedBy="tp")
     * @Gedmo\SortableGroup
     */
    protected $taxon;

    /**
     * Product
     *
     * @ORM\ManyToOne(targetEntity="Shop\ExtendBundle\Entity\Product", fetch="EAGER", inversedBy="tp")
     */
    protected $product;

    /**
     * Product position.
     *
     * @ORM\Column(type="integer")
     * @Gedmo\SortablePosition
     *
     * @var integer
     */
    protected $position;


    /**
     * {@inheritdoc}
     */
    public function getTaxon()
    {
        return $this->taxon;
    }

    /**
     * {@inheritdoc}
     */
    public function setTaxon($taxon)
    {
        $this->taxon = $taxon;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getProduct()
    {
        return $this->product;
    }

    /**
     * {@inheritdoc}
     */
    public function setProduct($product)
    {
        $this->product = $product;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getPosition()
    {
        return $this->position;
    }

    /**
     * {@inheritdoc}
     */
    public function setPosition($position)
    {
        $this->position = $position;

        return $this;
    }

    public function moveUp()
    {
        if ($this->position != 0) {
            $this->position--;
        }
    }
    public function moveDown()
    {
        $this->position++;
    }
}

As said, I didn't clean the code up, but hope it helps!

Hello,

Thanks a lot !
I'm working on it.
I'll inform you about this work.

Regards
Seb

2015-06-22 17:42 GMT+02:00 Matthias Esterl [email protected]:

It is pretty simple actually. I just overwrite the sylius config in
app/config/config.yml, which looks something like this:

sylius_product:
classes:
product:
model: Shop\ExtendBundle\Entity\Product
repository: Shop\ExtendBundle\Entity\ProductRepository

sylius_taxonomy:
classes:
taxon:
model: Shop\ExtendBundle\Entity\Taxon
repository: Shop\ExtendBundle\Doctrine\ORM\TaxonRepository

Then i'm able to connect the products and taxons via a TaxonProduct entity.

Product.php

protected $taxons;

/**
 * @ORM\OneToMany(targetEntity="TaxonProduct", mappedBy="product", cascade={"all"})
 *
 */
protected $tp;

// Followed by all the getter/setter

TaxonProduct.php

namespace Shop\ExtendBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Sylius\Component\Core\Model\Product as SyliusCoreProduct;
use Sylius\Component\Product\Model\Product as SyliusProduct;
use Gedmo\Mapping\Annotation as Gedmo;

/**

  • @ORM\Entity()
  • @ORM\Table(name="sylius_taxon_product")
  • @ORM\HasLifecycleCallbacks()
    _/
    class TaxonProduct
    {
    /_*

    • @var integer

      *

    • @ORM\Column(name="id", type="integer")

    • @ORM\Id

    • @ORM\GeneratedValue(strategy="AUTO")

      */

      private $id;

/**

  • Taxon
    *
  • @ORM\ManyToOne(targetEntity="Shop\ExtendBundle\Entity\Taxon", inversedBy="tp")
  • @Gedmo\SortableGroup
    */
    protected $taxon;

/**

  • Product
    *
  • @ORM\ManyToOne(targetEntity="Shop\ExtendBundle\Entity\Product", fetch="EAGER", inversedBy="tp")
    */
    protected $product;

/**

  • Product position.
    *
  • @ORM\Column(type="integer")
  • @Gedmo\SortablePosition
    *
  • @var integer
    */
    protected $position;

/**

  • {@inheritdoc}
    */
    public function getTaxon()
    {
    return $this->taxon;
    }

/**

  • {@inheritdoc}
    */
    public function setTaxon($taxon)
    {
    $this->taxon = $taxon;
return $this;
}

/**

  • {@inheritdoc}
    */
    public function getProduct()
    {
    return $this->product;
    }

/**

  • {@inheritdoc}
    */
    public function setProduct($product)
    {
    $this->product = $product;
return $this;
}

/**

  • {@inheritdoc}
    */
    public function getPosition()
    {
    return $this->position;
    }

/**

  • {@inheritdoc}
    */
    public function setPosition($position)
    {
    $this->position = $position;
return $this;
}

public function moveUp()
{
if ($this->position != 0) {
$this->position--;
}
}
public function moveDown()
{
$this->position++;
}
}

As said, I didn't clean the code up, but hope it helps!

โ€”
Reply to this email directly or view it on GitHub
https://github.com/Sylius/Sylius/issues/2312#issuecomment-114157749.

Note that @pjedrzejewski just commented on my PR, mentioning that taxonomies proberply beeing removed in a future milestone.

is it functionnal ?

Pretty sure, it's not working right out of the box anymore. This snippets are nearly a year old and I haven't used Sylius since then.

Hi @madc, hi @pjedrzejewski,

could you tell me if this feature exists on Sylius just now?

Actually, i'm overriding the Administration backend and i'm looking to create functionality, but i'd like to know if there is something ready to get as example!

My target is to order products under a taxon, with a page similar to /taxons/{id}/products page.

Thanks a lot,
Dan

@DanPhyxius nothing like that in core and probably this is something for future versions, but can be easily implemented. You would simply need to introduce a new entity, which will replace the relation between products and taxons. :)

Ok @pjedrzejewski, thank you for your answer! :)

We're working on it!

Great job guys! ๐Ÿ‘

You can now order products in taxon! ๐ŸŽ‰ ๐Ÿ’ฅ

Was this page helpful?
0 / 5 - 0 ratings

Related issues

javiereguiluz picture javiereguiluz  ยท  3Comments

inssein picture inssein  ยท  3Comments

reyostallenberg picture reyostallenberg  ยท  3Comments

Chrysweel picture Chrysweel  ยท  3Comments

mezoni picture mezoni  ยท  3Comments