Jump to content

Learning to use the API


bwakad
 Share

Recommended Posts

Foundation5 -

I need to display additional fields after the body field which is declared as $body. But also in the list of children which is a function. Basically I am stuck again! - text input and area fields seems to be working fine, but selects are painfull. Maybe there is a function to grab selects and turn them into values to use in arrays? Anyway...

In my basic-page.php is this code, which combines children list with $body:

if($page->numChildren(true)) $body .= renderBodyNav($page->children);

When I place my field after this code - it will be displayed under the children list (if it has any) and not directly after the $body variable. When I place my field in between - it will display, but only IF it HAS children.

The function itself is this and displays the list with title and summary fields:

function renderBodyNav(PageArray $items, array $options = array()) {
    $defaults = array(
        'class' => 'body-nav side-nav',
        'fields' => array('summary','myselect'),
        'dividers' => true
        );    
    $options = array_merge($defaults, $options);
    return renderNav($items, $options) . renderPagination($items);
}

I can't simply put the single-select page field 'myselect' in the array, because it will just return ID.

And the renderNav function (that is combined with the previous one) and displays as sidebar is this, where I also need additional fields:

function renderNav(PageArray $items, array $options = array()) {

    if(!count($items)) return '';

    $defaults = array(
        'fields' => array(), // array of other fields you want to display (title is assumed)
        'class' => '', // class for the <ul>
        'active' => 'active', // class for active item
        'dividers' => false, // add an <li class='divider'> between each item?
        'tree' => false, // render tree to reach current $page?
        );

    $options = array_merge($defaults, $options);
    $page = wire('page');
    $out = "<ul class='$options[class]'>";
    $divider = $options['dividers'] ? "<li class='divider'></li>" : "";

    foreach($items as $item) {

        // if this item is the current page, give it an 'active' class
        $class = $item->id == $page->id ? " class='$options[active]'" : "";

        // render linked item title
        $out .= "$divider<li$class><a href='$item->url'>$item->title</a> ";

        // render optional extra fields wrapped in named spans
        if(count($options['fields'])) foreach($options['fields'] as $name) {
            $out .= "<span class='$name'>" . $item->get($name) . "</span> ";
        }

        // optionally render a tree recursively to current $page
        if($options['tree']) {
            if($page->parents->has($item) || $item->id == $page->id) {
                $out .= renderNav($item->children("limit=50"), array(
                    'fields' => $options['fields'],
                    'tree' => true,
                    ));
            }
        }
     $out .= "</li>";
    }

  

  • Like 1
Link to comment
Share on other sites

...............Maybe there is a function to grab selects and turn them into values to use in arrays? Anyway...

You better re-read this answer to your previous question: https://processwire.com/talk/topic/6013-difference-select-aka-dropdown-vs-page-field-type/?p=58768

Hint....

$page->myselect->title;
$page->myselect->template;
$page->myselect->id;
$page->myselect->child->name;
$page->myselect->headline;//custom field
$page->myselect->othercustomfield;//custom field
$page->myselect->this;
$page->myselect->that;
$page->myselect->that->and->and->and;//you get the picture...

Here's your other homework...will the above work in a function?  ;) 

Edited by kongondo
  • Like 3
Link to comment
Share on other sites

The good read, was not so good... this: $a[$key] translates to me as "variable[iD]" - problem> I don't know ID upfront / how to turn $a into 'myselect' to use in array?

'fields' => array('summary','myselect'), - is not working for 'myselect' as value, only as ID.

But why does it work for 'summary'? Are they not both strings of text?

Will my only option then be to delete this function? Why does it say fields then?

I am so confused (again) :-[

EDIT --------------------------

Somehow, you all pointed me in the right direction, since the first function takes on the second function I described I looked at this particulair part, and added ->title. Then when I use 'myselect' it returns my value. BUT NOW THE FIELD SUMMARY IS GONE!!!

        // render optional extra fields wrapped in named spans
        if(count($options['fields])) foreach($options['fields'] as $name) {
            $out .= "<span class='$name'>" . $item->get($name)->title . "</span> ";
        }
Link to comment
Share on other sites

Did you read my post just above yours?

I don't understand what you are really trying to do with your function but there's is a world of difference between the fields 'summary' and 'myselect'. The former contains text = a string. 'myselect' is a page field, so returns a page object (like I stated above). If you just echo it out, it will just show the id of the selected page. The question is, what do you want from 'myselect', i.e. which of its fields are you after. In my hint above, I gave you examples of how you can get any property or custom field of your 'myselect'. That is what you need to give your array...

array('$page->myselect->title');//this is outside a function. Inside a function, that is the homework I suggested you read about 
Link to comment
Share on other sites

it's only good if you know how to use it. Like I said before: I am not good in php - so blaming me for asking I will take as policy I guess. I just keep trying to learn despite what some might think.

But if I look at the page you described - which I did several times, I have no clue what to do with it:

$a[$key]

From description (in human language) I can see what it suppose to do. But since I started with PW, it was my understanding litlle knowledge of php was enough and I was thought $page->myfield->title

So do I now have to make the $a into $page, and do I have to place 'myfield' in $key. Is my field a variable? Is $key the ID of something?

How the &^* do I translate the first with the second????

Link to comment
Share on other sites

In that example $a is a wireArray (can be a list of pages, or a list of fields, or a list of users... and so on)

$key represents the position that you want. so $a[0] would get the first item in the array and $a[5] the sixth. Works like in a normal PHP array. By the way, here is another good read —you will see "key" mentioned a lot there— http://www.php.net/manual/en/language.types.array.php

But I don't think that was the relevant part of the page that Martijn linked to.

Link to comment
Share on other sites

@bwaked, from the most recent posts you've done I conclude you don't fully understand the basic principles of the Wirearray / Pagearray. I can imagine that those are a little harder to understand. Next, I think to see is that you're still struggling with PHP. This is not a problem on it's own. But when you try to learn the ProcessWire basics next to it, it is maybe one little thing to much. Most people learn from little steps, expanding on the things already learned. The PW docs are written to be as simple as possible and on the same time it covers all the basics you'll need to know to get started.

  • Like 3
Link to comment
Share on other sites

Somehow, you all pointed me in the right direction, since the first function takes on the second function I described I looked at this particulair part, and added ->title. Then when I use 'myselect' it returns my value. BUT NOW THE FIELD SUMMARY IS GONE!!!

        // render optional extra fields wrapped in named spans
        if(count($options['fields'])) foreach($options['fields'] as $name) {
            $out .= "<span class='$name'>" . $item->get($name)->title . "</span> ";
        }

Your "summary" field is not a PageArray, therefore, you can't really iterate through it as one.  Hence the reason it's "gone".  The "my_select" field, if it is a Page Field, can be iterated, therefore the loop grabs the title.  If you wanted to determine if the field needs iterating, you could do a simple count.  If the # of objects that count finds is greater than 1, you've got to iterate. Using your code:

// render optional extra fields wrapped in named spans
  if(count($options['fields'])) {
    // Iterate options['fields'] array
    foreach($options['fields'] as $name) {
      // If the page's field returns more than one object
      if (count($item->$name) > 1){
        // Iterate the PageArray referenced by the "my_select" field
	foreach($item->$name as $pageField){
	  // Grab title
          $out .= $pageField->title."<br/>";
	}
      }
      else{ 
	$out .= "<span class='$name'>" . $item->$title . "</span> ";  //Or whatever you want to do
      }
    }
  }

Definitely not the most elegant solution but it highlights some important aspects of PW fields. In order to iterate through the "sub"-fields of a field set as a Page Field type: you must iterate through those pages. And for a field that would be returning just a string or numeric value, like your $page->summary, you simply return that value to wherever you want it to go.  I wasn't 100% sure what you were trying to accomplish but I hope this helps you over that little hump.

  • Like 1
Link to comment
Share on other sites

it's only good if you know how to use it. Like I said before: I am not good in php - so blaming me for asking I will take as policy I guess. I just keep trying to learn despite what some might think.

But if I look at the page you described - which I did several times, I have no clue what to do with it:

$a[$key]

From description (in human language) I can see what it suppose to do. But since I started with PW, it was my understanding litlle knowledge of php was enough and I was thought $page->myfield->title

So do I now have to make the $a into $page, and do I have to place 'myfield' in $key. Is my field a variable? Is $key the ID of something?

How the &^* do I translate the first with the second? ???

If you look on the cheatsheet, right below $a[$key] is $a->$key. If you want to translate that to your current page you could simply replace $a with $page.  Or in your code example, $item.

So you have:

$a->$key   is the same as   $item->summary:   $a is the page ($item) being referenced, and $key is the index or, in this case, the field name (summary).

According to the cheatsheet: $a->key returns the VALUE of the item at the given $key.  Therefore, $item->summary returns the string that you have in a text field. But look at what happens with $item->myfield:

myfield is a PageArray and title is a field: Translates to "return the value of the PageArray at the given field title".  PageArray's don't have title fields, pages do.  Therefore iteration is required to access the title field of each page in the array referenced by myfield.

It's easy to over complicate PW's API.  You have to be mindful of its syntax, the usage of the variables/methods available, and the return values of the methods being used or you will in for a bumpy ride: and that's with any API you decide to use.

  • Like 2
Link to comment
Share on other sites

Thank you guys,

All above comments starting to make more sence to me now. But I must admit, I certainly need to look in php and learn more.

I was really afraid I needed to go back to joomla or wordpress!

My best bet is to simply forget about using a site profile (responsivenes > is so inviting) which often make it more difficult (functions > that I do not fully understand), or (wire > something) = huh?, and focus on the more simple ways to display content.

So upon trying to understand the php, and also the API / cheatsheet, please share some php learning sites like the one linked above.

  • Like 2
Link to comment
Share on other sites

My best bet is to simply forget about using a site profile (responsivenes > is so inviting)

Exactly! One thing at a time. In PW things are not tied together like in other CMSs, this is what makes it so flexible. You will learn faster if you focus on the content. Test with a blank page, you'll see it's fun. And once you know how to print in that blank page exactly the parts of the content you want, it will be so easy to take any responsive theme and apply it to your site :)

  • Like 2
Link to comment
Share on other sites

My best bet is to simply forget about using a site profile (responsivenes > is so inviting) which often make it more difficult (functions > that I do not fully understand), or (wire > something) = huh?, and focus on the more simple ways to display content.

It's like diogo said.

My prefered way to work (I'm also a PHP noob like you): build a static website in html and css. Or at least make some demos with the desired structure/layout. There I can do all the responsiveness and other stuff. After that I split the parts/files to make the templates etc. The rest is doing echo, if and foreach...

Try to make it as simple as possible in the beginning. So you don't have to find out, what others have constructed in the ready made site profiles.

  • Like 1
Link to comment
Share on other sites

yes, I believe I have to do it like that - for now (again!) I started from the DEV branch. Mainly because it's more clear looking at template files. I will just make my structure first...

Link to comment
Share on other sites

I was really afraid I needed to go back to joomla or wordpress!

Do not go down that road, it is a dark and miserable path where fellow travelers seek to fill your pages with a contagion of confusion and dismay. >:D  Aside from the occasional notion of "oh, this might actually work", you will find yourself subject to the chains of their template systems. At the end of the day, though your site may work, you may cringe at the mere mention of changing anything in it. And it only gets worse as your projects become more involved.  (Speaking from experience.)

Stay here, it's nice here. ;)

  • Like 7
Link to comment
Share on other sites

Well, today I started fresh, Only a dev branch. Nothing fancy, no changes, just made a couple of pages with childs and some content.

Then I copied the part from API $page specifics and placed them in a table to include on my current page. That's exciting you might say! But it really give me some insight in what to expect using this $page variable.

I then did the same for $pages, but in this case, only the $pages->find and $pages->get ones.

I make this table as a find (more) vs get (one). But I had a suprise which I did not expect:

$pages->get("selector, path or ID"); states that it can be a selector to. A selector from what I read can be template=basic-page, but this gave me the 404 page ID.

So does it mean : a selector specified by path or id? Or  : selector or path or ID?

Link to comment
Share on other sites

Get and find do the same, except that get retrieves a single page. Everything about selectors is here https://processwire.com/api/selectors/ but now you have the perfect environment to start with the planets tutorial https://processwire.com/talk/topic/693-small-project-walkthrough-planets/ and that's where you should go next :)

Link to comment
Share on other sites

Well, today I started fresh, Only a dev branch. Nothing fancy, no changes, just made a couple of pages with childs and some content.

Then I copied the part from API $page specifics and placed them in a table to include on my current page. That's exciting you might say! But it really give me some insight in what to expect using this $page variable.

I then did the same for $pages, but in this case, only the $pages->find and $pages->get ones.

I make this table as a find (more) vs get (one). But I had a suprise which I did not expect:

$pages->get("selector, path or ID"); states that it can be a selector to. A selector from what I read can be template=basic-page, but this gave me the 404 page ID.

So does it mean : a selector specified by path or id? Or  : selector or path or ID?

1.) selector, path, or ID is correct.

2.) the 404 page uses the basic-page template, so the selector executed correctly.

Link to comment
Share on other sites

Thanks, but I have been through that 3 times. That's more then enough...

Here's a nice thing I found out: <?php highlight_string('<?php phpinfo(); ?>') ;?>

A inbuild php function to display code as text, just replace <?php phpinfo() ;?> with your code!


1.) selector, path, or ID is correct.

2.) the 404 page uses the basic-page template, so the selector executed correctly.

