Oznámení
Lean Mapper – výchozí řazení v proměnné typu m:belongsToMany
před 6 lety

- svezij
 - Člen | 69
 
Ahojte, nerad přidávám příspěvky do vlákna Lean
Mapper – tenké ORM nad dibi, protože mi přijde, že se tam řeší
důležité věci ohledně Lean Mapperu a nechci tam obtěžovat takovými
maličkostmi. Proto se omlouvám, měl-li bych tento dotaz vložit právě
tam.
Mám entitu výrobku, která obsahuje obrázky výrobku:
/**
 * @property int $id
 * ...
 * @property ProductImage[] $images m:belongsToMany(:product_images)
 * ...
 */
class Product extends \LeanMapper\Entity
{
}
Všechno funguje tak, jak má, ale tabulka product_images
obsahuje sloupec sequence, který je typu „integer“ a udává
řazení obrázků. Jak Lean Mapper „donutit“, aby mi obrázky z tabulky
product_images stahoval do proměnné $images
v pořadí ORDER BY sequence ASC? Tzn.:
Tabulka:
id | product | filename | sequence
----------------------------------
1  | 1       | obr1.jpg | 1
2  | 1       | obr2.jpg | 3
3  | 1       | obr3.jpg | 2
Kód:
$repository = getProductRepository();
$product = $repository->find(1);
foreach ($product->images as $image) {
  echo $image->file . '<br />';
}
Chtěl bych, aby vypsalo:
obr1.jpg
obr3.jpg
obr2.jpg
ale samozřejmě vypíše:
obr1.jpg
obr2.jpg
obr3.jpg
Jak to mám vyřešit? Děkuji :-).
před 6 lety

- svezij
 - Člen | 69
 
Tak zatím jsem to „zvládl“ přes vlastní getter.
/**
 * Getter of images
 *
 * @return ProductImage[]
 */
public function getImages()
{
  $value = array();
  foreach ($this->row->referencing('product_images', 'product_id') as $row) {
    $value[] = new ProductImage($row->referenced('product_images', 'id'));
  }
  usort($value, function($a, $b) {
    return (($a->sequence == $b->sequence) ? 0 : (($a->sequence < $b->sequence) ? -1 : 1));
  });
  return $value;
}
Je to správné řešení, nebo existuje jiné, lepší?
před 6 lety

- Casper
 - Člen | 253
 
Použij filtr.
Entita:
/**
 * @property ProductImage[] $images m:belongsToMany(:product_images) m:filter(sortImages)
 */
class Product extends \LeanMapper\Entity{}
config.neon
services:
    myFilter: Model\Filter\MyFilter
    connection:
        class: LeanMapper\Connection(%database%)
        setup:
            - registerFilter('sortImages', [@myFilter, 'sortImages'])
Filtr:
class MyFilter {
    public function sortImages(\LeanMapper\Fluent $statement){
        $statement->orderBy("sequence ASC");
    }
}
				před 6 lety

- Tharos
 - Člen | 1042
 
Použití filtru je best practice.
Ke Casperovo odpovědi jenom dodám, že filtr může být i obecnější (a univerzálnější) s „natvrdo“ vepsaným parametrem v anotaci, což bych zde asi volil:
/**
 * @property ProductImage[] $images m:belongsToMany(:product_images) m:filter(sort#sequence)
 */
class Product extends \LeanMapper\Entity
{
}
$connection->registerFilter('sort', function(Fluent $statement, $column) {
    $statement->orderBy($column);
});
				před 6 lety

- svezij
 - Člen | 69
 
Ahojte, mockrát děkuji za odpověď, chtěl jsem to takto provést, ale nevím, kde registrovat ten filter. Zkoušel jsem ho registrovat v konstruktoru repozitáře, ale laděnka píše:
Filter with name 'sort' was already registered.
Systém s LeanMapperem spojuji v bootstrap.php:
// LeanMapper connection registration
$configurator->onCompile[] = function($configurator, Nette\Config\Compiler $compiler) {
  $compiler->addExtension('dibi', new LeanMapperConnectionExtension());
};
a třída LeanMapperConnectionExtension se liší od
DibiNette20Extension tím, že volám:
$connection = $container->addDefinition($this->prefix('connection'))
                        ->setClass('LeanMapper\Connection', array($config));
místo:
$connection = $container->addDefinition($this->prefix('connection'))
                        ->setClass('DibiConnection', array($config));
Kde mám tedy zavolat
$connection->registerFilter('sort', function(Fluent $statement, $column) {
    $statement->orderBy($column);
});
?
Ještě jednou moc děkuji.
před 5 lety

- medhi
 - Bronze Partner | 189
 
Také bych se přimlouval za odpověď. Jak v Nette registrovat takový filtr, pokud mám Lean Mapper v configu jako extension?
Díky
Editoval medhi (29. 8. 2014 16:22)
před 5 lety

- Tharos
 - Člen | 1042
 
Ahoj,
já poslední dobou registruji filtry následovně:
<?php
namespace SomeProject\LeanMapper\DI;
use LeanMapper\Connection;
use Nette\DI\CompilerExtension;
use Nette\PhpGenerator\ClassType;
use SomeProject\LeanMapper\IFiltersConfigurator;
/**
 * @author Vojtěch Kohout
 */
class LeanMapperExtension extends CompilerExtension
{
    public function loadConfiguration()
    {
        $container = $this->getContainerBuilder();
        $config = $this->getConfig();
        $useProfiler = isset($config['profiler'])
            ? $config['profiler']
            : class_exists('Tracy\Debugger') && $container->parameters['debugMode'];
        unset($config['profiler']);
        if (isset($config['flags'])) {
            $flags = 0;
            foreach ((array) $config['flags'] as $flag) {
                $flags |= constant($flag);
            }
            $config['flags'] = $flags;
        }
        $connection = $container->addDefinition($this->prefix('connection'))
            ->setClass('LeanMapper\Connection', [$config]);
        if ($useProfiler) {
            $panel = $container->addDefinition($this->prefix('panel'))
                ->setClass('Dibi\Bridges\Tracy\Panel');
            $connection->addSetup([$panel, 'register'], [$connection]);
        }
    }
    /**
     * @param ClassType $class
     */
    public function afterCompile(ClassType $class)
    {
        $initialize = $class->methods['initialize'];
        $initialize->addBody('$this->getByType("' . IFiltersConfigurator::class . '")->setUpFilters($this->getByType("' . Connection::class . '"));');
    }
}
<?php
namespace SomeProject\LeanMapper;
use LeanMapper\Connection;
/**
 * @author Vojtěch Kohout
 */
interface IFiltersConfigurator
{
    function setUpFilters(Connection $connection);
}
<?php
namespace SomeProject\LeanMapper;
use SomeProject\LeanMapper\Query\IQuery;
use SomeProject\LeanMapper\Query\QueryUsingEntityReflection;
use LeanMapper\Connection;
use LeanMapper\Exception\InvalidArgumentException;
use LeanMapper\Fluent;
use LeanMapper\IMapper;
use LeanMapper\Reflection\Property;
/**
 * @author Vojtěch Kohout
 */
class FiltersConfigurator implements IFiltersConfigurator
{
    /**
     * @param Connection $connection
     */
    public function setUpFilters(Connection $connection)
    {
        $connection->registerFilter(...);
    }
}
Možností je vážně celá řada. Mně se líbí, když existuje nějaký
konfigurátor (FiltersConfigurator) a v extenzi, která
Lean Mapper integruje do projektu, se dá velmi pohodlně využít.
Editoval Tharos (2. 9. 2014 23:31)