Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

Data Model Questions /

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo, swaiba

How to merge or associate two ArrayLists?


Go to End


5 Posts   5210 Views

Avatar
P. A. Perini

Community Member, 6 Posts

8 February 2014 at 12:25am

Edited: 08/02/2014 12:30am

Hi there! I hope someone can help me.
I would like to create a top ten Guides to show on a GuideHolder page. Following the Form documentation I've created the GuideReviewSubmission object. Then the page type GuidePage. I would like to show for each PageGuide its poll "Percentage" from the higher to the lower.
But I have some problem with the following script because I am not able to merge the two ArrayLists or associate one to the other for each GuidePage.

<?php
class GuideHolder extends Page {
    private static $allowed_children = array('GuidePage');
}
class GuideHolder_Controller extends Page_Controller {
public function topTenGuides() {
    $submissions = new GroupedList(GuideReviewSubmission::get());
    $guides = GuidePage::get();
    $topGuides = new ArrayList();
    $list = new ArrayList();

    foreach($submissions->groupBy('Guide') as $guideName => $guideSubmissions) {
    	$guideTot = $guideSubmissions->Count();
    	$totalReview = 0;
	    	foreach ($guideSubmissions as $value) {
	    	$totalReview = ($value->Review + $totalReview);
	    	}
		$percentage = (int) ($totalReview / $guideTot * 20);
        $list->push(new ArrayData(array(
            'Guide' => $guideName,
            'Percentage' => $percentage,
            'Total' => $guideTot
        )));
    }
    $list = $list->sort('Percentage', 'DESC');
    foreach ($list as $eachGuideResult) {
    	foreach ($guides as $allTheGuides) {
    		if ($eachGuideResult->Guide == $allTheGuides->Title) {
    		$topGuides->merge($allTheGuides , $eachGuideResult);
    		}
    	}
    }
        return $topGuides;
}

$topGuides->merge($allTheGuides , $eachGuideResult); seems to do not work because the result is only the list of the PageGuides and it doesn't give the Poll result (Percentage).
If I change it with

 $topGuides->push($allTheGuides);
$topGuides->push($eachGuideResult);

the records are of course duplicated.

Here is the template code

 <% loop $topTenGuides %>
<h1>$Title</h1>
<div id="GuideResult">
	<div class="space"><div class="bar" style="width:$Percentage%">&nbsp;</div></div>
</div>
<p>$Content.FirstParagraph</P>
	<% end_loop %>

I am not an expert of PHP, can someone help me?
Thanks in advance!!

Avatar
martimiz

Forum Moderator, 1391 Posts

8 February 2014 at 10:29am

I'm not sure I totally get what you're building, but in the API docs for ArrayList (http://api.silverstripe.org/master/class-ArrayList.html) the merge function is defined like this:

merge( array|object $with )

so basically:

$theFirstList->merge($theSecondList);   // or the other way around :)

Avatar
P. A. Perini

Community Member, 6 Posts

8 February 2014 at 9:35pm

Edited: 08/02/2014 9:40pm

Dear Martimiz,
thank so much for your reply.
But the script doesn't work properly as I would.
1. If I use the following code I get a Server Error:

foreach ($list as $eachGuideResult) {
    	foreach ($guides as $allTheGuides) {
    		if ($eachGuideResult->Guide == $allTheGuides->Title) {
    		$eachGuideResult->merge($allTheGuides);
    		$topGuides->push($eachGuideResult);
    		}
    	}
    }
        return $topGuides;

2. If I change the parameters as follow I get just the items of the $guides DataList without the poll result:

foreach ($guides as $allTheGuides) {
    		if ($eachGuideResult->Guide == $allTheGuides->Title) {
    		$allTheGuides->merge($eachGuideResult);
    		$topGuides->push($allTheGuides);
    		}
    	}
    }
        return $topGuides;

I'll try to explain you better what I want to do.
I have two lists.
The first one is $guides that contain all the GuidesPage created [$guides=GuidePage::get();]. The second one is $list that contain all the poll result grouped by Guide (not by GuidesPage even if the names are the same) and listed by the best to the worst; each $list item has these associations

'Guide' => $guideName,
         'Percentage' => $percentage,
         'Total' => $guideTot

When I loop the function topTenGuides(); I would like to show a list of all the GuidePages listed by their rating (and I got it):

$list = $list->sort('Percentage', 'DESC');
    foreach ($list as $eachGuideResult) {
    	foreach ($guides as $allTheGuides) {
    		if ($eachGuideResult->Guide == $allTheGuides->Title) {
                ...
                }

But, and this is my problem, I would also to show the Percentage value for each PageGuide.
I've been trying a lot of ways, for example

if ($eachGuideResult->Guide == $allTheGuides->Title) {
               $topGuides->push($allTheGuides);
               $topGuides->push($eachGuideResult);
}

but in this case, of course, the result is a duplication of records where the first is a GuidePage and the second a $list item even if it corresponds to to the first one (the third a PageGuide, the fourth a $list item and so on).
But as I told you, what I need is to show the list of the PageGudes with their $Percentage.

I don't know if merging the two list is the solution (it seems not to work), maybe there is another way to just associate each PageGuide with its poll result.

I have another question :). When i make changes to the template or the code and I refresh the page with ?flush=1 the system takes few time to show the changes (SilverStripe is on MAMP). Why? And how can avoid this "caching" to show the changes as soon as I refresh the page?

Still tanks a lot for your patience.

Avatar
martimiz

Forum Moderator, 1391 Posts

9 February 2014 at 12:21am

Edited: 09/02/2014 4:48am

Much depends on how you initially set up your models and their relations. I would assume something like this:

GuideHolderPage has_many GuidePages
GuidePage has_one GuideHolderPage

That relation is obviously taken care of by the page hierarchy. As for the submissions:

GuidePage many_many Submissions
Submission belongs_many_many GuidePages

Is that about it? Or do you need to keep your Submissions totally disconnected from your GuidePages for some reason?

Avatar
P. A. Perini

Community Member, 6 Posts

11 February 2014 at 4:46am

Edited: 11/02/2014 4:46am

Dear Martimiz,
thank you again for the reply.
I am trying to do as you told me.
But I still have a couple problems to clarify.

First of all, I think the relation is:
GuidePage has_many Submissions
Submission has_one GuidePage.
In fact, I have created a forum where the users can review only one Guide a time. Is it right?

The second thing, and the most important, is that I don't know how to create the relation between the GuidePage and the Submission through the FormPage. GuidePage extends Page and has_many Submission(s); Submission extends DataObject and has_one GuidePage; the FormPage, that extends Page, is the one that create each Submission.

The FormPage has some fields (name of the user, email, comments, suggestions, etc), the Review field (where the user can rate the Guide from 1 to 5), and finally there should be a Dropdown field of all the GuidePage(s) created by the website owner. I think that here is the trick, but I really don't know how to get the GuidePage in the FormPage to associate with the submission of the form.

Please let me know if you can help me and thanks.