Jump to content
ryan

New post: New PW website ready

Recommended Posts

Quote

 

In the template context, how can $page be any page unless you have overridden it, which we always discourage. Otherwise, $page is always the current page. I do understand that page() can't be overridden like $page can, so maybe going forward the functions API should be the recommended approach, but we are going to confuse the hell out of beginners if homepage examples show both approaches.

 

This is not what I'm saying. You seem to think this is something complex, but I think that's because you are used to something different. New users will not already be used to something. What I'm suggesting is actually much simpler than you think, and is more specific and clear than using exclusively $var or var(). Please wait and see what I write up this week, and I think it'll make sense. Like I mentioned earlier, if you fully understand it and still don't agree about the benefits, then I'll reconsider, but for now trust me on this. 

Quote

going to confuse the hell out of beginners if homepage examples show both approaches.

I would agree if we were showing $pages and pages() in the same set of examples, or $page and page(). But we are not.

Quote

But the save() example won't work as is and will confuse the user to see an error about outputformatting which they will not understand anything about yet. We have setAndSave() - why not use that example?

The examples don’t state “this is from a template file” or “this is from another script”, or any number of other contexts you could access PW’s API from. There’s plenty of cases where this call will work exactly as-is. If you are in a context where it won’t, it even specifically tells you what you need to do: call $page->of(false); first. Any 1-line example could work in one context and not another, that's the nature of it. 

In this brief set of intro examples it's important that we show not just getting data, but also saving it—wouldn't you agree? Yet setAndSave() is an advanced call, there for people that know what they are doing with regards to output formatting. It's not something to put in a beginner example because it's not for beginners. It’s important to learn what output formatting is before you start bypassing it. So I’m a little shy about a setAndSave() call here, plus I think it’s kind of a unique one-off in PW’s API, so not a general API example to communicate the underlying flavor of the API. And these examples are trying to communicate the overall flavor of the API, something to get you interested enough to explore further. 

Quote

 

Same goes for my observation about the image example and the issue with the need for first() on the site profiles which I think mostly come with "images" fields, rather than an "image" field. 

 

In the examples we also refer to floors, height, year, email. Immediately under the examples it states “All fields in ProcessWire are custom fields that you easily define and edit in the admin.” This is what the examples are showing, and this is actually a pretty important point of the homepage.  The fields you access from a page are entirely your own and you configure them how you want. If this is something that causes one confusion, then that would be a good confusion because it's revealing a key "aha" point. If this is something that sends one packing, then they didn't get it and are likely looking for something different than what PW is, which is also fine. But my preference is not to present examples that imply a fixed-field system, because that is the opposite of what PW is. 

Quote

Sorry if I wasn't fully clear.  I meant to only left justify these elements on the mobile breakpoint/view when everything is vertically stacked.  Above that breakpoint everything looks fine center justified.

Ah okay, thanks, I'll revisit and test it out again for those elements. 

 

  • Like 1

Share this post


Link to post
Share on other sites

Regarding the code samples on the home page, what if we had little tabs above each sample (or one set of tabs that switched all the samples) that allowed the visitor to switch approaches for the API variables?

So for a code sample using $pages the tabs would switch between (essentially) equivalent ways of getting that variable:

  • pages()
  • $pages
  • wire('pages')
  • $this->wire('pages')

If we want to promote the Functions API then that could be the default tab.

There would be a brief statement explaining the reason for the different equivalent samples with a link to more detailed information.

I haven't fully thought through the next part, but I wonder if this could be at least partially automated, either server-side or client-side, and applied to all code samples across the API documentation.

  • Like 8

Share this post


Link to post
Share on other sites
On 1/14/2019 at 1:13 PM, Robin S said:

So for a code sample using $pages the tabs would switch between (essentially) equivalent ways of getting that variable:

  • pages()
  • $pages
  • wire('pages')
  • $this->wire('pages')

