Make this Magento nested loop better - php

I am trying to get all stores on a Magento shop. By all stores, I mean all stores from all websites. I wrote this code and it works, but I'm a little concerned about the complexity of the nested foreach loop. Please take a look at it and advise me if you think I can do something different.
public function getAllStoresCustom(){
$all_stores = array();
foreach (Mage::app()->getWebsites() as $website) {
foreach ($website->getGroups() as $group) {
$all_stores [] = $group->getStores();
}
}
return $all_stores;
}
I've only found these functions in Magento, so I think I had to use those and this seemed the only combination that worked.
Thanks a lot

Try this:
$allStores = Mage::getModel('core/store')->getCollection();
Then loop through $allStores when needed
foreach ($allStores as $store) {
//do something with $store
}
Notice: You will get a store with id 0. That is the admin store view. If you want all stores without the admin store view use this:
$allStores = Mage::getModel('core/store')->getCollection()->setWithoutDefaultFilter()

foreach() is an incredibly efficient PHP function so you can bet that it is not going to be your slowdown. If you are looking to optimize something then look into the code for the getStores() and getGroups() functions because those are being called within the iterations whereas getWebsites() gets called only once.
If you want more guidance then please feel free to update your question with the contents of those functions.
You may also want to try https://codereview.stackexchange.com/ for more experienced opinions especially since you don't have any specific programming issue/error =)

Related

Is there an easier way to iterate through a list of objects properties in Laravel

I have a Laravel app where I am using a bit of code which feels really unintuitive.
In the code I return a list of objects ($occupied) which all have the the column 'property'. I then go on to create an array of the list of objects 'property's ($occupiedproperty) just to use it in a whereNotIn call.
if ($occupied = Residency::currentResidents()){
// Here is the pointless part //////
$occupiedproperty = array();
foreach ($occupied as $occ) {
array_push($occupiedproperty, $occ->property);
}
///////////////////////////////////
return Property::whereNotIn('id', $occupiedproperty)->get();
}
This code works fine to do the job but creating a new array when I already have a list of objects seems lazy. I tried looking at eloquent's documentation but I couldn't figure this out.
I need to be able to access the 'property' column of $occupied so I can run something like whereNotIn('id', $occupied->property)
Thank you
Can't test it right now, but this should work (it should work even without casting to array the $occupied collection):
$occupiedProperties = array_pluck((array)$occupied, 'property');
It uses the array_pluck() helper method: http://laravel.com/docs/4.2/helpers#arrays

refactoring array looped around another arrary for assignment

I know this is more of PHP problem because of it's loose Typing of arrays but I see this problem all over the place in a project I took over and not sure of the best way to refactor it. Suppose you have two sets of data, both multi dimensional arrays, $results_by_entity and $target_limits and we want to check what the target is foreach result_by_entity so we can set some state
foreach ($results_by_entity AS $result_by_entity) {
foreach ($target_limits AS $target_limit) {
if ($target_limit['activity_id'] == $result_by_entity['activity_id']) {
$result_by_entity->target = $target_limit->quantity;
$result_by_entity->progress = $target_limit->score;
}
}
}
There are a couple of main problems here
1-The data is really strongly tied together, so it is really hard to refactor $results_by_entity into it's own class and $target_limits into it's own class
2-The time taken to process this grows exponentially as the data size grows
I read the Refactoring book by Martin Fowler and it was really helpful but this style of problem doesn't really show up I think mostly because his examples are in JAVA which is strongly typed. The class is super run on so really hard to debug and extend but all the data is so tied together primarily because of these types of loops so not to sure how to solve. Any recommendations would be really appreciated
What you want is to index your data pre-emptively if possible:
$results_index = array();
foreach ($results_by_entity AS $result_by_entity) {
//Index this value
$results_index[$result_by_entity['activity_id']] = $result_by_entity; //Add a & in front if it's a scalar value, but it looks like it's an object in your example
}
foreach ($target_limits AS $target_limit) {
//Find the corresponding activity id in results
if (isset($results_index[$target_limit['activity_id']])) {
$result_by_entity = $results_index[$target_limit['activity_id']];
$result_by_entity->target = $target_limit->quantity;
$result_by_entity->progress = $target_limit->score;
}
}

Maintain item maintenance for a items in a class created by developer using subclass per item

