Jump to content

[solved] is this a wrong selector or bug?


bernhard
 Share

Recommended Posts

hi!

very strange... i have several feedback-pages that store feedback values in repeaters. i want to show the last 5 feedbacks to my users and did a selector like this:

foreach(pages("has_parent=$project, template=feedback, sort=-modified, limit=5") as $p) {
  d($p->answers->count());
}

this works as expected, but we added some feedback-pages and they show up in this list. so i wanted to exclude them by only showing items that have at least one answer in the answers repeater:

foreach(pages("has_parent=$project, template=feedback, answers.count>0, sort=-modified, limit=5") as $p) {
  d($p->answers->count());
}

the results are:

// first code example
7
0
4
0
7

// second example
7
4
7

any other ideas how i can only show modified pages and NOT newly created ones?

thanks :)

Link to comment
Share on other sites

Sorry for being unclear! I would have expected the second to also return five pages but it only returns 3.

Thanks for the link szabez, that's a very similar problem but in my case it should also work with the answers.count>0

  • Like 1
Link to comment
Share on other sites

10 minutes ago, bernhard said:

I would have expected the second to also return five pages but it only returns 3.

Are you sure you have more than 3 pages with non-empty "answers" repeaters?

When I test a selector that includes a repeater.count clause the expected number of pages is returned (i.e. the limit).

  • Like 2
Link to comment
Share on other sites

hm... now this is weird :(

thanks for clarifying - yes, i have more than 3 pages with non-empty answers. see the screenshot - does anybody has an idea what could be going on?! :o

Zwischenablage01.thumb.png.195fc5f452dd8f36162d874fc42cb645.png

the field's name is "answers" (see line 2 of console). maybe this is related to my multilang setup? shouldn't that be irrelevant?

thanks for your help!

Link to comment
Share on other sites

That is really weird. Not sure what could cause that, but some things to try:

  • Add "include=all" to the selector.
  • Add "check_access=0" to the selector.
  • If there is any access control set for the repeater field, select the "Make field value accessible from API even if not viewable" option.
  • Test the selectors in a template file to rule out any issue with the Tracy console.
  • Like 2
Link to comment
Share on other sites

thanks robin, i found the problem! by coincidence i had to modify one feedback and manually save it. now i wanted to investigate further and got a count of 1 for the answers.count>0 selector.

then i saved another page and got a count of 2.

so the repeater.count selector seems to work only after a page was saved. i set all the values via API so the selector didn't work. first i thought it's maybe because of setAndSave() but even after a foreach and page->save() the selector didn't work. it works only after a manual pagesave.

my quickfix is an additional field + saveready hook that populates the number of answers. I'll file an issue on github.

  • Like 2
Link to comment
Share on other sites

@bernhard, could you show the code you are using to add pages and repeater items? I am trying to reproduce the problem but I'm not able to. I didn't know setAndSave() supported adding items to repeater fields - how are you using it for that?

And if you are creating pages and adding repeater items in one operation, are you saving the page before adding the repeater items? E.g.

$p = new Page();
// ...
$p->save(); // are you saving here?
$r = $p->your_repeater->getNew();
// ...
$p->save();

 

  • Like 1
Link to comment
Share on other sites

sure:

// save data or print errors
if(!count($err)) {
  $answer = $feedback->answers->findOne("competence=$compid");
  $feedback->of(false);

  // save data
  // if answer does not exist, create it
  if(!$answer OR !$answer->id) {
    // add a new repeater item
    $answer = $feedback->answers->getNew();
    $feedback->answers->add($answer);
    $feedback->save();
  }
  $answer->of(false);
  $answer->competence = $comp;
  $answer->rating = $rating;
  $answer->noanswer = $noanswer;
  $answer->textfeedback = $textfeedback;
  
  // save the changes
  $answer->save();
  
  // update numanswers field, quickfix for this:
  // https://processwire.com/talk/topic/17549-is-this-a-wrong-selector-or-bug/
  $feedback->save();
}
else {
  // print errors
  echo implode("\n", $err);
}

edit: setAndSave was wrong in this regard - i'm using it only to set the repeater values when somebody provides a new rating :)

Link to comment
Share on other sites

I still can't reproduce the issue. I notice that the way you are creating new repeater items does not follow the documentation to the letter:

Quote

$building = $page->buildings->getNew();
$building->title = 'One Atlantic Center';
$building->feet_high = 880;
$building->num_floors = 50;
$building->year_built = 1997;
$building->save();
$page->buildings->add($building);
$page->save(); 

Note that the new repeater page is saved before adding it to the repeater field. Also the repeater page values are set before adding the page, but I don't think that should make a difference in the way you are doing it.

But even when I do it the way you are I don't experience any problem:

 2017-10-26_100013.png.8f6c8e43114876df5d8501284baec31a.png

  • Like 1
Link to comment
Share on other sites

  • 5 months later...

OK finally I came back to this one and I found the problem. See these Tracy Console codes:

Works:

$p = $pages->get(1002);
$p->of(false);

$r = $p->repeater;
$item = $r->getNew();
$item->title = 'created via api @ ' . date('YmdHis');
$item->save();

$p->repeater->add($item);
$p->save();
d($p->repeater->count);

Does NOT work:

$p = $pages->get(1002);
$p->of(false);

$r = $p->repeater;
$item = $r->getNew();
$item->title = 'created via api @ ' . date('YmdHis');
$item->save();

$r->add($item); // <<------------ here is the change
$p->save();
d($p->repeater->count);

Saying "does not work" I mean, that a 

d($pages->find('repeater.count>0')->each('path'));

does NOT list a page with a repeater item added via the second code example, whereas it shows pages where I used the first (upper) example.

Looking at the database it becomes obvious why:

5adc92b9366f8_2018-04-2215_48_25-Laragon_repeatertest_field_repeater_-HeidiSQLPortable9.4.0_5125.png.e6f14cc51f9e3c7ee7504542d3b3b1de.png

For the page with id 1002 there is no data and no count value present.

 

@Robin S you should be able to reproduce it now. I've tested it on a fresh 3.0.99 dev version with the default profile and just added a repeater to the basic-page template.

I'm not sure if this is a bug or I just have to use the api correctly... But at least I think it is an odd behaviour since it looks like everything is working correctly also with the bad code and you might not notice that you are in trouble... Items are available and even published:

5adc94526be50_2018-04-2215_15_34-EditPage_Childpageexample1repeatertest_test.png.ca501fccd19495d4b3c6dde9b20f24d6.png

Here is the github issue: https://github.com/processwire/processwire-issues/issues/413

Link to comment
Share on other sites

9 hours ago, bernhard said:

$r = $p->repeater;

I guess the issue is because of how you are assigning $r. When you assign like this $r gets the value of $p->repeater but is otherwise not connected to it. The PHP manual says:

Quote

Note that the assignment copies the original variable to the new one (assignment by value), so changes to one will not affect the other.

So when you add an item to $r you are not adding it to $p->repeater.

Does the problem resolve if you assign $r by reference?

$r = &$p->repeater;

 

  • Like 3
Link to comment
Share on other sites

  • 10 months later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...