Don't forget about:

  • $this->pages
  • $this->wire->pages
  • $this->wire()->pages
  • $wire->pages
  • wire()->pages
  • wirePages()
  • _wirePagesAPI('pages', '')

That's a total of 11 variations that I've found so far, although obviously the last one is a bit silly 🙂

  • Haha 1

Share this post


Link to post
Share on other sites
29 minutes ago, adrian said:

Don't forget about:

Hmm.. Too many tabs already? 

🙂

  • Like 1

Share this post


Link to post
Share on other sites

Here is another example of a nice homepage feature switcher with good screenshots for inspiration. 😉

Share this post


Link to post
Share on other sites
3 hours ago, adrian said:

Don't forget about:

  • $this->pages
  • $this->wire->pages
  • $this->wire()->pages
  • $wire->pages
  • wire()->pages

With the examples and documentation I think we should focus on illustrating things that a new user should use (depending on context) rather than all the things they could use. So we should take a best practices approach rather than trying to cover everything that technically will work.

Please correct me if I'm wrong here, but I don't think there are any circumstances where the extra examples you gave would be advantageous over the four examples I suggested (again, which of the four would depend on context). So although it's common to see the form $this->pages in modules it's actually more optimal to use $this->wire('pages') because it's more efficient (no extra check needed for a class property named "pages") and cannot clash with class properties with the same name.

(To be honest I personally do use $this->wire()->pages over $this->wire('pages') but that's just because it's easier to automate with macros in my IDE rather than for any other advantage).

  • Like 2

Share this post


Link to post
Share on other sites
4 minutes ago, Robin S said:

With the examples and documentation I think we should focus on illustrating things that a new user should use (depending on context) rather than all the things they could use. So we should take a best practices approach rather than trying to cover everything that technically will work.

Sorry for the confusion @Robin S - it was a failed attempt at humor 🙂

I was trying to make the point that there are way too many options - some are intentionally provided and some are just due to class inheritance etc, but I personally think we should be very careful to document just one default approach for all examples and then properly explain the other options and where they can/need to be different to the chosen default approach.

 

  • Like 9

Share this post


Link to post
Share on other sites
18 minutes ago, adrian said:

and then properly explain the other options and where they can/need to be different to the chosen default approach

Absolutely this needs to be covered in the official documentation. It's foundational stuff and too important leave to a scattering of forum discussions. I'd hazard to say there are many here who have been working with PW for years and are not 100% clear on this stuff (myself included).

  • Like 5

Share this post


Link to post
Share on other sites
On 1/14/2019 at 10:36 PM, ryan said:

What I'm suggesting is actually much simpler than you think, and is more specific and clear than using exclusively $var or var(). Please wait and see what I write up this week, and I think it'll make sense. Like I mentioned earlier, if you fully understand it and still don't agree about the benefits, then I'll reconsider, but for now trust me on this. 

I've been following this topic from the sidelines with mixed feelings. I've always considered ProcessWire's API exceptionally clean and easy to understand, and technically that hasn't changed, but I do find it confusing as well that there are so many ways to achieve essentially the same thing – except that some will only work on certain situations (bootstrap, templates, modules, multi-instance, ...) or may have performance benefits or perhaps won't be available on all sites depending on config settings, etc.

I'm very eager to hear what you've got to say about this, and I'm hoping that it'll make everything crystal clear again 🙂

---

Either way, the tab idea (different approaches in different tabs) is, in my opinion, awesome. Combined with per-tab instructions on where and how to use each approach (could be a tooltip with short summary and a link to full documentation page) this would be a huge improvement. If functions API calls are shorter, then show those by default – it won't take anything away from the marketing / functions API promotion perspective, and it may in fact give users a better understanding of what they're missing if they're not using the functions API.

---

