Jump to content

Field only saving when set twice


Tom.
 Share

Recommended Posts

Solution:

$p->save(["uncacheAll" => false]);

 

 

 

Edit:

Added step by step

 

Hey guys,

I'm building an eCommerce for ProcessWire which is coming along nicely.


MGGS42g.png

 

However I've come across a bug which I can't seem to figure out what's going off and why. I've put up a post on GitHub, but I know Ryan is a busy man and I am currently working on this 6-8 hours a day.

https://github.com/processwire/processwire-issues/issues/434

Here is a link to the issue. 

Link to comment
Share on other sites

Your code copied from the GitHub issue:

$options = wirecommerce_get_all_variations($page);
$variations = $page->wirecommerce_variations;

// Detect added
$added = 0;

foreach($options as $option) {
   if(!$variations->has("wirecommerce_variation_value='$option'")) {
      $new_option = $variations->getNewItem();
      $new_option->wirecommerce_variation_value = $option;
      $new_option->save();

      $added++;
  }
}
if($added > 0) $this->message("$added variations added.");

The code example for adding a repeater item from the documentation:

$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();

So I think your code should be:

$options = wirecommerce_get_all_variations($page);
$variations = $page->wirecommerce_variations;

// Detect added
$added = 0;

foreach($options as $option) {
    if(!$variations->has("wirecommerce_variation_value='$option'")) {
        $new_option = $variations->getNew(); // Or getNewItem(), they are the same thing
        $new_option->wirecommerce_variation_value = $option;
        $new_option->save();
        $variations->add($new_option);

        $added++;
    }
}
$page->save();
if($added > 0) $this->message("$added variations added.");

 

  • Like 3
Link to comment
Share on other sites

1 hour ago, Robin S said:

Your code copied from the GitHub issue:


$options = wirecommerce_get_all_variations($page);
$variations = $page->wirecommerce_variations;

// Detect added
$added = 0;

foreach($options as $option) {
   if(!$variations->has("wirecommerce_variation_value='$option'")) {
      $new_option = $variations->getNewItem();
      $new_option->wirecommerce_variation_value = $option;
      $new_option->save();

      $added++;
  }
}
if($added > 0) $this->message("$added variations added.");

The code example for adding a repeater item from the documentation:


$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();

So I think your code should be:


$options = wirecommerce_get_all_variations($page);
$variations = $page->wirecommerce_variations;

// Detect added
$added = 0;

foreach($options as $option) {
    if(!$variations->has("wirecommerce_variation_value='$option'")) {
        $new_option = $variations->getNew(); // Or getNewItem(), they are the same thing
        $new_option->wirecommerce_variation_value = $option;
        $new_option->save();
        $variations->add($new_option);

        $added++;
    }
}
$page->save();
if($added > 0) $this->message("$added variations added.");

 

Thanks for the suggestion, but sadly not the case. Here is a quote from Ryan:

"It shouldn't be necessary to do the $page->repeater->add($repeater); as the getNew() method already does that."

 

Link to comment
Share on other sites

In a rush, but take a look at this post: https://processwire.com/talk/topic/6435-cant-figure-out-how-to-create-a-repeater-through-the-api/?do=findComment&comment=62987

Can't remember why I say that the docs are wrong, but for some reason I save the new item before adding any subfields - maybe something to that for some reason?

Link to comment
Share on other sites

1 minute ago, adrian said:

Can't remember why I say that the docs are wrong, but for some reason I save the new item before adding any subfields - maybe something to that for some reason?

I think that is because in that example you are adding files to the repeater page. A page has to be saved before you can add files or images to it.

  • Like 1
Link to comment
Share on other sites

Yeah, I'm starting to think this is something to do with mod_security or timeout. The script seems good? 

That or it's a bug with ProcessWire. It has the appearance of a mod_security issue blocking the fields from saving. But I don't know. Usually when that happens if effects all fields. 

Edit:

Checked, mod security is turned off

Link to comment
Share on other sites

Added step by step guide: 

