Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 12/12/2022 in all areas

  1. One step closer, yes. But realistically, that's still not very close at all. Someone always needs to enter those prompts, after all. And while I've heard some people say an AI will always create more secure code than a human being, I don't believe that at all. So any code created by an AI should always be double-checked by a human being. The code examples ChatGPT is giving us right now is only snippets. There's still a lot of manual work needed in creating, say, a new Fieldtype and Inputfield. I've asked ChatGPT to create a Fieldtype and Inputfield and it wasn't able to show me a fully working example that didn't need a lot of manual editing. It always "forgot" some things, like the constructor, or it used a wrong parameter signature. Of course this will get better, but the more complex your prompts are becoming, the higher the risk the code simply will not work out of the box. The way I'm seeing it, AI is a great and valuable TOOL. It can save you from having to Google an answer for 30 minutes. It can give you some inspiration. But it's still just a tool, and for the foreseeable future, our jobs will be safe, because it's going to be US who will write the prompts and incorporate the code created. We shouldn't ignore it, and we need to learn to use it correctly. If all goes well, it might make our jobs a little easier, but shhh, don't tell our clients! Seriously though, yes, it's probably going to change things in the long term. See it as an evolution of our jobs. It might make SOME jobs obsolete. But frankly, comparing the clean elegance of ProcessWire with the convoluted mess of some other web frameworks and content management systems that keep reinventing the wheel every six months, you could argue if some web developers maybe should become obsolete. But finally, there's the issue that's been debated when it comes to art AI and Github Copilot already: copyright. AIs are always trained on existing material, and there will always be the risk that it simply lifts some code/art that has been released under an incompatible license. That's something a human will need to have an eye on, too.
    5 points
  2. With dedicated sub-domains this isn't really an issue but it brings other challenges as Google expects a super highly optimized version then. So... choose your challenge. ? It's also not that big of a problem on trusted high-traffic sites as reducing HTML/source load is a very good reason in those cases. Google respects that. Here comes the big BUT... most sites can't offer a super optimized sub-domain version, neither are high-traffic, nor are they that trusted by Google. So if you aren't maintaining a 20-25+ year old financial, automotive, insurance, Fortune 500, or media/news outlet site... I highly support the following statement: (all of the above excludes member areas and sites Google/Bing/... can't officially crawl or see.)
    3 points
  3. This is one of those rare weeks where I've got a lot of projects in progress, but all are in the middle, none are at a convenient Friday conclusion for this weekly update. In progress are some core updates, Pro module updates, other module updates, and a client project that's keeping me busy. So I don't have anything new or interesting to report this week, but I like to still check in and say hello, and let you know I'm not running low on coffee or anything like that. ? I hope that you have a great weekend!
    3 points
  4. You could achieve this if you are using your own custom CSS animation: Take a look at my Codepen example Uikit scrollspy animation different on viewport width (codepen.io) You can see, that I use a media query to trigger the different directions of the animation @keyframes my-animation { 0% { transform: translateX(-100%) } 100% { transform: translateX(0) } } @media(min-width: 768px){ @keyframes my-animation { 0% { transform: translateY(100%) } 100% { transform: translateY(0) } } } <div class="uk-child-width-1-3@m" id="animateMe" uk-grid uk-scrollspy="cls: uk-animation-slide-bottom; target: .uk-card; delay: 300; repeat: true"> <div> <div class="uk-card uk-card-default uk-card-body" uk-scrollspy-class="my-animation"> <h3 class="uk-card-title">Animation based on viewport width</h3> <p>On a small viewport I slide into your DMs from the left.</p> <p>On a large viewport I sneak in from the bottom.</p> <p>Resize the window and click on me me to trigger the animation again. </div> </div> </div>
    2 points
  5. To me the biggest factor missing here is intent. Why is the form where it is? What does it allow the user of the form to accomplish? What does the user want to have happened at the end? Answering those questions will bring out the UX part of what you want to do on submit, which technology you want to use to handle the submit. This is likely best described by examples: Contact Form: This is a form of allowing users to reach out. It allows users to put a message in whomever reads the messages' backlog. For these I think the outcome of the submit is ensuring the user that the submission was successful, so I usually have custom pages to redirect to, which show a success message and some prose telling them how soon they can expect an answer, …. If there's useful info to link to, e.g. FAQ, or something link to that. Also link back to the website if there isn't navigation anyways. As for technology simple is better. WebApp Create Resource form: When a form is meant to create (or edit) some resource in a system, the best way to ensure a user about having created/edited things correctly is just redirecting to that resources' details page and show a flash message of "Successfully created" or such. As for technology use whatever fits best with the rest of the system. Chat Input Form: Here the intend is to leave a message for wherever chat messages are visible, but not at all to leave the page. Make sure the form submits via AJAX, there shouldn't really be ways to input something, which is not "valid". Probably track acknowledgement of persistance by the server async (e.g. message rendered opaque until acknowledged). In the end don't think the page you get to after submitting the form successfully needs to be the page the form was on. There are places where this makes sense, but imo that's more the exception than the default.
    2 points
  6. So basically it all depends on the screen width here. Take this for example. How do you change data-attributes or custom code inside HTML elements depending on the screen width directly inside your markup? For example when the plugin does not have responsive options. <div class="uk-card" uk-scrollspy="cls: uk-animation-slide-left;"> <p>Hello World</p> </div> I want to change the properties of the uk-scrollspy attribute for example. A different animation on small (=mobile) screens or maybe no animation at all. UIKit does not offer such responsive options (yet). For that I would use the detect-mobile library like this: <div class="uk-card" uk-scrollspy="<?= (!$deviceCheck->isMobile()) ? 'cls: uk-animation-slide-left': 'cls: uk-animation-slide-bottom' ?>"> <p>Hello World</p> </div> When resizing the window this change is not applied though, I have to reload the page to make it happen. (t might confuse some plugins that read those values on DOM ready but hat is another story)
    2 points
  7. For YouTube videos... just use: https://orestbida.com/demo-projects/iframemanager/demo1/ or any other minimal YouTube solution with a placeholder as cover. If you hit a performance issue just with video thumbnails... mobile detection isn't your solution. In this case you probably have way bigger problems. Let's start with the basics: How many videos are on that (single) site/page? How large (in kb) is the poster/cover in average for a video? Where does that poster/cover come from? Are images lazy loaded if possible? How do you know there is a performance issue? Do you pay more than $0,99/month/year for hosting? Tell us more. I ran quite busy sites on cheap shared hostings solutions (H*stgator, Dr*amh*st, H*stnun,... and similar) without almost any issues.
    2 points
  8. With all the hype about ChatGPT, I wanted to see how useful it could be for us ProcessWire lovers. In a word: wow! It's pretty darn impressive for such early public testing and for such targeted subject. I love how it proposes code with comments, then proceeds to explain it. (Note: I've been getting more impressive and consistent results on mobile for some reason.) Prompt: Filter blog post by category in ProcessWire To filter blog posts by category in ProcessWire, you can use the find method of the $pages object, along with the category field and the equals operator, like this: // Get the category slug from the URL $category_slug = $input->urlSegment1; // Find all blog posts in the given category $posts = $pages->find("template=blog-post, category.slug=$category_slug"); // Loop through the posts and output their titles foreach ($posts as $post) { echo "<h2>$post->title</h2>"; } This code will find all blog posts that are in the category with the given slug, and output their titles. You can modify this code to output other information about the posts, such as their content, images, or dates. To make it easier for users to filter posts by category, you can also create a navigation menu that lists all the available categories, like this: // Find all categories $categories = $pages->find("template=blog-category"); // Output a link for each category echo "<ul>"; foreach ($categories as $category) { echo "<li><a href='/blog/$category->slug'>$category->title</a></li>"; } echo "</ul>"; This code will find all blog categories and output a link for each one, using the category slug as the URL parameter. When a user clicks on a link, they will be taken to the blog page with the posts filtered by that category. Prompt: Login form in ProcessWire To create a login form in ProcessWire, you can use the following code: // Check if form has been submitted if ($input->post->submit) { // Sanitize user input $email = $sanitizer->email($input->post->email); $password = $sanitizer->text($input->post->password); // Check if user exists and password is correct $user = $users->get("email=$email"); if ($user && $user->matches($password)) { // Login user $session->login($user); // Redirect to home page $session->redirect("/"); } else { // Output error message $error = "Invalid email or password."; } } // Output login form echo "<form method='post'>"; echo "<label>Email:</label>"; echo "<input type='email' name='email' value='$email'>"; echo "<label>Password:</label>"; echo "<input type='password' name='password' value='$password'>"; echo "<input type='submit' name='submit' value='Login'>"; echo "</form>"; // Output any errors if ($error) { echo "<p class='error'>$error</p>"; } This code creates a login form that accepts an email and password. When the form is submitted, it checks if a user with the given email exists, and if the password is correct. If the email and password are valid, it logs in the user and redirects to the home page. If the email and password are invalid, it outputs an error message. Prompt: User registration class in ProcessWire with email, password of at least 10 characters and age over 18. Check if email is unique. To create a user registration class in ProcessWire with email, password of at least 10 characters, and age over 18, you can use the following code: class UserRegistration { public function register($email, $password, $age) { // Sanitize user input $email = $sanitizer->email($email); $password = $sanitizer->text($password); $age = (int) $age; // Validate user input if ($age < 18) { $errors[] = "You must be over 18 to register."; } if (strlen($password) < 10) { $errors[] = "Your password must be at least 10 characters long."; } if ($users->get("email=$email")) { $errors[] = "A user with this email already exists."; } // If no errors, create user account if (!$errors) { // Create new user $user = new User(); $user->email = $email; $user->password = $password; $user->age = $age; // Save user to database $user->save(); // Redirect to confirmation page $session->redirect("/confirmation"); } } } This code creates a UserRegistration class with a register method that takes an email, password, and age as arguments. The method sanitizes and validates the input, and creates a new user if the input is valid. It also checks if a user with the given email already exists in the database, and outputs an error if one does. To use this class, you would first instantiate it: $registration = new UserRegistration(); Then, you can call the register method to create a new user: $registration->register($email, $password, $age); Prompt (similar to previous one): User registration form in ProcessWire with first name, last name, email, password of at least 10 characters and age over 18. To create a user registration form in ProcessWire with first name, last name, email, password of at least 10 characters, and age over 18, you can use the following code: // Check if form has been submitted if ($input->post->submit) { // Sanitize user input $first_name = $sanitizer->text($input->post->first_name); $last_name = $sanitizer->text($input->post->last_name); $email = $sanitizer->email($input->post->email); $password = $sanitizer->text($input->post->password); $age = (int) $input->post->age; // Validate user input if ($age < 18) { $errors[] = "You must be over 18 to register."; } if (strlen($password) < 10) { $errors[] = "Your password must be at least 10 characters long."; } // If no errors, create user account if (!$errors) { // Create new user $user = new User(); $user->first_name = $first_name; $user->last_name = $last_name; $user->email = $email; $user->password = $password; $user->age = $age; // Save user to database $user->save(); // Redirect to confirmation page $session->redirect("/confirmation"); } } // Output registration form echo "<form method='post'>"; echo "<label>First Name:</label>"; echo "<input type='text' name='first_name' value='$first_name'>"; echo "<label>Last Name:</label>"; echo "<input type='text' name='last_name' value='$last_name'>"; echo "<label>Email:</label>"; echo "<input type='email' name='email' value='$email'>"; echo "<label>Password:</label>"; echo "<input type='password' name='password' value='$password'>"; echo "<label>Age:</label>"; echo "<input type='number' name='age' value='$age'>"; echo "<input type='submit' name='submit' value='Submit'>"; echo "</form>"; // Output any errors if ($errors) { foreach ($errors as $error) { echo "<p class='error'>$error</p>"; } } Watch out, this is addictive ?
    1 point
  9. Hi there, just installed padloper 2, for that I needed php > 7.3, so i upgraded to what is now the latest (8.2) but I get these errors: Deprecated: Creation of dynamic property ProcessWire\Padloper::$outOfStock is deprecated in /home/joel/subdomains/godzillab/site/modules/Padloper/Padloper/Padloper.module on line 111 Deprecated: Creation of dynamic property ProcessWire\Padloper::$productNotFound is deprecated in /home/joel/subdomains/godzillab/site/modules/Padloper/Padloper/Padloper.module on line 112 Deprecated: Creation of dynamic property ProcessWire\Padloper::$checkYourOptions is deprecated in /home/joel/subdomains/godzillab/site/modules/Padloper/Padloper/Padloper.module on line 113 Deprecated: Creation of dynamic property ProcessWire\Padloper::$session_id is deprecated in /home/joel/subdomains/godzillab/site/modules/Padloper/Padloper/Padloper.module on line 122 thanks!
    1 point
  10. Hi hello, After filling in the final checkout form, selecting a payment method and clicking "proceed to confirmation" i get this error: It seems to have something to do with Countries and tax rates, but i think i've got them filled in: many thanks, j
    1 point
  11. Hello, I'm trying to install demo-1 but I can't add the pages 'categories' and 'products' with a template that is "similarly named": I can only choose one template called 'Padloper' However, there are more under templates - but i'm not sure how to choose them. tx, J
    1 point
  12. Forms are a pain. They are not only quite complex to build from a technical point of view but also from a UI/UX perspective. I've done some research and surprisingly I was not able to find helpful information on one crucial part of forms: Form submission! All blog posts and videos (like this one https://youtu.be/hPS7LUW7SlA) show all the necessary steps to make the form+fields look good and behave well, but none of the posts that I found showed anything about form submission. How do you handle that? Or do you have any information about that topic for me? I mean... There's so many ways how you can tackle that and I'm still not 100% happy with the way I implement forms with my forms module. There are two main ways of submitting forms: Regular HTTP get request AJAX AJAX are maybe a little harder to implement but have the benefit that they don't need another page load. Regular form submissions need to show a success message though and that has often been a challenge for me to implement that in an appealing way. Most of the time I show a success message instead of the form and add an anchor to jump directly to the success message if the page should be longer. On AJAX submitted forms on the other hand it is easy to show a modal (submitting form.... done, success!) but then you have the question what to do with the form that was submitted in the background? On one project I've made all fields disabled after submission so that the form is still there and takes up the same place as before (to not get any layout shifts/quirks) but it is obvious that it can't be submitted again (and the submission has worked). Does anybody have better ideas?
    1 point
  13. Aha, i get it now - i should make my own templates called 'categories' and 'products' ?
    1 point
  14. Ok. So as the comments in the hook example explain, there needs to be logic added to identify the logged in user. I'm thinking the best way to identify the customer details is to add a new role for administrators of the shop and then use a condition to check if a user has said role. If they do, don't auto-populate, as this hook overrides more PadloperProcessOrder::getOrderCustomer and this is used for more than the checkout customer details form.
    1 point
  15. Ah ha! It's the customGetOrderCustomer() hook from the demo for auto-populating the checkout customer form fields.
    1 point
  16. Hi mattgs, reading your reply, your writing about it, I am sure that is how it is in the real world for a long time to come. Also your writing about it from an experienced coder, could only come from a real human and not from ChatGPT
    1 point
  17. Hey @kongondo just to let ya know there is still some issue with adding/saving products and pages in Padloper after PW v3.0.203. I've just tried updating to 3.0.208 and that little bug is there. ??
    1 point
  18. With 8.2 the 'pages' view doesn't work either. You get 'unkown error, please try later'. I downgraded to 8.1 for the time being, that worked for now
    1 point
  19. Why would you even do that? What you mean when you are talking about "device"? Do you mean resolution? Then use media queries. Do you mean specific features? Then use feature detection. What is the specific use case, that can't be handled via normal media queries or window.matchMedia and feature queries? Maybe that is the problem, because the application has grown over time and now you can not easily change it to use best practices. I work in this industry since 1999 and know that browser detection is a thing of the past and preached by webexperts (I count myself to that, not in all areas, but many) everywhere not to use it. Even if many companies should still use it (which I believe is not true, or they might have legacy websites), that doesn't make it right. I also worked on over 100+ projects (international and national) and my company moved from using browser detection very long ago. Never had something that we couldn't do without it. Exactly, thats why you would load scripts conditionally via the import() expression via JS modules (all evergreen browsers support this). Stylesheets can be loaded depending on a media query to target specific media. I think the main problem what we talking about here is, that you have a legacy webpage/application, which could not be easily transformed to use best practices. The second one is the definition of "mobile" or "device" and what should be possible or not with that device. I neither wouldn't do that, because it is a bad practice. You can do this via JavaScript with the matchMedia method, if we are talking about viewport width. If you have specific questions how you might tackle your problem, we might give you suggestions here.
    1 point
  20. This is not the case. On some applications progressive enhancement is not possible (or let's say: ideal) because of the technological structure or other reasons. I am working for one of the biggest online stores in germany and for mobile/desktop devices we absolutely use browser detection and I am pretty sure most of the industry does. When visiting a product page there is a switch in the master template which then leads either to a mobile or desktop markup. These markup files share the same data source but code wise they are entirely different from each other. The reason behind this is that there was a completely different approach on how google ranked those mobile sites in the past AND since there are tons of elements and features (like custom written plugins) on the pages that massively differ depending on the device you're using this makes maintaining the code a bit easier. You have to load less/different assets, but it does add work when you have to make changes to both the desktop and mobile versions. Loading speed is an important ranking factor too, that's why you want to load only scripts and assets on your mobile page that you really need. Another reason why we use this approach. It's a giant application, though. On my private (and way simpler) ProcessWire projects I am sticking to progressive enhancement if possible. For images this will work. But I would never advice someone use media queries to hide elements with important content (SEO stuff) with "display: none" on any application. Just because google nowadays ignores this kind of content. Render the markup and the content that google needs to see (mobile first because mobile sites have top priority to google). And as you said: Take the same element and just make it look good on any device by using media queries. As I said I only use this browser detection for changing data-attributes or (only in one or two cases) the image format for a title image. Even advanced plugins like aos.js or high-end frameworks like UIKit are NOT responsive in some cases (https://getuikit.com/docs/animation). What do you do when you want to alter an animation based on the device? You have to somehow detect it and change the markup.
    1 point
  21. 1 point
  22. thanks for chiming in @dotnetic @teppo @gebeer I will re-consider the approach in my template. I was hitting performance issues with video thumbnails on mobile so I wanted to cancel displaying them if the user was on mobile (via Latte template query) and display a still image instead, but I guess this was the wrong approach. I will see if I can tackle the template logic differently and explore @media queries in CSS further. Many thanks for the feedback.
    1 point
  23. Sorry for the delay, I’ve posted the PR here: https://github.com/processwire/processwire/pull/251 Since it simply uses an anchor tag with a download attribute, it also allows you to open the full-size image in a new tab using a middle click or “open in new tab”, which is just the behaviour I would expect and seems pretty useful. Your SCSS module is amazing! Unfortunately SCSSPHP doesn’t seem to do exactly what Ryan’s setup does, and I suppose the “self” thing is a bug in SCSSPHP, but a great help nonetheless!
    1 point
  24. I think a lot depends on the form's purpose, the client's needs and – of course – on how much time you can spend on a given task. For example, I am working on an "online ordering solution", where the management of multiple addresses is needed, and this is what I already have working for this particular purpose: [image has been removed] So, for this form and for other "record management like" forms in the system, I opted for modal windows, toast messages and inline form error notifications (validation messages). I use Unpoly 2 and Bootstrap 5, btw.
    1 point
  25. Yes and no. I think the answer to what you mean is yes, but to be precise: The LESS module (https://github.com/ryancramerdesign/Less) got some updates some time ago that make RockLESS obsolete. I'll update RockLESS readme, thx!
    1 point
  26. @snck I am currently working on implementing Repeater Matrix support. It is basically working but needs some more thorough testing. ATM the setMatrixItems() method seems to be working well. If you like, you can grab a copy from https://github.com/gebeer/RockMigrations/tree/repeatermatrix and test it out. This is how you create a Repeater Matrix field: // first create the blank field $rm->createField('repeater_matrix_test', 'FieldtypeRepeaterMatrix', ['label' => 'Product Content Blocks', 'tags' => 'products']); /** * Set items (matrixtypes) of a RepeaterMatrix field * * If wipe is set to TRUE it will wipe all existing matrix types before * setting the new ones. Otherwise it will override settings of old types * and add the type to the end of the matrix if it does not exist yet. * * CAUTION: wipe = true will also delete all field data stored in the * repeater matrix fields!! */ $rm->setMatrixItems('your_matrix_field', [ 'foo' => [ // matrixtype name 'label' => 'foo label', // matrixtype label 'fields' => [ // matrixtype fields 'field1' => [ 'label' => 'foolabel', // matrixtype field options 'columnWidth' => 50, // matrixtype field options ], 'field2' => [ 'label' => 'foolabel', // matrixtype field options 'columnWidth' => 50, // matrixtype field options ], ], ], 'bar' => [ // matrixtype name 'label' => 'bar label', // matrixtype label 'fields' => [ // matrixtype fields 'field1' => [ 'label' => 'foolabel', // matrixtype field options 'columnWidth' => 50, // matrixtype field options ], 'field2' => [ 'label' => 'foolabel', // matrixtype field options 'columnWidth' => 50, // matrixtype field options ], ], ], ], true); Still need to test the other methods for removing/adding items etc. But this one should work. At least it was working in my tests. When testing is completed I will make a PR so @bernhard can implement.
    1 point
  27. Hi Clarity, Can you clarify what you mean by, "modify the query during search," perhaps with an example of what you are looking for? SearchEngine does provide the ability for you to not use its default ProcessWire searches, and instead simply prepare the index and form/results for you, so that you can form the query manually on your own depending on your own needs, as shown in the module page's documentation. Is that what you mean? If not, an example would be great. ? Some of adrian's examples within this topic may be of use too.
    1 point
  28. Hi @gs-df Coupons/Vouchers are not currently supported so there are no files to look at ?. Some quick thoughts... I see three main components: Creating coupons Managing them (editing, etc) Using the coupons in the frontend and expiring them in the backend. Creating Coupons There's are a number of approaches. a. Coupons as a special type of product Add a custom text field to products template. Create coupons as products. Hide these 'special products' from the frontend. Advantages Easy to create. Not much coding needed; you can use the Padloper and ProcessWire APIs. Disadvantages Not intuitive; can confuse editors. Lots of unused fields relevant to product but not to coupons. Extra code to hide coupons from being displayed in the frontend as products. b. Coupons as dedicated ProcessWire pages Let coupons be dedicated ProcessWire pages. Could use own custom dedicated template (i.e. non-Padloper template). Can either hide these pages under admin or have them live under Padloper main parent page or have them as usual pages. Add custom fields to hold coupon details such as valid date(s), expiry, usage, number, etc. Alternatively, create a custom Fieldtype for coupons. Advantages Straightforward and easy to manage as separate pages. Not much coding needed; you can use the ProcessWire APIs. Disadvantages Extra code to hide manage coupons c. Coupons as items in a custom database table Create a custom database table dedicated to holding coupons data. Use $database to CRUD coupons. Advantages Straightforward and relatively easy to manage as separate records. Scalable. Disadvantages Knowledge of working with custom tables needed. Extra code for CRUD. Managing Coupons Depending on your chosen route above, you could directly edit the coupons as ProcessWire pages, or create a Process Module (not great as will be outside the Padloper 'environment') or use the Padloper addons and addons API. The latter is my preferred method as it gives you near unlimited ways to manage your coupons in a dashboard. You could use this dashboard to manually send coupons to customers. You could also automate the process. Using Coupons This is the easy bit. You will need to use a custom checkout form to add fields you need to capture details about the coupon details that the customer has provided. You can then use a hook(s) to process coupon details entered by customer (e.g. validate, etc). See demo 2 and demo 3 on how to use and hook into the order checkout to process custom form details. Hope this helps.
    1 point
  29. While ProcessWire and WireArray does not have support for array_chunk, there is a simple way to achieve this. With array_chunk() you can easily add DIVs to a foreach loop, without having to set up counters when using general PHP (hat-tip to Laurance over at StackOverflow). The idea in a ProcessWire context is to use array_chunk() to split an array into chunks - and use eq() when looping page results. Simple example that will split a WireArray into three columns. Before we begin, you should know the array_chunk syntax: array_chunk($array, $chunk_size, $preserve_keys=true|false). <?php $p = $pages->get('/news')->children('limit=15, template=article, sort=-sort'); ?> <div class="row"> <?php foreach (array_chunk(range(0,14),5) as $chunk): ?> <div class="col"> <?php foreach ($chunk as $i): ?> <h5><a href="<?=$p->eq($i)->url?>"><?=$p->eq($i)->title?></a></h5> <?php endforeach; ?> </div> <?php endforeach; ?> </div> A more realistic example: <?php $p = $pages->get('/news'); $pp = $p->children('limit=15, template=article, sort=-sort'); ?> <h2><a href="<?=$p->url?>"><?=$p->title?></a></h2> <div class="row"> <?php foreach (array_chunk(range(0,14),5) as $chunk): ?> <div class="col"> <?php foreach ($chunk as $i): ?> <h5> <a href="<?=$pp->eq($i)->url?>"><?=$pp->eq($i)->title?></a> </h5> <?php endforeach; ?> </div> <?php endforeach; ?> </div>
    1 point
  30. Although your approach would be a bit faster (less function calls overall), it can be turned into a hook and be called on any class that extends WireArray, basically any collection returned by ProcessWire API // /site/ready.php wire()->addHookMethod('WireArray::chunk', function (HookEvent $e) { $chunkSize = (int)$e->arguments(0) ?? 1; $e->return = array_chunk($e->object->getArray(), $chunkSize); }); A common use case is to build grids <?php $myPages = $pages('template=my-template'); ?> <div class="grid"> <?php foreach ($myPages->chunk(5) as $chunk): ?> <div class="row"> <?php foreach ($chunk as $item): ?> <div class="col"><?= $item->title ?></div> <?php endforeach; ?> </div> <?php endforeach; ?> </div>
    1 point
  31. Sorry, was on mobile so couldn't add a code sample. $precioschico = $page->get("planos"); $preciosgrande = $page->get("mapas"); $precios = $precioschico->makeCopy(); // So we don't change the variable itself on the next line $precios->import($preciosgrande); foreach( $precios as $precio ) { echo $precio . '<br/>'; }
    1 point
  32. If you want to keep the original Pageimages WireArray but use an index you can create your own index counter: $index = 0; foreach($data->img_gallery as $image) { // do whatever with $index and $image here $index++; }
    1 point
×
×
  • Create New...