On a completely different topic, one thing I've been wondering is if it would make sense to provide some kind of "interactive editor" for the API features – "tweak the code and see the result here". I know, ProcessWire isn't a JavaScript app, and the API has loads of stuff that wouldn't make any sense to implement in JavaScript, but perhaps as some kind of a virtual box (not sure how one would set that up securely, though) or a limited scope JavaScript mock API with a set of mock data behind it?

Just an idea for now.

  • Like 3

Share this post


Link to post
Share on other sites
9 hours ago, teppo said:

with mixed feelings

Me too. I also think that "mixing it up" for a newcomer the various ways to use the API is not a good idea, even the tabbed interface idea (which is great) feels a bit too much to present to a beginner. If the function API is the preferable one on the frontend, then all frontend examples should use that one only and only module related docs should use another one (which one is preferable in that case). There should be an article explaining all the other ways to do the very similar, and only in the "advanced" category. BTW, some docs tag pages/tutorials as beginner/intermediate/advanced. I think ProcessWire docs could use those too.

Edited by szabesz
typos
  • Like 3

Share this post


Link to post
Share on other sites
6 hours ago, teppo said:

On a completely different topic, one thing I've been wondering is if it would make sense to provide some kind of "interactive editor" for the API features – "tweak the code and see the result here". I know, ProcessWire isn't a JavaScript app, and the API has loads of stuff that wouldn't make any sense to implement in JavaScript, but perhaps as some kind of a virtual box (not sure how one would set that up securely, though) or a limited scope JavaScript mock API with a set of mock data behind it?

I've suggested this a couple of times above - making use of the Tracy Console panel - either as is, or more likely using the code behind it to have something that can be embedded in an iframe on the page itself. 

 

  • Like 4

Share this post


Link to post
Share on other sites

On the issue of page() vs $page it's actually unfortunate that page() can't be overwritten because I often use the Tracy console in the admin when editing a page. $page is automatically set to the page you are editing, but of course page() will return the "/admin/page/edit/" page. I don't think this is a valid reason to NOT promote the use of page() as the default approach, but it is something to be aware of.

  • Like 2

Share this post


Link to post
Share on other sites
15 hours ago, adrian said:

I've suggested this a couple of times above - making use of the Tracy Console panel - either as is, or more likely using the code behind it to have something that can be embedded in an iframe on the page itself. 

Right – I might've misunderstood those posts, thought you were referring to the demo site. Probably just me not paying enough attention 🙂

I've been doing JS related work recently, and found it really helpful how some libraries provide these interactive code blocks on promo sites and/or docs: "here's our example, here's what it does – try modifying it and see how that'll change things." Another use case are incomplete (or even empty) code blocks urging the user to figure out how to produce some predefined output from them.

Personally I dislike learning from docs alone, so this approach provides the best of both worlds: docs so I don't feel like I have to figure everything out myself, and editable/executable code to give me the opportunity to learn things by doing (and making mistakes along the way) 👌

15 hours ago, adrian said:

On the issue of page() vs $page it's actually unfortunate that page() can't be overwritten because I often use the Tracy console in the admin when editing a page. $page is automatically set to the page you are editing, but of course page() will return the "/admin/page/edit/" page. I don't think this is a valid reason to NOT promote the use of page() as the default approach, but it is something to be aware of.

Now that you mention this, I've done that on a few occasions too. While this may be a bit of an edge case, it's a good example of how something that may seems like an issue at first (overriding API variables by accident) can also be a good thing once you know what you're doing 🙂

