Jump to content

API code to add FieldtypePage items to a page (not via form inputs)


Recommended Posts

Hi Folks,

I've brought my front-end app to the point where I'm successfully adding single and multi-type FieldtypePage items to a new page, from input via a form, using this type of code (thanks, Soma, for your tips on this):

           $field_value = $input->post->$field_name;

           ...

            # set field values

            if ( is_array( $field_value ) )
                  {
                  foreach( $input->post->$field_name as $pid )
                        {
                        $new_page->$field->add( (int) $pid );
                        }
                  }
            else
                  {
                  $new_page->set("$field_name", "$field_value");
                  }


It works like a charm with single selects, radio buttons, multi-selects, multi-checkboxes, etc.

However, in my app, I need to specifically set some field values (like drop down status fields, etc) that the user doesn't interact with.

I tried this code, but got an error: "Call to a member function add() on a non-object...".

                  $field = $fields->get("account_status");
                  # Trial = 1102

                  $selectors = "parent=/elements/custom_selects/account_status/," .
                               "select_value=Trial," .
                               "include=all";

                  $field_value_id = $pages->get("$selectors")->id;

                  $new_page->account_status = $field_value_id; ## (THIS CODE WORKED)

                  # $new_page->$field->add( (int) $field_value_id ); ## (THIS CODE DID NOT WORK)

 

The odd thing is that the first block of code works, from a form, for that same field (a single select).

I'd like to be able to programmatically set both single and multi-select fields, not via a form, for fields on a new page, or even on an existing page. Things like adding 4 or 5 checkbox values to a multi-checkbox field, etc.

I'm sure that my lack of knowledge about PHP OOP is getting in the way, which I plan to rectify. But until then, any tips would be most appreciated.

Thanks!

Peter

Link to comment
Share on other sites

Just a guess really, but have you tried $new_page->{$field->name}->add( (int) $field_value_id ); ? I'm guessing the problem might be that here your $field is an actual field (object), while what you really want is it's name.

Link to comment
Share on other sites

Dear Teppo,

I haven't tried that, but I already know the name of the field, so with your example, I could write:

$new_page->account_status->add( (int) $field_value_id );

I'm wondering why the code works when the values are coming from a form post....

Also, the error message was: "Call to a member function add() on a non-object...".

Yours,

Peter


 

Link to comment
Share on other sites

@Peter: $field = $fields->get("account_status") returns a field object. This would in turn return field ID when converted to string.

This explains the error you're getting: while $new_page->account_status returns field called "account_status" attached to that particular page, $new_page->123 (or whatever the ID of that field is) won't work (fields are called with their names, not ID values) and thus it returns an error when you try to use method "add" of this non-existent object.

Am I making any sense here? :)

Anyway, reading you post again, I must admit that I don't really get how your application works. There's just not enough data here, I'm afraid.

For an example your first example gets field value from $input->post->$field_name but field name itself ($new_page->$field->...) seems to already exist at that point. This is why I'm having a bit of a hard time understanding the relation between these two code examples.

  • Like 1
Link to comment
Share on other sites

Dear Teppo,

In the first example, with the $field_value input coming from a form post, I iterate over an array of field names, getting $field_name from that array.

In the second example, the user has filled out a form, and the code in the first example parses most of the ordinary fields.

Then, after that has been done, prior to saving the new page, I need to set the values on a small group of 'admin' type fields, like account_status.

Account status is of FieldtypePage, (a single select dropdown). I'm trying to set the field to one of the values ('Trial'), which of course has a page ID.

So, since I already know the field name, and the value, I just have to figure out the code to set the value.

I want to be able to do the same thing for multi-selects or multi-checkboxes as well.

I thought I had to add those values, using the $field->add function, as I did with the 1st example which process user form post input,

but then I ran into that error.

I'm sure I'm missing something obvious to an OOP expert, but I haven't figured it out yet.

This whole thing is a front-end app for members, where they will add, edit and delete pages, all through the API in custom php files.

I've got most things working... I'm just stuck on this little point, at the moment. I'm deliberately not using the form API, because I'm

using HTML templates with field tags, and then replacing them with values or input fields.

Yours,

Peter

  • Like 1
Link to comment
Share on other sites

If account_status is of single page select it won't have a add() method like PageArrays have.