1. Create a new template called bug.
2. Create two repeaters one called repeater_1 and repeater_2.
3. Create a text field called text and add that to repeater_1 and repeater_2. 
4. Add repeater_1 and repeater_2 to the bug template. 
5. Add this code to ready.php:

$wire->addHookBefore("Pages::save", function($event) {
  $page = $event->arguments("page");

  if($page->template == "bug") {

    for($i = 0; $i < 3; $i++) {
      $p = $page->repeater_2->getNew();
      $p->text = "Bug";
      $p->save();
    }

  }
});

6. Create a bug template page and add content to repeater_1.
7. Click save, you will see that the content for repeater_2 isn't saved, however 3 repeater_2's are added. 
8. Remove $p->save(); from the provided code. 
9. Add content to repeater_1, you will see that content is added however only 1 repeater is added to repeater_2. 

$p->save() causes any other repeater to not save, I believe this also applies to Page Reference (see: https://github.com/processwire/processwire-issues/issues/430
 

Link to comment
Share on other sites

I haven't followed closely, but please try:

$p->save('text');

Or something like that depending on what field(s) you are trying to save. Sorry, I should probably look at this more thoroughly, but not enough time :)

Saving the entire page in a save hook will always cause problems because of recursion.

  • Like 1
Link to comment
Share on other sites

6 minutes ago, adrian said:

I haven't followed closely, but please try:


$p->save('text');

Or something like that depending on what field(s) you are trying to save. Sorry, I should probably look at this more thoroughly, but not enough time :)

Saving the entire page in a save hook will always cause problems because of recursion.

Thanks, sadly that returns the error "Can't save field from a new page - please save the entire page first".

Maybe I will just have to rethink how this is going to work if that's the case, shame I thought it was a really user friendly way of handling product variations. 

Link to comment
Share on other sites

2 minutes ago, Tom. said:

Thanks, sadly that returns the error "Can't save field from a new page - please save the entire page first"

Makes sense - tricky because you are adding a repeater item. I am sure there is a fix, but really have to go now :)

Have a read of this: https://processwire.com/talk/topic/315-run-code-after-page-save/?do=findComment&comment=2206 - might put you on the right track!

Link to comment
Share on other sites

@Tom., there does seem to be something funny going on in this case when hooking before Pages::save. Will do some more testing, but to allow you to move forward with your project the quick solution is just to hook after Pages::save. So in the test case:

$wire->addHookAfter("Pages::save", function(HookEvent $event) {
    $page = $event->arguments('page');
    if($page->template == 'bug' && !$page->skip_me) {
        for($i = 0; $i < 3; $i++) {
            $p = $page->repeater_2->getNew();
            $p->text = 'Bug';
            $p->save();
            $page->repeater_2->add($p);
            $page->skip_me = true; // prevent recursion
            $page->save();
        }
    }
});

 

Edit: did some more testing using a Page Reference field and managed to trace it back to the "uncacheAll" option in PagesEditor::save(). Posted a comment on the other GitHub issue, which is definitely related to your issue. Hopefully Ryan can fix it soon.

  • Like 3
Link to comment
Share on other sites

5 hours ago, Robin S said:

@Tom., there does seem to be something funny going on in this case when hooking before Pages::save. Will do some more testing, but to allow you to move forward with your project the quick solution is just to hook after Pages::save. So in the test case:


$wire->addHookAfter("Pages::save", function(HookEvent $event) {
    $page = $event->arguments('page');
    if($page->template == 'bug' && !$page->skip_me) {
        for($i = 0; $i < 3; $i++) {
            $p = $page->repeater_2->getNew();
            $p->text = 'Bug';
            $p->save();
            $page->repeater_2->add($p);
            $page->skip_me = true; // prevent recursion
            $page->save();
        }
    }
});

 

Edit: did some more testing using a Page Reference field and managed to trace it back to the "uncacheAll" option in PagesEditor::save(). Posted a comment on the other GitHub issue, which is definitely related to your issue. Hopefully Ryan can fix it soon.

Thank you so much Robin, I really appreciate it! 

  • Like 2
Link to comment
Share on other sites

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...