(By the way, it seems that the wire-prefixed versions of these were missing from those lists of "all the different ways to access one API variable". Not sure how often people actually use wirePage() etc... but they've probably found their way to some projects out there. And, as is explained in the blog post introducing Functions API and in the FunctionsWireAPI.php file, this version has the advantage (over regular Functions API) of always being available.)

  • Like 4

Share this post


Link to post
Share on other sites
7 minutes ago, teppo said:

I've been doing JS related work recently, and found it really helpful how some libraries provide these interactive code blocks on promo sites and/or docs: "here's our example, here's what it does – try modifying it and see how that'll change things." Another use case are incomplete (or even empty) code blocks urging the user to figure out how to produce some predefined output from them.

Personally I dislike learning from docs alone, so this approach provides the best of both worlds: docs so I don't feel like I have to figure everything out myself, and editable/executable code so to give me the opportunity to learn things by doing (and making mistakes along the way) 

OT, but though to mention it here. I have been working on a site profile (still in alpha >>> it's been ages! other things got in the way) inspired by the Electron API Demos app that will do this and more. Essentially, it teaches you to use the API. On install, you get nothing but the 'blank profile'. You choose a topic and It teaches how to accomplish what is covered in that topic, e.g. the AP to create/edit/delete fields, templates, pages, etc.

  • Like 9

Share this post


Link to post
Share on other sites
30 minutes ago, teppo said:

Right – I might've misunderstood those posts, thought you were referring to the demo site. Probably just me not paying enough attention 🙂

Sorry if I wasn't clear - the idea was to have it one the PW homepage instead of (or in addition to) the API examples so potential users can actually play with them and generate output returned via AJAX - just like the Console panel.

 

17 minutes ago, kongondo said:

You choose a topic and It teaches how to accomplish what is covered in that topic, e.g. the AP to create/edit/delete fields, templates, pages, etc.

This sounds really great, but is there actually an interactive code console that can run code, or do you need to edit template files with your code editor?

  • Like 1

Share this post


Link to post
Share on other sites
32 minutes ago, adrian said:

do you need to edit template files with your code editor?

No.

Say you want to create a page. You click on create page, choose template , blah blah. The original thinking was then to display very short code snippets (the show you how to do it bit),  with each step, i.e. assign the template, assign title, (save) create the page, etc. However,  I now realise there's need to have this and a live code editor where you can play with the code (like in Tracy).

Share this post


Link to post
Share on other sites
13 hours ago, teppo said:

(By the way, it seems that the wire-prefixed versions of these were missing from those lists of "all the different ways to access one API variable". Not sure how often people actually use wirePage() etc... but they've probably found their way to some projects out there. And, as is explained in the blog post introducing Functions API and in the FunctionsWireAPI.php file, this version has the advantage (over regular Functions API) of always being available.)

Correction to this: in the blog post Ryan mentions the wire-prefixed Functions API methods and explains that they have the benefit of being always available regardless of config settings (essentially the same thing that the comments in the FunctionsWireAPI.php file say) – but there is a comment to the blog post in which he mentions that these are actually "for an internal core purpose".

@ryan, this might be one of the things that should be clarified somewhere: if wire-versions of the Functions API methods are indeed not intended for public use, it should probably be mentioned somewhere (other than a single comment to the Functions API announcement blog post). If one reads the blog post and doesn't check all the comments, or checks the code / code comments directly (which is a common thing to do in our context), this is currently not obvious.

  • Like 5

Share this post


Link to post
Share on other sites

By the way, I was just wondering what might be the recommended alternative to defining custom API variables (particularly by modules) for the Functions API? Is there one?

I for one have found these very useful, as they provide a way for module authors to add developer features that feel consistent with the "native" API. In case custom API variables are only feasible with the non-Functions API, then perhaps that should be documented as well; or am I just overthinking this? 🙂

  • Like 2

Share this post


Link to post
Share on other sites

A few more minor bits and pieces...

The left-side-only border on the three columns under the home page code samples looks a little off:

2019-01-18_105853.thumb.png.a8004092bf3f16a139a981f2f78e2f29.png

It would look better if the borders were only on the inside edges of the columns, like the three column example in the footer:

2019-01-18_105925.thumb.png.4127076a9e1c0cec08a780f2fc1c024d.png

 

I think others have already commented about the blog overview layout. I find this layout confusing to parse because the box alignment is stronger vertically than it is horizontally, which makes me scan the posts top to bottom when actually the order is left to right. Having equal box heights within each row would improve this somewhat but I think there will still be some confusion for readers trying to work out the order. Maybe we should consider an entirely different layout for this page?

2019-01-18_110538.thumb.png.4f918f243c5b6cf0e8e9505c61f705d2.png

Also regarding the blue box style - the are some small issues with the little circles on the corners. Sometimes they are stacking behind a neighbouring box so the line goes through the circle instead of behind it. This can be seen in the screenshot above.

And perhaps there should be a circle in every corner of each box (it doesn't matter if the circles are doubled-up where two boxes meet) because the visual logic of where the circles are missing doesn't make much sense in some places: 

2019-01-18_110559.thumb.png.1aabfd9e9c632527c1d23314967c57b1.png

2019-01-18_112638.thumb.png.2e786f0b6a830755907ef9ba661804b3.png

 

Lastly, I spotted a couple of little issues in some code blocks.

1. LSEP character showing here: https://processwire.com/docs/start/templates/
2019-01-18_110721.png.553c6c53df4a322217b7b5900999871f.png

2. $ variable symbol sometimes gets wrong colour here: https://processwire.com/docs/selectors/
2019-01-18_110634.png.9fc106d300f5edc264cb5a603f748619.png

  • Like 4

Share this post


Link to post
Share on other sites

@ryan - I have been thinking about that save() API example on the homepage and my complaint about the fact that as is it will fail with an error. It has made me wonder why the pages->save() method can't automatically turn off outputformatting itself? So I started looking around and found @thetuningspoon 's excellent thread here:
https://processwire.com/talk/topic/10485-simplify-output-formatting-when-saving-pages-via-the-api/ 

Obviously when saving via the admin, PW takes care of turning off outputformatting, so, I am curious why it can't handle this for us automatically via the API as well. I know you must have a good reason (you always do), but the only thing I can think of is that it's basically an educational thing - it helps users to understand what output formatting is. If so, I agree this is important to understand, but I still don't see why the save method can't do this for us.

Thanks for your thoughts on this.

  • Like 3

Share this post


Link to post
Share on other sites
16 minutes ago, adrian said:

It has made me wonder why the pages->save() method can't automatically turn off outputformatting itself?

I might have this wrong, but isn't the important thing that output formatting be off when you get and set values? It's not enough that it simply be off at the moment the page is saved.

Doing the following doesn't solve the "problem" of output formatting...

$page->foo = $page->bar . ' baz';
$page->of(false);
$page->save();

...and so likewise some feature that automatically turned off output formatting within the save() method wouldn't be a solution either. Output formatting has to be turned off earlier in the process of getting and setting values and PW can't automatically know when to do that, so it has be done manually by the developer.

Edit: to clarify regarding getting values - output formatting only needs to be off if you are going use that value in a field you are setting.

  • Like 4
  • Thanks 1

Share this post


Link to post
Share on other sites

@Robin S - That's a really good point about needing to turn of outputformatting before setting the field values. You're absolutely correct that it must before off beforehand. I knew I must be forgetting something 🙂

I guess there really is no shortcut for this, other than setAndSave() which is obviously one field at a time, rather than all fields on the page/template.

My only other thought is when would you want to actually set a field value to a formatted version? Could setting always apply unformatted values? I guess this gets messy because you never know how the developer might want to handle things so I suppose the current situation is probably the most flexible option. 

I'll go hide now 🙂

Share this post


Link to post
Share on other sites

I have an interesting scenario for you though. Say you try this:

image.png.f0deaf8fe6b7656fad3833ff532e85ec.png

So then you try:

image.png.9a2ff6edb2412213cb24693df2c54b36.png

which of course also doesn't work if you're not actually on page 1023.

So maybe it's a simple matter of changing the exception message to not specifically state:

$page->of(false)

because that could cause new users some pain.

Hopefully they won't be mixing $page and page() calls, but if they did, then it would be confusing.

Share this post


Link to post
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

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...