Magento 2 - Category List Sort by Position with Sub Category Not Working - magento2

A little background, I'm trying to do a custom Category listing, but at the moment it seems the Category not being sort as I seen on Admin.
Here's the code that I've done so far
$current_store = $this->_storeManager->getStore();
$root_category_id = $this->_storeManager->getStore()->getRootCategoryId();
$collection = $this->_categoryCollectionFactory->create()
->addAttributeToSelect('*')
->addAttributeToFilter('is_active', 1)
->setStore($current_store);
return $collection->addAttributeToFilter('entity_id', array('nin' => $root_category_id))
->setOrder('position','ASC');
And the result, when I tried to echo its ID is like below
3
10
4
11
5
7
12
8
15
9
13
14
16
6
But, from the Admin, it doesn't reflect the order correctly, below is the figure
The problem that I realize is, that, I have sub category, I tried to echo the query from above code, and then copy-paste it into sql GUI, and I realize, the position is kinda weird but, it does make-sense, because it's a sub category.
Here's the result when I execute the query on sql GUI
So, what I tried to achieve is to sort above result, to reflecting what I set on Admin.
Is there anything that I missed? I'm not sure where to look, since I've been stuck around 1-2 days, not sure what's the proper keyword, almost all keyword I did will arrive to product sort or kind of that, not category sort
Thanks in Advance!

For those who still needs some answer relating to this question, here's the answer
...
$store_categories = $this->_categoryFactory->create();
$store_categories = $store_categories->load($this->_root_category_id)->getChildrenCategories();
foreach ($store_categories as $category) {
//get id
$category_id = $category->getId();
//get category model
$category = $this->getCategoryModel($category_id);
$sub_children = $this->getActiveChildCategories($category);
if (count($sub_children) > 0) {
$sub_categories = $this->getSubCategory($sub_children);
$categories = array_merge($categories, $sub_categories);
} else {
$categories[] = $category;
}
}
...
The _categoryFactory comes from Magento\Catalog\Model\CategoryFactory.
It's pretty much covering what I want, but not really as I expected before, because I think it's not really efficient.
PS - I'm still new on Magento 2, so, if someone else has other answer that might be pretty much like I expect, then, I'm happily change it as Accepted Answer. :)
Goodluck!

Related

Within Where Clause, Nested Case When Statement to return Result with 'OR'

Good afternoon everyone,
I am trying to combine 2 separate function to create a semi-dynamic where clause. Currently I have 3 identical view in my SQL database which are pretty much the same except for the following line pending on what the user state are.
For WA User.
(dbo.JunctionT.ProcessState = 'CDS' )
For VIC User.
(dbo.JunctionT.ProcessState = 'VIC' OR dbo.JunctionT.ProcessState = 'WA')
For NSW User.
(dbo.JunctionT.ProcessState = 'NSW')
Therefore, if the user is from NSW, return results from their user state.. and if the user is from WA then return result where ProcessState is CDS and if the user is from VIC then return result where ProcessState is either VIC or WA.
I have written the following nested case when statement to try and combine these 3 views into 1:
`dbo.JunctionT.ProcessState =
(CASE
WHEN dbo.fnGetReviewState(CURRENT_USER) = 'NSW' THEN 'NSW'
WHEN dbo.fnGetReviewState(CURRENT_USER) = 'WA' THEN 'CDS'
WHEN dbo.fnGetReviewState(CURRENT_USER) = 'VIC' THEN 'VIC OR WA'
END)`
This seems to be working perfectly fine for both NSW and WA users but when I trial it as a VIC user, it returns nothing. I suspect it could be a syntax issue but i have tried the following without much success:
Have tried to use:('VIC OR WA'), ('VIC' OR 'WA'), ['VIC' OR 'WA'], <'VIC' OR 'WA'>
Hoping that someone more knowledgeable is able to show me what it is I am missing or even suggest a better way to complete this dynamic statement. Many many thanks in advance!!
SeanY
Brien is close. This should do the trick:
case
when dbo.JunctionT.ProcessState = 'NSW' and
dbo.fnGetReviewState(CURRENT_USER) = 'NSW' then 1
when dbo.JunctionT.ProcessState = 'CDS' and
dbo.fnGetReviewState(CURRENT_USER) = 'WA' then 1
when dbo.JunctionT.ProcessState in ( 'VIC', 'WA' ) and
dbo.fnGetReviewState(CURRENT_USER) = 'VIC' then 1
else 0
end = 1
'VIC OR WA' is literally "VIC OR WA", that is why there are no rows returning.
dbo.JunctionT.ProcessState would have to equal "VIC OR WA" (this exact/literal string) to return rows.
What you want instead dbo.JunctionT.ProcessState IN ('VIC','WA')
So there is an element of dynamic SQL involved in order to have your CASE statement return exactly what you need.

