Leaderboard
Popular Content
Showing content with the highest reputation on 11/03/2022 in all areas
-
@bernhard I know you've put a lot of work into your module and I can see why my post pissed you off (to be honest, after I posted it I thought about removing it because I was worried this might happen). I did "test drive" RockMigrations last week. Unfortunately, my test drive started with me trying to create and migrate a ProField for a project I'm working on, and the result was that my new field's settings were wiped out each time the migration ran. Then I read a post you wrote that made it sound like you didn't plan on supporting ProFields and didn't understand why anybody would have need for them since you don't use them yourself. All of our projects use ProFields, so it's a showstopper for us if these aren't going to be supported. And I don't feel like I should really have to justify that need and I'm not interested in arguing about it. That's why the system that I have in mind would use the existing JSON export/import mechanism from the core, which already supports migrating ProFields, and presumably will continue to support any new 1st party field types that are built. It would just bolt onto it and make the export/import process more automated. And as I described in my last post, it would be agnostic about the order of the field and template definitions so the user wouldn't have to worry about dependencies with order of import. So I'm not really sure what to say. There's no reason why we can't have more than one approach to this. You're saying that you're interested in feedback, but then it feels like you're mocking our ideas. If you think our ideas are stupid or too limiting or whatever, then at least let us have fun with them on our own :-) EDIT: I just looked over the processwire-requests thread on Github again and I see that some other people who have gotten deeper into this already have reported issues with the core JSON export/import module that would need resolving before certain fields could work. Other than the FieldtypeOptions I haven't had many issues lately in my experience. I also saw that you expressed interest in supporting the Combo field in that thread, so I apologize if I've misinterpreted. If RockMigrations can support my fields and desired workflow with just a bit of additional development (from either you, me, or someone else), then I would certainly prefer that to having to write a new module from scratch! Also, I have to say that your car analogy had me in stitches after reading it fully from start to finish. :D I agree in theory, but I would personally rather err on the side of caution. Neglecting to delete a field or template doesn't effect the operation of the system, but deleting one unintentionally (I'm picturing something like a merge conflict being resolved incorrectly) would require restoring from a backup. I see the list of deleted templates/fields as still declarative in the sense that it doesn't matter what order they're in or when they're added. It's just saying "these fields and templates should never exist". Anyway, I can see wanting it to work either way. So this could simply be a matter of a setting in the module.6 points
-
Hi all, Im sure you guys can point me in the right direction. Im a former web developer from the days where you opened notepad and type tags to build a page, but havent done that for probably a decade or so. I have a little experience with CMS using wordpress but this is the first time I have come across processwire. I work for a tiny company who got a 3rd party to create their site and now need a few changes. Is there an idiots guide or such as I cant even work out how to amend things like css files or how to add google analytics tags to the head of each page. Be gentle im probably old enough to be the dad of all of you! Thanks in advance Mike2 points
-
Hi @MikeF77 welcome to the forum and to the world of processwire ? The thing here is: ProcessWire is very different to other CMSs in that it does not dictate HOW things are done. It just tries to make all the complicated things easy so that you can focus on building your ideas rather than having to fiddle around with all the technical parts. So for example it helps you to resize images properly ($page->your_image_field->maxSize(400,300)->url), but it has no default way of how images are managed. So there is no central media manager or such. That might be important to understand when looking how things are done. That means in your case you don't need to understand how ProcessWire works, but you need to find out first how the company built the website. To understand that you could inspect the file /site/templates/home.php --> that is the template file for the home page and it is rendered when anybody opens http://yoursite.com Maybe you could share the content of that file? Or a screenshot. Without any sensitive information of course. Then we could maybe give better instructions ? Or maybe with the video posted about things are already clearer? Also have a look if there is maybe a file /site/templates/_main.php ? Let us know what you find and we can help I'm sure ?2 points
-
Hi Mike, welcome, as you are used with Notepad, then you are on the best solutionware to keep using it, easier than wordpress really. Read a bit there and choose an output strategy that feel your dev experience (biased suggestion: Delayed Strat.) : https://processwire.com/docs/front-end/output/ https://processwire.com/docs/tutorials/default-site-profile/ Then watch this vid: And enjoy ? edit: before you ask, when you will stumb on some ten years answer forum thread, yes they almost still work in 2022. But at least upgrade your php 3 install ?2 points
-
It is something I have used a little bit when the alternative would be too many additional fields created in the list that are just taking up space. Say if I have a set of fields that I know are only going to be used in a single field group, it makes sense for me to store those in a combo field because I never plan on calling them independently. For example, if I have a product, odds are good I may pull the product title in a number of different contexts, and perhaps prices and variants - so I'll set up normal fields for those. But things like manufacturer, dimensions, weight, checkbox features, warranty length, UPN etc. are things it doesn't necessarily make sense to have a separate field for because outside of the context of recalling a particular item/page, those fields are never referred. I see it as the difference between having a sort of 'local' field group where everything is 1:1 and bound to view together, vs a 'global' field where I may want to include it of view in it context with other templates, other indices, other tags, etc. That being said, I have also run into situations where I have a value that originally is in a combo field, but then we discover that we want to actually build that piece of information out into a separate template entity - so it is most valuable when you plan ahead. Things like testimonial entries, product reviews, these each have multiple fields, but honestly, they could each be put on a card and stored away - there is no real value that any single field in the group has independent from the card - indeed, sometimes having the information in separate places can sometimes make the information more confusing and less valuable.2 points
-
@bernhard Thanks for the clarifications. I think we are on the same page now. Regarding the order agnostic application of migrations, I had assumed that it was not order agnostic because of something you said to me in the RockMigrations thread about defining dependencies after creating fields/templates. does this also work when you have migrations spread across multiple files? I guess I am also a bit confused about the difference between using the migrate() function and using the createField() and createTemplate() functions. Is it just a matter of preference or are there differences in how these are processed (i.e. do you need to put everything in a single migrate() in order for it to be order agnostic)? I didn't see anything about the difference between these functions in your documentation and it took me a while to figure out that I should use the migrate function when copying and pasting the data from the field/template back end editor.2 points
-
<?php namespace ProcessWire class FooPage extends Page { // "location" one public function migrate() { $rm = $this->wire->modules->get('RockMigrations'); $this->cleanup($rm); $rm->migrate([ 'fields' => ['foo', 'bar'], 'templates' => ['footpl', 'bartpl'], ]); } // "location" two public function cleanup($rm) { $rm->deleteField('baz'); } } RM does not have this approach. But you listed that as "another approach could be" so I did not take that into account. I was not sure what you meant by "outside changes" and with your latest post I see that you where more thinking of a GUI way rather than a code solution. So my 100% are maybe a little too much and I'd say you did an 80% description of RM ? But I still don't think it is a good solution. Think of the excel macro recorder... It produces a total mess and you have no control what it does. I don't want that for my projects. I understand that it could work and I'm thinking about that all the time, but I still don't have a good solution. If someone else found it: PERFECT! Please let me know!! I released the module for free so that everybody can use it, everybody can see the code and improve it. But instead of doing that I see a lot of people begging for "a way to go to the mountains". That's what annoys me. It's the way they talk about ProcessWire and RockMigrations. And that's what I tried to express with my story about the mountains. It's a totally different story if you say "I want to go to the mountains and I tried your car, but I had a huge tent with me (proField) and it did not fit into the baggage compartment (was not supported by the createField() method). PS: RM works the other way round: You write "code" (it's actually a lot more plain PHP arrays that represent field/template settings) and the changes appear in the backend like magic (when using RockFrontend for live reloading as shown in the video). 100% RockMigrations: First it creates all fields and templates: https://github.com/baumrock/RockMigrations/blob/df2ccefe2df49134c16b622c07e308864880827b/RockMigrations.module.php#L2177 And then it applies all settings: https://github.com/baumrock/RockMigrations/blob/df2ccefe2df49134c16b622c07e308864880827b/RockMigrations.module.php#L2198 You explain 100% how RM works in the paragraph above and end with "unless someone else hasn't already gotten to it". ? I know how you mean it but maybe you can understand that it's not nice to read for me... You are quoting me totally wrong here. I did never say that I don't understand why anybody would have a need for them! Quite the contrary, I've bought almost all if not all profields. Some because I use them on every project (ProCache), some because I used them in older projects before I had my own solution (RepeaterMatrix) and some just to support Ryan's great work and free CMS that has helped me in so many ways and is still so much fun to use. I'm just not keen on adding support for them in my spare time, for free, for people that don't contribute anything to our community. It would be a totally different story if someone asked me to add support for it and sponsored that addition. In RM1 that happened and I see no reason why that should not happen in RM2. And I also see no reason for not adding a trailer hitch to my car so that others can use it with a trailer to bring all their baggage to the mountains... And I don't think I have to justify that ? At the moment no, but I'm happy to accept PR's in any of those directions and for example the last one would be extremely easy to add ? For Field/template cleanup I want to add that we both know that this is an unfair argument. You know that this would mean that you'd need to list EVERYTHING in your config before, so that you can afterwards remove one part and make the module remove that as well. So while that might sound a little more comfortable it is just so much more bloat and has so many drawbacks that I thought it would be better to just add those things that are defined in config and if I wanted to remove something simply use deleteField() or deleteTemplate() etc. But it does not mean one could not build it that way. But again: Why should I build that if I don't work that way? Give me a reason and I'll do it (if you don't want to). Yeah I don't know exactly what problems I had, but I've tried using the internal export/import syntax (as it sounds so obvious and good), but it somehow did not work for me. I might revisit that at some point but I had to get things done so I implemented the array syntax (which is by the way a lot more intuitive to use for humans than the core export/import syntax that is built for computers). I don't see any reason why RM should not be able to support any other field. RM is just an abstraction layer between the human brain and the PW API. The admin interface uses PW API to write GUI interactions into the PW database. So you could also just use PW api if you wanted. But I realised that using the PW api for creating fields/templates/etc is really not as easy as it could be (see createField() as an example) and it does not work the way the human brain works. And our brain works the way the PW GUI works, so we think "create a new template" and we don't think "create a new fieldgroup, then create a new template and assign that new fieldgroup to that new template". At least my brain works that way. And that's all RM provides. An easy to use API that can do anything for you that the PW GUI can do (and even more). Everything that we have in the GUI we have in the core API. RM just provides helpers to trigger the right methods in the correct order and catch edge cases etc. If you find a way to use core json export/import for RM then great. Please let me know and we can work on a solution that supports profields out of the box! Glad you had fun reading it ? I didn't want to offend you @Ivan Gretsky but sometimes people need a helping hand and sometimes they need a kick in their *** and it's not easy to know when they need what... It sounded like you really want to do migrations so I thought maybe you need a push. If you need help I'm happy to answer all the questions you have. Just please be precise in your explanations and don't do "I tried it but it simply did not work" kind of feedback... Because others might be reading that and might get a wrong impression. And well, yes, I'm happy if people are using the module and liking the module, since that is the only "reward" I get from it (besides being a lot more productive and a lot more professional in my daily work).2 points
-
1 point
-
On many of my sites I have a page for business information which includes: toggle for site down for maintenance or live combo field for business name, address, phone, email, contact name, etc functional field for common phrases The combo field is great in this scenario. The data is fairly static and I only need to add the one combo field for a bunch of 'sub' information, bits of which may be used throughout the site. The alternative is to create a fieldset with individual fields, all of which would only be used in a single template and have one entry per field.1 point
-
@Juergen I needed a solution to start with a quite complex form. I tried the module, thats was fast. Freaking cool ! Thanks .1 point
-
While I'm not using it in real world project yet, the Combo field works well for a "link" field. For example, you could link something to a page (page field), a external website (url field) or a modal (page field), or a page + url parameters. Also, what about absolute vs relative URLs? Here's an export of that field you can import and play around with: https://pastebin.com/N8UuiFKQ Somewhat related is this module:1 point
-
I think I would go with - raster - image masks, like mentioned here: https://css-tricks.com/almanac/properties/m/mask-size/ Nowadays the support is very good and it covers the problems you are facing.1 point
-
Sorry, I didn't see this comment before my previous post. I know that RockMigrations does not remove fields and templates unless you explicitly request it to. Does RockMigrations support the additional features I mentioned? Automatic update of config files when changes are made in the admin (I know it offers the copy & paste feature, which is a great start and preferable when using multiple migration files) Order-agnostic migration Field/template cleanup function for those not defined in migration files Option to only apply changes manually via cli or button press in admin1 point
-
@DrQuincy, you could use JavaScript to remove any disallowed characters from the input if the href is a tel link: $wire->addHookAfter('ProcessPageEditLink::execute', function(HookEvent $event) { $event->return .= <<<EOT <script> $(document).ready(function() { $(document).on('blur', '#link_page_url_input', function() { var href = $(this).val(); // If the href is a tel link if(href.startsWith('tel:')) { // Remove any disallowed characters href = href.replaceAll(' ', '').replaceAll('(', '').replaceAll(')', ''); $(this).val(href).trigger('change'); } }); }); </script> EOT; });1 point
-
Looks like MarkupHTMLPurifier used to skip tel: links in the past due to HTML Purifier not supporting them. This bypass was removed in 3.0.137, so after that version tel: links have likely had to adhere to stricter rules. I would likely go with this option, to be honest. But perhaps someone else knows how to customize Purifier — I've tried it once or twice, but eventually had to give up ?1 point
-
I do use Project Manager already and it's definitely a must have extension. Cool. Whilst we're sharing tips though - on a Mac you can set up a Quick Action in Automater to open a folder in VS Code: the command I've got in that Quick Action is open -n -b "com.microsoft.VSCode" --args "$*" On my Linux box I'm using Dolphin on KDE and get offered the option to 'Open with VSCode' when I right click on a folder ... I think thats just happens by default; I don't remember ever setting that up.1 point
-
If you can believe it, I could have really used that feature just this saturday, when I had to downlod multiple images with a fiddly laptop touchpad ? I’ll check out your SASS module (I’ve often wondered why that’s not the predominant way to do it, actually. Sounds awesome!) and get a PR going, but it’s going to be a couple of days.1 point
-
That's quite an expressive post, @bernhard! I am actually a pretty slow driver. My Renault is no racing car, and that's because I never wanted to race) And when I need to go a long way (like, to the mountains), I actually try to take a train, so I can have some (root?) beer and yes, chips, along the way and not exhaust myself driving. So you're right - at least in describing me) To my defense, I can say that I actually did install your... car... in my remote testing... garage. And now I am testing how it is showing itself in a... no load situation. But you're right - I (we?) could go faster out of that garage to the mountains (I would rather go to the sea, but nevermind))) Getting rid of those comparisons... yes, I am kind of picky here, as migrations / versionable config is something that can easily break things. ProcessWire is a really author's project, so I am used to be inclined to choose 1st party solutions. But I've already read the source code and tested in a few different ways. Long things short - agreed, I need to get in you car and step on the gas))) Will do so and report back! Still this topic is about something similar, but a bit different than migrations - another way to store configs. So it interesting to me see how things go here. And, as always, Ryan's say on this is a big thing to me. And he still didn't answer in that issue).1 point
-
@thetuningspoon I completely disagree, because that is farther removed from the goal of having a declarative dec config and closer to the territory of migrations. You don't want to give the system a list of instructions on how to build the correct state, you want to have a declarative list of configuration values that describes the correct state. Getting there happens under the hood. Similar to the difference between declarative or functional programming and imperative programming - you only describe what to do, not how to do it. The system can compare the list of fields in the config and in the database, add and remove fields as needed, and update config values. Combined with version control, this allows you to go back seamlessly to any previous state, revert changes to the declarative config etc, which is something that migrations struggle with, as mentioned. I understand the hesitation to have the system outright delete anything that's missing from the config, but that's just a combination of not going 'all-in' on the declarative config, or not embracing some important workflow changes along with it. You want the config to be the single source of truth for the state of the project, independent of any existing installation or database. If you take an existing 'base' state (for example, tracked in version control as a database dump of an existing installation) and only include changes relative to that base state in your config, you're not there all the way. You want the config to include everything, every field, template, setting, installed plugin, etc. This way, a new installation (for example, a staging environment for a specific feature) can ideally be created with a single console command. Once you have that, you don't have to worry about having the system delete fields that aren't in the config, because deleting a field from the config requires the same amount of effort and has the same visibility in your quality control pipeline as adding one. The rest is just a question of workflow. Changes to the config should be tracked in version control, and merging those changes should require an approved pull request (if you're working in a team). Deleting a field is just as much of a change that is visible in the PR as adding one, since you will see the deleted field config in the PR and make sure that this is really what you want to do. Once you have a solid workflow in place, you can confidently delete everything that you no longer need, because you know you this change will go through review and quality control, and you can get it back through version control if you really need it again in the future. Of course, mistakes still happen. Turns out the client still had some vital data in that field you removed? Well, that's what backups are for. The first step in every deployment script should be a backup. Yes, absolutely. Though in a perfect world, changes to the config are only made in development environments, tracked in version control, and then deployed to the live site (after any staging environments in between). Pulling the config and applying it should be done as part of the deployment script. This way, there is rarely a need to have a button in the backend that applies the config (though this is still useful for development). The more you can automate deployments and get rid of manual steps, the better. This allows you to work in smaller iterations and get features out faster and with more confidence. The Phoenix Project is a great read on that subject!1 point
-
RM1 had support for RepeaterMatrix so it would likely just be copy&paste: https://github.com/baumrock/RockMigrations1/blob/1ee9f9eb4afaf83529bcedf443b31dd63a5403c8/RockMigrations1.module.php#L1336-L1384 So if you think RockMigrations is missing anything why don't you stop complaining and start asking me if it is already possible or if I can implement it? Why do you think that? ----------- Sorry, but I have to say I'm getting a little pissed with you guys talking about migrations. It's like you were sitting in front of your TV eating chips and watching a documentary about mountains. And you say: "Wow, that views are so great. It must really be awesome to see that in real life! I've dreamed about that for a decade (yep, quoting you here @Ivan Gretsky ? But I don't mean you exclusively with the protagonist in that story )." And then I tell you: "I built a car. It stands in your garage. You simply have to get into it, learn how to drive and 5 hours later you are there! It's great, I'm going there all the time and it's such a great experience and once you've been there you'll never want back. Ah, forgot to mention: You can take my car for free!" And you: "Oh, well... Thank you... I totally appreciate that. You know... it's just... driving a car?! I've never been driving a car... And... You didn't say anything about the car-radio... Does it even have a radio? You know, it's so important to me, because I always hear the news on radio!" And you continue eating chips and watching TV... Me: "You'll learn how to drive in 10 Minutes. It's an automatic car. The previous car had a manual gear shift, but the new car that I built has automatic gear shift, so you really just need to sit in, steer the wheel and push the break or the gas pedal." You: "Well... I'm afraid I could cause an accident! That's really kind of you, but I'd much more prefer if there was a train to that mountains! That would be great! I'm sure the one that builds the train thinks of everything that I need. A radio. I could even take my Laptop with me and watch TV during the ride. I'd be the first to buy a ticket for that train (yep, quoting again)!" You continue eating chips... Me: "Sure, I was also afraid when I first drove a car. But believe me: It's really not hard! And you can go really slow at first and of course, you don't start driving that car on a real street! You go to a big free area where no obstacles and no people are so that you can't hurt anybody or yourself. I have even made a video about how to drive the car." You: "Ok wow, thank you, I have to try that!" You eat the rest of your chips. --- one month later --- Me: "Did you drive the car already?" You (eating chips and watching docs about that great mountains): "Oh... well... yes... I tried... But it does not work. I think I'll wait for the train to be built!" Me: "Ähm... Why? What is wrong with the car?" You: "Nothing... it's just... it is too complicated for me. It's for sure great if you drive cars daily like you do. But for someone like me it's too complicated. It would be much easier to go by train. That would be so great, that mountains look so awesome. I'd love to go there one day." You open a new bag of chips. -------------------- Get your *** up and stop eating chips! Watch that movie and get into that car! Go to a free and safe area and practise. Once you did that I'm happy to hear feedback how the car could be improved. Maybe we need to add cruise control. Or maybe we need to put sunglasses in the car. Or maybe we need to place a sticker on the outside of the car that says: "If you want to drive that car you have to enter on the front seat where the steering wheel is. You can't drive this car from one of the back seats." Or maybe you say "I've tried. I drove the car two hours, but it was terrible. It was loud, it was exhausting. I was not able to watch TV while driving." That's fine. If that is really what you want, then the car might not be the best choice for you. But one of my points is: We have that car already! The train would have to be built. If it is only about you not being able to stop watching TV and eating chips you could also pay someone to drive the car for you. Or you could pay me to add a self driving mode into that car. And for the noise: I'm happy to get those reports and then we can decide if it's something to take care of (to make sure the car does not explode while driving) or if it would be enough to just use oropax until the car get's its silent driving mode. Another point is: I know that it sounds totally great to get into the train, continue watching TV and eating chips and arrive relaxed at the mountains. But you can't go anywhere else. With the car you have the flexibility to go anywhere. And you can go on top of the mountain whereas on the train you'll arrive at the train station and you have to go the last mile by foot. So jump into that car and stop asking for a train by pretending that there is no other way to go to the mountains! Do you get my point? I'm not against having a train to the mountains. But @thetuningspoon's message is like saying "I have thought about it. To go to the mountains we'd need a vehicle that can carry passengers. We'd need an endurance of at least 6 hours, because the mountains are 5h away. It should drive forward by default. Going backwards should require an extra step of caution because it might be more dangerous to push back with that vehicle." Me: "Yeah, you are describing my car." You: "Hm. I thought more of something like a train..." --- So if you don't want to ride that car for whatever reason: Please start describing your train properly and add notes what should work differently to the car that we already have and why. PS: Read the title of this thread... "Build a vehicle to go to the mountains and add gps tracking". Did I already say that my car has gps tracking??1 point
-
@horst Well then, allow me to raise your expectations again, because your description is not how it works ? In your scenario, both developers could merge their branches with zero conflicts, and as a result the main branch would incorporate all the changes from both branches. They don't even need to know what the other one is doing, and nobody needs to constantly keep up with changes from other branches / team members. That's because git is really smart in the way it performs merges. Basically, you can view every branch as a set of changes applied to the existing files. As long as those changes don't conflict, you can merge in multiple PRs back to back without any manual conflict resolution. So most of the time, you can just lean back and everything works. The only time you get a merge conflict that needs to be resolved is if there are actual conflicts that require a decision. For example, if developer A renames some_old_field to unicorns and developer B renames the same field to rainbows, that would result in a merge conflict, because a single field can't have multiple names. So someone needs to decide between unicorns and rainbows for the field name. In other words, you don't have any overhead caused by git itself – git acts as a safety net by warning you about merge conflicts so you can fix them. In a well-engineered system with good separation of concerns, it's rare to have non-trivial merge conflicts, since it's unlikely that two people working on separate features will need to touch the exact same files. And most of the time, if you do get a merge conflict it's trivial to resolve – for example, if two PRs add a new variable to our SCSS variables in the same place. This would be a merge conflicts, but it's trivial to resolve, since you know you want both changes. If you know git well, you can resolve those in under a minute, oftentimes with a single command (by specifying the appropriate merge strategy for the situation). It's the exact opposite – the larger the development team, the more you will benefit from this streamlined workflow. Everyone can focus on different features and merge their work in with the minimum amount of effort required by either them or other developers to keep in sync with each other. Regarding all the git stuff, I recommend the Git Pro book (available for free), a great resource to understanding how git works under the hood and discover some of the lesser-known features and power tools. Reading the book front to back helped me a lot to establish our feature-branch workflow (for Craft projects) at work, utilize git to work way more effectively, solve issues with simple commands instead of the xkcd 1597 route and much more. For branching and merging in particular, check out the following chapters: 3.2 Git Branching - Basic Branching and Merging 7.8 Git Tools - Advanced Merging1 point
-
Ok, working now, I changed the date picker to include an actual time too and tested: // blog-index.php <ul class="list-unstyled"> <?php $entries = $pages->find("template=blog-entry, sort=-postDate, limit=5"); foreach ($entries as $entry): $daysAgo = $datetime->relativeTimeStr($entry->getUnformatted("postDate")); ?> <li class="py-1"><a href="<?= $entry->url; ?>"><?= $entry->title; ?></a> - <?= $daysAgo; ?></li> <?php endforeach; ?> </ul> ...and: Gotta start checking that API reference more often.1 point
-
well... in theory... ^^ I just tested it: jpeg 3888 x 2592 original file size: 5,1 MB ==> hits the PHP limit same image after saving it again with only 50% quality jpeg 3888 x 2592 new file size: 0,8 MB ==> does not hit the PHP limit, scaling works as expected I expected these results because reducing the quality does not reduce the actual size of the image but the number of information (e.g. in the first example every pixel has it's own color definition while in the second example color information is combined e.g. 4 pixels contain the same color ==> file size is reduced) but maybe @horst is deep into the theory and might be able to explain how it really works1 point
-
It's not only the same error in the log, but you're also doing the same thing wrong. You can't use $pages in functions because of variable scope. ProcessWire makes these object automatically available for the scope of the templatefiles, but inside a function is a new scope, so you need to either redefine the variable itself or use a function to get the object. // Template scope $id = 15; // simple variable, defined by you $pages = $pages; // the pages object, defined automatically by processwire function something(){ // this is now a new variable scope // neither $pages nor $id are available here. // the api variables are not a special global variable $pages = wire('pages'); $pages->find(""); // OR just wire('pages')->find(""); } It's the same reason, why you can't use $pages in modules. $page/$pages and the other variables are just convenient to use in templates. Everywhere else you need to call them differently.1 point