Sylius: How to sort product by variant.sku - sylius

I would like to sort the products by its sku. How would that be possible ?
I tried to add in ProductRepository.php:
...
$queryBuilder = $this->getCollectionQueryBuilder();
$queryBuilder
->innerJoin('product.taxons', 'taxon')
->innerJoin('product.variants', 'variant')
->andWhere('taxon = :taxon')
->setParameter('taxon', $taxon)
;
foreach ($criteria as $attributeName => $value) {
$queryBuilder
->andWhere('product.'.$attributeName.' IN (:'.$attributeName.')')
->setParameter($attributeName, $value)
;
}
$queryBuilder->orderBy('variant.sku');
...
but got:
Cannot select distinct identifiers from query with LIMIT and ORDER BY
on a column from a fetch joined to-many association. Use output
walkers.

Finally what I did: Sorted the products just before output in a custom twig function:
macros.html.twig
{% set products = skusort(products) %}
In my SkusortExtenstion.php (as of PHP 5.3)
$product->getIterator()->uasort(function($a, $b){
return $a->getMasterVariant()->getSku() > $b->getMasterVariant()->getSku();
});
return $product;
Was afraid of performance issue as there's a lot of products but seems to be very fast.

Another way is to reload method getPaginator() of class Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository. In that case we must instantinate DoctrineORMAdapter with $useOutputWalkers flag (the latest constructor argument).
So, put the folowing code in your ProductRepository.php:
/**
* {#inheritdoc}
*/
public function getPaginator(QueryBuilder $queryBuilder)
{
return new Pagerfanta(new DoctrineORMAdapter($queryBuilder, true, true));
}

Related

getProduct()->getTag() return null, when it should return tags associated to the Product