Oh, wait. Of course you are right! It just returns the FIRST, probably based on date or ID. Thanks!

Link to comment
Share on other sites

from: $page->parent;

// what's my parent?

to: $page->get(parent)->title;

// retrieve the title of the parent page

experimenting with: $page->get(parent)->fields;

// take array from the template of the parents page

itterating: $parentfields = $page->get(parent)->fields; foreach ($parentfields as $myfield) echo $myfield;

// get field names from the template of the parent page

and some: $page->get(modifiedUser)->name;

// retrieve the name

or like this: <a href='.$page->get(parent)->headline->url.'>'.$page->get(parent)->headline.'</a>

// this way I can use a field value and link it to the page // ONLY THE URL IS WRONG... will check...

// of course, it has to be : <a href='.$page->get(parent)->url.'>'.$page->get(parent)->headline.'</a>

All fun so far! Type of code should be in a cheatsheet for newbies...

  • Like 2
Link to comment
Share on other sites

Thanks!

I just experiment with the API and started actually with a couple of rows: PHP in text format | PHP code executed | explenation

And every line get a little more code inside, mixing, trying, and if it works, I save it.

Now, I also realize:

if I receive more then 1 result back (array) - of course I can GET it, but only the first result (if any),

otherwise, I just have to itterate through them.