select option by text in webform

I'm using powershell for completing webform. I have dropdown there and can select it by value:
$dropdown.value = '3236'
It works fine, but I need to select by text. I read this answer and tried this code:
($dropdown | where {$_.innerHTML -eq "sometext"}).Selected = $true
It works too, but because dropdown has too many options (probably several thousands), it takes several minutes to select, which is not acceptable.
How can I improve this?
btw, I use powershell 2.0
Okay, I found solution, maybe it isn't perfect, but I got performance improved in hundreds times, instead several minutes it takes less than second.
I created the following function:
function getValue($innerHTML, $Name)
{
$innerHTML = $innerHTML.Substring($innerHTML.IndexOf($Name) - 11, 10)
return $innerHTML.Substring($innerHTML.IndexOf('=') + 1)
}
Function takes innerHTML of dropdown as string, search for option name and return value instead.
and use function the following way:
$drop.Value = getValue $drop.innerHTML 'somename'

Carbon Difference in Time between two Dates in hh:mm:ss format

I'm trying to figure out how I can take two date time strings that are stored in our database and convert it to a difference in time format of hh:mm:ss.
I looked at diffForHumans, but that does give the format I'd like and returns things like after, ago, etc; which is useful, but not for what I'm trying to do.
The duration will never span days, only a max of a couple hours.
$startTime = Carbon::parse($this->start_time);
$finishTime = Carbon::parse($this->finish_time);
$totalDuration = $finishTime->diffForHumans($startTime);
dd($totalDuration);
// Have: "21 seconds after"
// Want: 00:00:21
I ended up grabbing the total seconds difference using Carbon:
$totalDuration = $finishTime->diffInSeconds($startTime);
// 21
Then used gmdate:
gmdate('H:i:s', $totalDuration);
// 00:00:21
If anyone has a better way I'd be interested. Otherwise this works.
$finishTime->diff($startTime)->format('%H:%I:%S');
// 00:00:21
$start = new Carbon('2018-10-04 15:00:03');
$end = new Carbon('2018-10-05 17:00:09');
You may use
$start->diff($end)->format('%H:%I:%S');
which gives the difference modulo 24h
02:00:06
If you want to have the difference with more than 24h, you may use :
$start->diffInHours($end) . ':' . $start->diff($end)->format('%I:%S');
which gives :
26:00:06
I know this is an old question, but it still tops Google results when searching for this sort of thing and Carbon has added a lot of flexibility on this, so wanted to drop a 2022 solution here as well.
TL;DR - check out the documentation for different/more verbose versions of the diffForHumans method, and greater control over options.
As an example, we needed to show the difference between two Carbon instances (start and end) in hours & minutes, but it's possible they're more than 24 hours apart—in which case the minutes become less valuable/important. We want to exclude the "ago" or Also wanted to join the strings with a comma.
We can accomplish all of that, with the $options passed into diffForHumans, like this:
use Carbon\CarbonInterface;
$options = [
'join' => ', ',
'parts' => 2,
'syntax' => CarbonInterface::DIFF_ABSOLUTE,
];
return $end->diffForHumans($start, $options);
Which will result in values like what's seen in the Duration column:
Hope that's helpful for someone!
You can do it using the Carbon package this way to get the time difference:
$start_time = new Carbon('14:53:00');
$end_time = new Carbon('15:00:00');
$time_difference_in_minutes = $end_time->diffInMinutes($start_time);//you also find difference in hours using diffInHours()

Logical indexing of fields within a structure