Multiple page select

$new_page->$field->name->add(1023);
// like
$new_page->account_status->add(1023);

// and also this (which seems to append db entry) guess makes sense? 
$new_page->account_status = 1023;

Single page select 

$new_page->$field->name = 1023;
// like
$new_page->account_status = 1023;

// but not 
$new_page->account_status->add(ID); // wrong

So the page field can have different types based on the dereference settings multiple or single and behave slightly different. Single: it will only be a value of type page and page have no method add, multiple: will be a PageArray. PageArrays have the method add() to add pages, but also the field recognizes just ID's set to it, and it will save the entry and the others already saved or doublicates remain untouched. So to clear a multiple page field you have to call field->removeAll() first.

You get this error because the value is most likely not an object (yet). If it dereferences as "single page or false if none selected (!)" .. so if the field is empty it will throw an error: Error: Call to a member function add() on a non-object 

If you would have already saved a value you would get this error instead, same code but different message because the field now has a page object set:

 Error: Exception: Method Page::add does not exist or is not callable in this context 

Hope this shares some light.

  • Like 4
Link to comment
Share on other sites

Dear Soma,

This is really helpful. Thanks! So, based on what you wrote, it seems that this code worked with the form:

if ( is_array( $field_value ) )
                  {
                  foreach( $input->post->$field_name as $pid )
                        {
                        $new_page->$field->add( (int) $pid );
                        }

                  }

because the add method was appropriate because the field was a multi.

In other words, that code didn't click in when the field was a single (i.e. no array).

Your comment about the Page and PageArrays was especially helpful:

"Single: it will only be a value of type page and page have no method
add, multiple: will be a PageArray. PageArrays have the method add() to
add pages, but also the field recognizes just ID's set to it, and it
will save the entry and the others already saved or doublicates remain
untouched."

I'm wondering -- since this line:

// and also this (which seems to append db entry) guess makes sense? :)
$new_page->account_status = 1023;

seems to work for BOTH cases, would you consider it a proper PW way to use that

type of code for both single and multi fields?

I believe that you imply above that one could even do this on a multi field, with

the values (pages) getting appended one after the other:

$new_page->account_status = 1023;

$new_page->account_status = 1024:

$new_page->account_status = 1025:

This way, one doesn't have to test whether it's a single or multi field.

Thanks so much for your help!

Peter

Link to comment
Share on other sites

$new_page->account_status = 1023;

 

seems to work for BOTH cases, would you consider it a proper PW way to use that

type of code for both single and multi fields?

 

I believe that you imply above that one could even do this on a multi field, with

the values (pages) getting appended one after the other:

 

$new_page->account_status = 1023;

$new_page->account_status = 1024:

$new_page->account_status = 1025:

 

This way, one doesn't have to test whether it's a single or multi field.

While you may be able to use some of these syntactic tricks when it comes to setting a value, I think it's better to treat a Page as a Page and a PageArray as a PageArray, just as a matter of keeping your code readable. If I have code that needs to deal with either a Page or a PageArray, but it doesn't know ahead of time which it will be, I usually treat it like this:

if($value instanceof Page) {
  // treat it as a Page
} else if($value instanceof PageArray) {
  // treat it as a PageArray
}

Or I normalize it to one or the other. For instance:

if($value instanceof Page) {
  $a = new PageArray();
  $a->add($value);
  $value = $a;
}
// now we can assume $value is always a PageArray
  • Like 3
Link to comment
Share on other sites

Dear Ryan,

Thanks, that makes sense; to keep the code clean.

When I tried to integrate your suggestion into my form processing code (listed at the very top of this post), it didn't work.

Specifically:

            # if ( $field_value instanceof PageArray )
            # this didn't work

            if ( is_array( $field_value ) )
                  {
                  foreach( $input->post->$field_name as $pid )
                        {
                        $new_page->$field->add( (int) $pid );
                        }
                  }

 

whereas the "is_array" method did work. Once again, I'm grabbing field values like this:

$field_value = $input->post->$field_name;

In the case of Page type fields, I didn't use sanitize, since they were the result of dropdowns, etc.

Do you think that the "is_array" method is solid enough, and is there something I'm missing with the "instanceof PageArray" method?

Thanks,

Peter

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