Link to comment
Share on other sites

if I receive more then 1 result back (array)

Not sure if you already got this, but just to be clear: you don't just "receive" one or more results, you explicitly ask for either of those. A get() will return one result that you can use directly, even if the selector you use would return more, and a find() will return an array that you have to itterate through, even if the result of that select is only one page.

  • Like 4
Link to comment
Share on other sites

Yes, that I know. But to just to keep it human language... Now I am using foundation (did it myself) to arrange my test content a little more nice.

Made a test.php file with some basic code from the API, which I include in my site wide used template file (to test).

Since I made pages on different levels, this simple code (which in your terms "explicitly ask for either of those") is included by default on any level of page I am in. Then it's easy to see what's going on. Mind you, my text are in my own words, so not to blame me please....

Here it is to test (ps. I made a tag called <code2> for another color to keep things clear):

<?php
// used to test on a per function based API //
?>
<ul class="no-bullet">
<li>Code: <code>echo $page;</code> and <code2>echo $page->id;</code2></li>
<li>Result: <code><?php echo $page;?></code> and <code2><?php echo $page->id;?></code2></li>
<li>Both will give you the ID of the <em>current</em> viewed page.</li>
</ul>

<hr>

<ul class="no-bullet">
<li>Code: <code>echo $page->rootParent;</code> and <code2>echo $page->rootParent->id;</code2></li>
<li>Result: <code><?php echo $page->rootParent;?></code> and <code2><?php echo $page->rootParent->id;?></code2></li>
<li>Both will give you the ID of the <em>root parent</em> page, from the current viewed page.</li>
<li>This is <em>not</em> the top-level root from page tree!</li>
</ul>

