Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 11/27/2021 in all areas

  1. This is a holiday week here in the US, at least for my kids (school break). With kids home I've been off work this week so don't have any ProcessWire updates to report, but I'm looking forward to getting back to work next week and will have more updates to report then. Yesterday was Thanksgiving here in the the US and that kind of marks the beginning of the holiday season here. So today the Christmas tree went up, the lights are coming out and the holiday music has taken over the radio (or Alexa or Google or whatever we call it). Cheers and Happy Holidays!
    10 points
  2. Hi, welcome to the ProcessWire forums! The questions in your recent threads are kind of broad and it’s difficult to tell what exactly you’re struggling with and what you already know. I’m assuming you have ProcessWire installed and working, and you want to save some user inputs from the frontend into the fields you have created in PW’s admin area. Saving fields using the ProcessWire API First of all, you need a page to hold the data. Perhaps this page already exists, then you just get it using selectors, or maybe it’s the page you’re already on. Likely you want to save a new page for every time a user fills out the form, so let’s create a page: $p = new Page(); $p->template = 'form-submission'; //or whatever your template is called $p->parent = wire('pages')->get('/submissions/'); //or whatever the parent page is called Nice. Now, to get the information from the form you’re going to need ProcessWire’s input capabilities. You can find out all about it at the link and you’ll need to make some decisions about validation/sanitization depending on the data you’re dealing with, but the gist is to get stuff from the POST request sent by your user and put it into fields. Let’s say your user submits their e-mail address and you want to save it to a field called email: /* You see the name “email” three times: * 1. The first is the field you set up in the admin area. * 2. The second is the sanitizer that makes sure the thing the * user sent you actually looks like an email address. * 3. The third is the name of the input from from the form the * user filled out and submitted. */ $p->email = $input->post->email('email'); //Now you will probably want to fill out some more fields the same way: $p->comment = $input->post->textarea('comment'); $p->title = 'Form submission from ' . date('Y-m-d H:i'); Then you save the page and you’re done. You can go to the admin backend and check out the newly created page. $p->save(); However, we haven’t talked about the frontend bits yet. Creating a frontend form and sending submissions to ProcessWire Once again much depends on what you actually want to do, but for simplicity’s sake, let’s say this all happens on the same page. You have a ProcessWire template associated with a template file and all the above code is in it. Now we put the form into the same file. Basically the form is sent to the same page it’s coming from, but as you’ve seen above, you can still create the new page wherever you want. So here’s a simple HTML form that submits to the same page: <form method="POST" action="<?php echo $page->url; ?>"> <label for="email">Your e-mail address</label> <input name="email" type="email" /> <label for="comment">Your comment (no swearing!!!)</label> <textarea name="comment" rows="5"></textarea> <input type="submit" value="Send"/> </form> Note how the names of the input fields match the names we accessed earlier using $input->post(). Putting it together If you simply copy all my code blocks into your template file, you’ll probably notice that it tries to create a new page ever time the page is loaded. You’ll need to figure out if there is a form submission at all before you deal with it, and otherwise just skip that part and show the blank form. You may just check if there is anything in the comment variable. So here is your complete template file: <?php namespace ProcessWire; $thanks = ""; if ($input->post('comment')) { $p = new Page(); $p->template = 'form-submission'; //or whatever your template is called $p->parent = wire('pages')->get('/submissions/'); //or whatever the parent page is called $p->email = $input->post->email('email'); $p->comment = $input->post->textarea('comment'); $p->title = 'Form submission from ' . date('Y-m-d H:i'); $p->save(); $thanks = "Thanks a bunch, we value your feedback!"; } ?> <!doctype html> <html> <head> <title>Post a comment</title> </head> <body> <?php if ($thanks !== "") { echo "<h1>{$thanks}</h1>"; } ?> <form method="POST" action="<?php echo $page->url; ?>"> <label for="email">Your e-mail address</label> <input name="email" type="email" /> <label for="comment">Your comment (no swearing!!!)</label> <textarea name="comment" rows="5"></textarea> <input type="submit" value="Send"/> </form> </body> </html> Now I’m not saying you should put this exact code on your website, but it’s a demonstration of the most bare-bones things you’ll need to get input from users: A HTML form that generates a POST request and some PHP code to receive it. It doesn’t matter where these things are or what they’re called or how they’re generated. In this example we’ve written the form by hand because it’s easy, but you could just as well generate it from ProcessWire’s fields.
    2 points
  3. ProcessWire is an excellent framework for building just about anything, with great tools for permissions, input fields, and creating data structures. With the Combo and Table profields, it's possible to handle just about any data. These fieldtypes show the potential of ProcessWire to handle SQL tables in a more 'traditional' SQL table format, which leads to one area I wonder might have potential for a new feature. In addition to ProcessWire, I also do some work with ASP.Net Core, and one of the nice features it has is the ability to work with existing SQL databases, so that you can either build your models in the framework, or use existing SQL Tables. While working with any SQL data is possible in ProcessWire, it's a lot more hands on, with less built-in support. InputFields and FieldTypes are separate, and there's no reason why an inputField can't be used for data input for any kind of data, and indeed there are some modules that use inputFields to edit custom table data. What would be an amazingly useful addition to ProcessWire would be a module that allows mapping of inputFields to fields in an arbitrary SQL table without modifying the structure of the table itself. This is something the open source Directus project does by using metadata tables to store data about to display input for existing SQL tables, without touching their structure, but documentation isn't great for that project. I think ProcessWire has all the plumbing in place to enable this kind of functionality, and the Combo fieldtype gets pretty close, but still requires the combo table records to be associated with a ProcessWire page. Obviously, existing SQL tables won't automatically map to pages, which means directly accessing them on the front-end via URL automatically isn't possible, but often this isn't required as they may be for backend use only, or for consumption within a ProcessWire page. The recent support for URL/Path hooks though, means that if there is a need to directly access existing SQL on the front end via URL, it should be possible to create a hook to do so. I think adding the ability to create backend data entry for existing SQL tables would fully complete the ProcessWire philosophy of getting out of your way and not making assumptions about your content. It's currently already best of class in terms of doing this regard to front end presentation, but it's still a bit opinionated about data structures at the back end. This is absolutely fine if you're building a web app from scratch, and works really well in most cases, but there are times where being able to quickly incorporate existing data structures would be useful. To be clear, this isn't a replacement for the existing pages model, as that would be a huge and unecessary task to completely re-engineer ProcessWire, but rather an enhancement that can sit alongside all the good stuff that's already in ProcessWire so that it's possible to get ProcessWire to handle existing SQL data tables on the backend as neatly as it already does with its own data.
    1 point
  4. In my case clearing ProCache would be more than enough. This can be achieved in two ways in my opinion: 1. Clear ProCache cache button in admin bar. Will clear the caches for current edited page in all active languages. The downside of this can be that not everyone is using ProCache and they might have a useless button in the bar. 2. Alternatively and probably the easiest way would be to insert/display “Save” button In admin bar. By pressing Save will have the same functionality as option 1. Thanks for considering this!
    1 point
  5. 1 point
  6. Hi @Jan Romero Yes, I've solved it, but I don't remember what actually was causing this problem. What is your collation / encoding type? Have you tried to set $config->dbCharset = 'utf8mb4';
    1 point
  7. I can confirm this. It's like the order of the field names is treated as if they are in order of priority, but I don't think this is expected - all the fields in the OR condition should be treated equally. Could you please open a GitHub issue so Ryan is alerted? https://github.com/processwire/processwire-issues/issues
    1 point
  8. It looks like has_parent now supports multiple pages and I think it has served all my needs around this. What can't it do in your use case?
    1 point
  9. In that case, the most straight forward approach is to add a custom permission through the backend (e.g. 'import-pages'), hook before your module's execute method and check if the current user has this permission. Untested code for site/ready.php: <?php namespace ProcessWire; wire()->addHookBefore("ImportPagesCSV::execute", function(HookEvent $event) { if(wire('user')->isSuperuser() || wire('user')->hasPermission('import-pages')) return; $event->return = '<h3>You do not have permission to import pages. Please contact the administrator!</h3>'; $event->replace = true; }); Of course, this still leaves the backend menu item in place, but unlike modifying third party modules, it is upgrade safe.
    1 point
  10. This is what I do, which is almost like (2). site/config.php: <?php namespace ProcessWire; if(!defined("PROCESSWIRE")) die(); // Other PW default config values... // ... $config->dbHost = 'localhost'; $config->dbName = 'example_site'; $config->dbUser = ''; $config->dbPass = ''; $config->dbPort = '3306'; $config->dbCharset = 'utf8mb4'; $config->dbEngine = 'InnoDB'; // Environment overwrite if (file_exists(__DIR__ . '/config.local.php')) { require_once(__DIR__ . '/config.local.php'); } config.local.php: <?php namespace ProcessWire; $config->dbUser = 'example_site_user'; $config->dbPass = 'example_user_pass_123456'; config.local.php is in .gitignore, so never committed, and separate config.local.php files exist on testing / live environments. (I use DeployHQ and this is added as a config file that gets deployed with the rest of the code). To me, the benefits of this approach means that the entire config can be changed depending on the environment, and used to turn things on or off, like debug or advanced mode.
    1 point
  11. @teppo Hi. It would be great to have a note about PageRenderNoCachePage session variable in the docs, it took me some time to understand the reason for the non-worked cache for some pages.
    1 point
  12. I'm not sure what I was talking about back then, but you can simply do something like this: <?php namespace ProcessWire; class MyPage extends Page { public function init() { $this->addHookAfter("ProcessPageEdit::buildForm", $this, "buildForm"); } public function buildForm(HookEvent $event) { $page = $event->process->getPage(); if(!$page instanceof self) return; // $page is a MyPage object now $form = $event->return; // get the title field and add a note if we find it if($f = $form->get('title')) { // note that we use $page->foo() and not $this->foo() $f->notes = "I am a MyPage object and my foo() method says: ".$page->foo(); } } public function foo() { return 'MyPage-Foo!'; } } Note that the hook in this example never gets executed! You'd need to trigger it once. Where you do that is up to you - I'm usually doing that via RockMigrations (https://github.com/BernhardBaumrock/RockMigrations/blob/5cafb3c6c0f2004b8d4087ca243cc0d5f771dd11/RockMigrations.module.php#L377) but you could also add it in init.php <?php $tmp = new MyPage(); $tmp->init(); This adds a little overhead since we load an additional instance of MyPage on every request but I do much more prefer that over getting more and more of a hook hell on larger projects. The way I showed above is much cleaner and keeps everything where it belongs: To the MyPage class. Now once you open a MyPage in the PW backend you get the note on the title field and you know where to look for that hook: In MyPage.php - not in ready.php, or init.php, or another module, or wherever else...
    1 point
  13. Hey, @teppo! I am back at this great module. Trying to make everything work as it should. I've read your conversation with @bernhard a number of times and think that a lot of issues discussed should make their way into the docs somehow. And answering the question quoted above (about the usage of custom page classes and controllers in Wireframe) would make another great page for Patterns and practices . The great docs are one of the main things that make Wireframe so attractive, as we can easily point to them when working in a team or passing a project to someone else. So keeping them up to date and adding more info is definitely as important (for someone who didn't write the framework in the 1st place))) as adding new features. I would participate in this process if there was a way to. At least I would fix some typos. But as cool as PW backend is it is not as good for open documentation. Is there a chance we can move the content creation to github and populate/update pages in PW via a script? I think someone already done this before...
    1 point
  14. Also worth to mention 'owner' selector https://processwire.com/blog/posts/processwire-3.0.95-core-updates/
    1 point
  15. Hi, welcome to ProcessWire! A page reference field IS a many-to-many relationship. Say you want to model Students and Courses: each Student can enroll in many Courses, each Course can have many Students. You put a page reference field in your Student template and make multiple Courses selectable. Now you can get all Courses a Student is enrolled in: $studentPage->courses And all Students enrolled in a Course: $pages->find("template=student, courses=$coursePage") A feature that is often requested is the ability to edit or at least view this relationship from both sides. In my example, the Admin area will only show Courses while editing a Student, but when editing a Course you can’t see its Students . There are Modules that fix this, such as this one by @Robin S: https://processwire.com/modules/connect-page-fields/. It will synchronise two page reference fields so the relationship will actually be stored from both sides.
    1 point
  16. Hey! This is a very early/experimental/alpha not for production environments release of a new module I'm working on. Just testing the possibilities and the interest that might be for such a thing. The idea is to be able to quickly create fields while working inside the template files without having to go to the admin. For example, in an early stage of development when creating a layout, insteading of putting a placeholder headline and then going to the admin to create the headline field where the real content will be, you can create the field directly from the template file by doing: <h2><?=$page->field("A nice headline", "headline", "text")?></h2> This will create a new "headline" text field when it doesn't exist in the system and add it to the the template of the page you're working on and add "A nice headline" value to it. On a second run the module will recognize that the field already exists on that template and will simply return it's value. The method accepts three string parameters in the order ( value, field name, field type ). Value and name are required but field type will assume "text" when omitted. $page->field("A nice headline", "headline"); // creates a text field $page->field("A nice paragraph", "body", "textarea"); // creates a textarea field The method also accepts a boolean parameter in any position: TRUE forces the value to be saved into the field on that page, FALSE (or omitted) sets that value to the field when it adds it to the template, but leaves it how it is when the field already exists in the page. This is the only situation when this module can be destructive, and it's only concerning the value of the field on that page: $page->field("Another nice headline", "headline", TRUE); // will create or add a text field and add the value to the page even if the field already exists there The method also accepts an array as parameter. This array will be used as options for the creation of the field. The options array will override the string parameters when they clash. $page->field("A nice headline", "headline", array( 'name' => 'subtitle', 'label' => 'Subtitle' )); // will ignore the name "headline" and use "subtitle" instead As soon as the fields are created and added to the template, all the method will do is return the value, just like if using $page->headline, unless you use the TRUE parameter which will override the value of the field by the value in the first parameter. -- With this module you can, for instance, convert an existing HTML template quickly, just by pasting the html into a template with no fields created yet, and going through all the code, replacing the content by calls to my field() method. In the end you should have a working page with all the fields created in the template. Now you just need to go to the fields and adjust their preferences. So, just download it > install it > test it > tell me what you think! dynamicPageFields.module.zip -- Edit: Multilanguage fields threw an error but they don't now. You can create a multi lang text by doing: $page->field("A nice headline", "headline", "textlanguage"); that third parameter is just a case insensitive simplification of input field names to make it easier to write. You can still use the original input field name like "FieldtypeTextLanguage" if you prefer.
    1 point
×
×
  • Create New...