In my project, we have products that has tag called serviceItem. Those item with that tag when ordered should be separated by the quantity into individuals order.
It issue is that getTags() returns null, and getTagIds gets "Call to a member function getTagIds() on null" when it gets to the next loop.
Is there a reason for why getTags() returns null?
private function transformOrderLines(OrderEntity $order): array
{
/**
* TODO: If we need to send advanced prices,
* the price value of the the lines array should be changed to caldulate the advanced price,
* with the built in quantity calculator
*/
$lines = [];
foreach ($order->getLineItems() as $orderLine) {
$hasDsmServiceItemTag = $orderLine->getProduct()->getTags();
$lines[] = [
'name' => $orderLine->getLabel(),
'sku' => substr($orderLine->getProduct()->getProductNumber(), 0, 19),
'price' => (string) ($orderLine->getProduct()->getPrice()->first()->getNet()
* $order->getCurrencyFactor()), //gets original price, calculates factor
'quantity' => (string) $orderLine->getQuantity()
];
}
$shipping = $this->transformShipping($order);
if ($shipping) {
$lines = array_merge($lines, $shipping);
}
return $lines;
}`
I also tried $orderLine->getProduct()->getTags()->getName() it also return "Call to a member function getTags() on null"
The problem is wherever the $order is fetched from the DB the orderLineItem.product.tag association is not included in the criteria.
For performance reasons shopware does not lazily load all association when you access them on entities, but you have to exactly define which associations should be included when you fetch the entities from the database.
For the full explanation take a look at the docs.

How to get lineItems.product option value

I want to make a json field of an order to our API. The issue is, that it can't find productNumber.
I've made search of an order with the association:
$this->context = $context;
$criteria = new Criteria([$orderId]);
$criteria->addAssociation(OrderExtension::DSM_INTEGRATION_ORDER);
$criteria->addAssociation('addresses');
$criteria->addAssociation('billingAddress.country');
$criteria->addAssociation('transactions.paymentMethod');
$criteria->addAssociation('deliveries.shippingMethod');
$criteria->addAssociation('deliveries.shippingOrderAddress.country');
$criteria->addAssociation('lineItems.product');
$criteria->addAssociation('lineItems.product.tags');
$criteria->addAssociation('lineItems.product.options');
$criteria->addAssociation('orderCustomer.customer');
$result = $this->orderRepository->search($criteria, $context);
However, the result has no productNumber, when I receive the type "customized-products"
enter image description here
it use uses OrderEntity.
I want the productNumber, when the order is a type "customized-products". I expect, the association is something like "lineItems.product.customized_product", but I have yet to find the correct one.
Note. We use "productOswag_customized_products_templateptions"
To retrieve the product number starting from the order entity, via the order line items, you would have to proceed similar to this:
$criteria = new Criteria();
$criteria->addAssociation('lineItems.product');
$result = $this->orderRepository->search($criteria, $context);
/** #var OrderEntity|null $order */
$order = $result->first();
/** #var OrderLineItemCollection|null $lineItems */
$lineItems = $order->getLineItems();
/** #var OrderLineItemEntity|null $lineItem */
$lineItem = $lineItems->first();
/** #var ProductEntity|null $product */
$product = $lineItem->getProduct();
$productNumber = $product->getProductNumber();
Note the getters might return null at any point, e.g. due to the product having been deleted in the meanwhile or the line item being a discount, so add some checks for that case.

Typo3 9.5 - Custom flexform ordering, wrong backquotes in sql

i have an custom extension, where you can select the different entries at the backend, to show them at the list view. I have a custom sorting at my backend, but the system always sort them Descending.
I implemented an "orderBy" function, which doesnt work, because the system uses wrong backspaces.
My code looks like this:
I call the sort function in my "findByUid($uid)" function like this:
$query->setOrderings($this->orderByKey('uid', $uidArray));
protected function orderByKey($key, $uidlist) {
$order = array();
foreach ($uidlist as $uid) {
//$order["$key=$uid"] = \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING;
$order["$key=$uid"] = "ASC";
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($order);
}
return $order;
}
The result at the sql query is:
ORDER BY `tx_MYEXTENSION_domain_model_FIELD`.`uid=3` DESC
But it must be:
ORDER BY `tx_MYEXTENSION_domain_model_FIELD`.`uid` = 3 DESC
Is there a way to change this?
After a lot of search, I found this solution on an stackoverflow entry:
$ids = explode(',',$this->settings['entries'])
foreach($ids as $key => $id){
$entries[$id] = $this->entriesRepository->findByUid($id);
}
This code snippet has to be intergrated at the controller.
For me its working.

Laravel 5.5, Display news data from two tables

I am new to laravel and I experience some trouble. I try to obtain data stored in two different tables and display them:
News.php (model)
public static function Data($category) {
$perPage = config('var.news.perPage');
if ($category) {
$news = News::orderBy('id', 'desc')->where('category', $category)->SimplePaginate($perPage);
} else {
$news = News::orderBy('id', 'desc')->SimplePaginate($perPage);
}
return $news;
}
This is how I grab all data from News table which struct is:
id, title, body, created_at updated_at, created_by, updated_by, category
The category column contains values separated by comma, e.g. 1,2,3,4
Now, I have another table, News_Cat which has id, name columns.
In another method I try to grab the filters names against values stored in category column of News table
public static function getFilterNames($id) {
$filters = DB::table('News_Cat')
->select('News_Cat.name as name')
->leftJoin('News', DB::raw('CAST(News_Cat.id as nvarchar)'), DB::raw('ANY(SELECT(News.category))'))
->where('News.id', $id)
->get();
return $filters;
}
However, it completely does not work. What I try to achieve is to display filter name in view.blade as 'name' value for specified filter from News_Cat
#if($news->count())
#foreach($news as $article)
<a href="{{ route('news.show', $article->id) }}" class="item angled-bg" data-filters="{{ $filters }}">
<div class="row">
So as result I would get e.g. data-filters="news, update, hot, latest"> instead data-filters="1,2,3,4">
Thank you
You should use eloquent!
In your News Model
public function getFiltersAttribute(){
$categories = explode(',', $this->category);
return implode(', ', NewsCat::find($categories)->pluck('name')->toArray());
}
then in your view :
{{ $article->filters }}
will output news, update, hot, latest
BUT
You should use a pivot table between your categories and your news, it would be much easier.
This method can't allow you to eager load the relationship and make a request for each news
If you can't change your database structure, I can propose you this:
In the boot method of your AppServiceProvider:
Config::set('tags', NewsCat::all());
THEN
public function getFiltersAttribute(){
$categories = explode(',' $this->category);
return implode(', ', config('tags')->whereIn('id', $categories)->pluck('name')->toArray());
}
MANY TO MANY METHOD
I am using laravel naming convention for the table :
news, categories_news (the pivot), and categories
You will have 2 models : New and Category
In your New Model
public function categories(){
return $this->belongsToMany(Category::class)
}
in your Category Model :
public function news(){
return $this->belongsToMany(New::class);
}
if you are not using laravel naming conventions, you will have to customize these raltionship like this : https://laravel.com/docs/5.5/eloquent-relationships#many-to-many

How to get all products of a Shopify shop?

In my theme development, I don't find the way to get all the products of my shop.
Although, I can retrieve all the collections with the variable collections (exemple: {% for c in collections %}).
Check this url: https://help.shopify.com/en/themes/customization/collections/change-catalog-page
Like magic... all your products...
Get all products at once or to run a query(API Request) for all products in shopify store :
using this app is more managed -> https://github.com/phpish/shopify_private_app-skeleton so, my solution below is based on this app or you can relate the solution with your solution as well
<?php
session_start();
require __DIR__.'/vendor/autoload.php';
use phpish\shopify;
require __DIR__.'/conf.php';
$shopify = shopify\client(SHOPIFY_SHOP, SHOPIFY_APP_API_KEY, SHOPIFY_APP_PASSWORD, true);
try
{
$products = $shopify('GET /admin/products/count.json', array('published_status'=>'published'));
$totalproducts = $shopify('GET /admin/products/count.json', array('published_status'=>'published'));
$limit = 50;
$totalpage = ceil($totalproducts/$limit);
for($i=1; $i<=$totalpage; $i++){
$products = $shopify('GET /admin/products.json?'.$limit.'=50&page='.$i, array('published_status'=>'published'));
foreach($products as $product){
//do anything at once for all the products in store
}
}
}
catch (shopify\ApiException $e)
{
//
}
Summary : The idea is to retrieve with page=x as parameter. after calculating the number of pages we will have with specified limit i.e 50 at one time fetch.