<hr>

<ul class="no-bullet">
<li>Code: <code>echo $page->parent;</code> and <code2>echo $page->parent_id;</code2></li>
<li>Result: <code><?php echo $page->parent;?></code> and <code2><?php echo $page->parent_id;?></code2></li>
<li>Both will give you the ID of the top level <em>parent</em> page (in the page tree).</li>
<li>Mind the underscore in the code when using the last one!</li>
</ul>

<hr>

<ul class="no-bullet">
<li>Code: <code>echo $page->child;</code> and <code2>echo $page->child->id;</code2></li>
<li>Result: <code><?php echo $page->child;?></code> and <code2><?php echo $page->child->id;?></code2></li>
<li>Both will give you the ID of the <em>first child</em> page, starting from the current viewed page.</li>
<li>If nothing present, the first code is <code>empty (NONE)</code>, the second code is <code2>0 (NULL)</code2>.</li>
</ul>

<hr>

<ul class="no-bullet">
<li>Code: <code>echo $page->children;</code></li>
<li>Result: <code><?php echo $page->children;?></code></li>
<li>This will give you the ID of the <em>children</em> pages.</li>
<li>If nothing present, it will return <code>empty (NONE)</code>.</li>
<li><span class="alert label">Don't excist</span> <code2>page->children->id</code2> and <code2>pages->children->id</code2>.</li>
</ul>

<hr>

<ul class="no-bullet">
<li>Code: <code>echo $page->siblings;</code></li>
<li>Result: <code><?php echo $page->siblings;?></code></li>
<li>This will give you the ID of <em>same level</em> pages, called siblings.</li>
<li>It will only return public listed pages.</li>
<li><span class="alert label">Don't excist</span> <code2>page->siblings->id</code2> and <code2>pages->siblings->id</code2>.</li>
</ul>
<hr>

<ul class="no-bullet">
<li>Code: <code2>echo $page->template->id;</code2>
<li>Result: <code2><?php echo $page->template->id;?></code2></li>
<li>This will give you the ID of the <em>template used</em> used for this page.</li>
<li>With the <code>$page->template</code> you will only get template DB name: <code><?php echo $page->template;?></code></li>
</ul>
<hr>
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...