If anyone has an idea, I couldn't think of a better way to phase the question.
I'll try to not make this to complicated an explination.
I'm writing a "quotes" class that is the main class. This class has "overall" functions that preform calculations based on "items" stored in its array. Suffice it to say, the end-developer will call it as $q = new apiQuote/quote().
Then, before it's of any use, the first item must be added and it's properties set so it can do it's "own" calculations. Something like $q->createItem(). Once the item is created with this call, an "item" of the class "item" is added to an array in "quotes" named "items".
The currently editable item, $q->item is always the last one added to the array via the createItem method. Which looks like:
public function createNewItem() {
$this->items[] = new item();
$this->item = $this->items[count($this->items)-1];
}
I added setItem method, whereby the parameter would be an integer representing item index in the array and would set $q->item to the item index chosen. This works, but still seems "not as productive" as I'd like".
What I'm curious about, is if anyone has any suggestions on a better way to go about this. I tried looking for a "cards/deck" php example, but all I could find was array shuffles, which is kinda useless here. I know how to do such associations in .NET and thought this would be just as easy, but I don't have the same property abilities in PHP that I have in a .NET language, thus negating what I'm used to in created this kind of "class/subclass[items]" type structure.
Really I would just like to know if anyone has done anything similar and if I'm doing things to the "best of ability" or if there might be a better way, via PHP, to allow an "end-developer" to call on one main class and create a list "items" based on a subclass that can later be used for methods of the main class?
I really hope this sums it all up well and I havn't gone outside the guidelines of "question asking" here, but I can't think of a better place, other than maybe Code Review to pose such a question and get great developer feed back. If y'all feel I need move it to Code Review, let me know. My main reason for choosing this over CR is this site tends to get faster responses.
Perhaps a view of what I have and what I "might" like to see:
Way it works now
$q = new apiQuote\quote(TRUE);
$q->createNewItem();
$q->item->totalHeight = 100;
$q->item->totalWidth = 250;
...
$q->createNewItem();
$q->item->totalHeight = 300;
$q->item->set_coverage('25%');
...
$q->setItem(1);
$q->item->totalHeight = 250;
...
$q->getTotalsCurv(); // an array to create a graph curve of totals from each item
What I "think" I might like:
$q = new apiQuote\quote(TRUE);
$q->items[] = new apiQuote\item();
$q->items[0]->totalHeight = 100;
$q->items[0]->totalWidth = 250;
...
$q->items[] = new apiQuote\item();
$q->items[1]->totalHeight = 300;
$q->items[1]->set_coverage('25%');
...
$q->items[0]->totalHeight = 250;
...
$q->getTotalsCurv();
However, something like the second idea mean leaving the "items" array public, which could lead to a vast amount of "other" problems as I'm trying to set this whole thing up to be "near dummy proof". Thus the usage of protected variables with specific get/set methods as if they where C# properties.
I think your problem is how to identify an "item" outside of the quote instance. And by using its array index you feel you are going to run into the problems. And you will, when you will try to delete an item. It would successfully invalidate any index already known/stored outside. The simplest patch to it is to give every item a unique ID and store them in the map instead of storing it as a vector.
Also, in your solution item by itself cannot provide you with any helpful information how to access this item in your collection of items (a quote).
public function createNewItem() {
static $counter;
$id = $counter++;
return $this->item = $this->items[$id] = new item($id);
}
public function editItem($id) {
return $this->item = $this->items[$id];
}
public function removeItem($id) {
$this->item = null;
unset($this->item[$id]);
}
Alternatively I recommend you not to reinvent the wheel and take a look here:
http://php.net/manual/en/spl.datastructures.php
and here in specific
http://www.php.net/manual/en/class.splobjectstorage.php
Anything that implements Iterator interface can be iterated with foreach
http://www.php.net/manual/en/class.iterator.php
Ah well you could return the new item from the createItem function.
An equivalent of your .NET example would be to simply return the new item
public function createNewItem() {
$this->items[] = new item();
$this->item = $this->items[count($this->items)-1];
return $this->items[count($this->items)-1];
}
then you could do
$item = $q->createNewItem();
$item->totalHeight = 100;
...
And as you are already adding the new item to the array from within createNewItem so no need for something like $q->add($item);
And to get at any other item you could do a
function getItem($index){
return $this->items[count($this->items)-1];
}
$otheritem = $q->getItem(3);
$otheritem->totalHeight = 100;

What would be the best way to showing nested comment(s)?

To implement this feature I had created a a column replyTo which relates to the comment_id in the same table. The original comments have this as 0. The problem I face is what could be the best way to show them.
In my model, I have created a function nested_comments() to get them and in my view I was doing like, this.
<? foreach( $comments as $comment ): ?>
....
<? foreach( $comment->nested_comments() as $comm): ?>
But that is only fine if I have one level of nested comments. Actually, I wish if there was a way to do this in the view. I don't wish to create another view file and controller for this purpose alone.
You can use function, Like below:
function getComments($comments){
if(!is_array($comments)){
return;
}
foreach($comments as $key => $value){
// do what you want with comments
getComments($nestedComments);
}
}
it's not ready to use function, but you can work in the same way.
You can achieve it with mptt modules, there are a few around:
https://github.com/spadefoot/kohana-orm-leap
https://github.com/rafi/orm-mptt
https://github.com/evopix/orm-mptt
I've been using third one but now its old and I suggest you to take a look at leap, it looks very promising.
And also take a look at http://kohana-modules.com/search?query=mptt

Codeigniter - Moving complicated IF statements out of the View

I'm currently working on a project thats means I'm dealing with lots of dates and I have one view where a user can see an overview of various events, for the coming week.
The view shows multiple events for multiple accounts.
The problem I am facing is that my view has some pretty complex IF statements (checking the current date, checking the event date, checking the account id against the event etc) and its starting to look messy and I'm sure it could be done easier/more streamlined!
How would I go about moving an IF statement to the controller?
I tried looking up best practices for CI but nothing useful comes up.
Any insight would be highly appreciated!
i would have a seperate function (within the controller or a library) that is used to prepare the data. this function only needs to return an array so that the data can be constructed in the HTML without the need for all the conditional checks.
This is an example of a data prepration library, it won't just work so you will need to create a full library, it is just to give you a general idea.
<?php
class prepare {
function prep_page_data($page_id) {
$output = array();
$query = $this->ci->db->get_where("page_data", array("page_id" => $page_id));
foreach($query->result_array() as $row) {
$output = $row;
//complete all addtional checks below
if($row['datetime'] < date("Y-m-d 00:00:00")) {
$output['archive'] = "old"
}
else {
$output['archive'] = "new";
}
//you can add as many conditions as you like to complete the data collection.
}
return $output;
}
}
?>

Categories