I have a structure like so:
Basis.FieldsBasisType.fieldsBasisComponents
There are ~13 components to each basis, including 6 asset class IDs.
So, for example
fieldnames(Basis.SalaryIncrease) =
'Constant'
'AWeight'
'AAssetClassID'
'ATimeLag'
'BWeight'
'BAssetClassID'
'BTimeLag'
'CWeight'
'CAssetClassID'
'CTimeLag'
'DWeight'
'DAssetClassID'
'DTimeLag'
'EWeight'
'EAssetClassID'
'ETimeLag'
'FWeight'
'FAssetClassID'
'FTimeLag'
'cap'
'floor'
Now what I want to do is select all unique asset classes used in any basis. I am really struggling to make this neat though, currently I am using:
basisNames = fieldnames(Basis);
requiredSeries=[];
for i = 1:size(fieldnames(Basis),1)
requiredSeries = [requiredSeries;unique(Basis.(basisNames{i}).AAssetClassID)];
requiredSeries = [requiredSeries;unique(Basis.(basisNames{i}).BAssetClassID)];
requiredSeries = [requiredSeries;unique(Basis.(basisNames{i}).CAssetClassID)];
requiredSeries = [requiredSeries;unique(Basis.(basisNames{i}).DAssetClassID)];
requiredSeries = [requiredSeries;unique(Basis.(basisNames{i}).EAssetClassID)];
requiredSeries = [requiredSeries;unique(Basis.(basisNames{i}).FAssetClassID)];
end
requiredSeries = unique(requiredSeries)
Which is really ugly in my opinion. I want to do some kind of string compare to find 'AssetClassID' within the fields, so something like:
field = fieldnames(Basis.(basisNames{1}));
strfind(field,'AssetClassID');
And then use that cell array to logically index 'field' and just grab the data from 'AssetClassID' fields. But I am stuck on making that work.
~cellfun('isempty',strfind(field,'AssetClassID'))
gets me the logical index, how do I apply that to fields and then use it to get values.
Any ideas would be appreciated, I feel there should be a neat way of doing it and I am missing something. Hardcoding those fieldnames seems short sighted as a solution.
#
Edit: I hate myself.
Sorry folks, I came up with a working variant like moments after posting this, apologies for wasting anyones time!
basisNames = fieldnames(Basis);
for i = 1:size(fieldnames(Basis),1)
field = fieldnames(Basis.(basisNames{i}));
field = cell2mat(field(~cellfun('isempty',strfind(field,'AssetClassID'))));
for j = 1:size(field,1)
requiredSeries = [requiredSeries;unique(Basis.(basisNames{i}).(field(1,:)))];
end
requiredSeries = unique(requiredSeries)
end
I was missing a necessary cell2mat earlier which caused the inability to get it to bloody work. Anyway, I'd always like to hear improvements to that but otherwise you can shut this down.
Sorry folks, I came up with a working variant 30 mins or after posting this, popping it down as an answer as per Michelle's suggestion.
basisNames = fieldnames(Basis);
for i = 1:size(fieldnames(Basis),1)
field = fieldnames(Basis.(basisNames{i}));
field = cell2mat(field(~cellfun('isempty',strfind(field,'AssetClassID'))));
for j = 1:size(field,1)
requiredSeries = [requiredSeries;unique(Basis.(basisNames{i}).(a(1,:)))];
end
requiredSeries = unique(requiredSeries)
end
I was missing a necessary cell2mat earlier which caused the inability to get it to bloody work. Anyway, I'd always like to hear improvements to that but otherwise you ignore this entirely :)

Cassandra: get_range_slices of TimeUUID super column?

I have a schema of Row Keys 1-n. In each row there are a variable number of supercolumns with a TimeUUID 'name'. Im hoping to be able to query this data by a time range.
Two issues have come up:
in KeyRange -> the values that I put in for 'start_key' and 'end_key' are getting misunderstood (for lack of a better term) by Thrift. Experimenting with different groups of values Im not seeing what I expect and often get back something completely unexpected.
Example: my row keys are running from 1-1000 with lots of random gaps. I put start_key = 50 and end_key = 20 .. and I get back rows with keys ranging from 99 to 414.
Example: I have a known row with key = 13. Putting this value into start_key and end_key gives me no results.
Second issue: even when I do get results the 'columns' portion of the 'keyslice' is always empty. I have checked via cassandra-cli and I know there is data.
Im using Perl as follows:
my $slice_range = new Cassandra::SliceRange();
$slice_range->{ start } = create_UUID( UUID::Tiny::UUID_TIME, "2010-12-24 00:00:00" );
$slice_range->{ finish } = create_UUID( UUID::Tiny::UUID_TIME, "2011-12-25 00:00:00" );
my $slice_predicate = new Cassandra::SlicePredicate();
$slice_predicate->{ slice_range } = $slice_range;
my $key_range = new Cassandra::KeyRange();
$key_range->{ start_key } = 13;
$key_range->{ end_key } = 13;
my $result = $client->get_range_slices( $column_parent, $slice_predicate, $key_range, $consistency_level );
print Dumper( $result );
Clearly Im misunderstanding some basic precept.
EDIT: It turns out that the Perl library Im using is not properly documented. The UUID creation was not working as advertised. I opened it up, fixed it, and now its all going a bit more as I was expecting. I can slice my supercolumns by date/time range. Still working on getting the key range portion to work.
http://wiki.apache.org/cassandra/FAQ#range_rp covers why you're not seeing what you expect with key ranges.
You need to specify a SlicePredicate that contains the actual range of what you're trying to select. The default of no column_names and no slice_range will result in the empty columns list that you see.