Leaderboard
Popular Content
Showing content with the highest reputation on 07/11/2020 in all areas
-
Check the "Advanced" tab in the Template settings. There you'll find an option to make the createdUser modifiable:5 points
-
Relative to ProcessWire 3.0.161, version 3.0.162 contains 24 commits that continue upgrades/improvements to selector operators, fix various minor issues, add new API convenience methods, improve documentation, optimize and refactor various portions of code and DB queries, and much more. For full details, see the dev branch commit log as well as last week’s post. Next week I hope to finally finish up a new version of ProCache and continue with some additional core to-do items. By early August my hope is that we’ll have the next master branch version ready. Also added this week is a new dedicated documentation page on this site that covers all of ProcessWire’s selector operators, including all the newly added ones here: selector operators. Thanks for reading and have a great weekend!2 points
-
@fruid I'm using this function for /** * Render breadcrumb navigation * */ function renderBreadcrumbs(PageArray $items, Array $options = []) { $page = wire('page'); if (!count($items)) return ''; $index = 1; $defaults = array( 'class' => 'breadcrumbs__list', // class for the <ul> 'a_class' => 'breadcrumbs__link', // class for a item 'a_active_class' => 'breadcrumbs__link--active', // class for a active item 'liclass' => 'breadcrumbs__item', // class for li item 'active' => 'breadcrumbs__item--active', // class for active item ); $options = array_merge($defaults); $out = "<ul class='$options[class]' itemscope itemtype='http://schema.org/BreadcrumbList'>"; foreach ($items as $item) { $class = $item->id == $page->id ? " class='$options[liclass]" . ' ' . "$options[active]'" : " class='$options[liclass]'"; $a_class = $item->id == $page->id ? " class='$options[a_class]" . ' ' . "$options[a_active_class]'" : " class='$options[a_class]'"; $title = $item("bradcrumbs_title|title"); $url = $item->url; $out .= "<li $class itemprop='itemListElement' itemscope itemtype='http://schema.org/ListItem'><a $a_class href='$url' itemprop='item'><span itemprop='name'>$title</span><meta itemprop='position' content='$index' /></a>"; $out .= "</li>"; $index++; } $out .= "</ul>"; return $out; } Then in template file $breadcrumbs = renderBreadcrumbs(page('parents')->not('template=categories|products')->add(page()));2 points
-
Another approach to try: // Store page changes in custom property on $wire $wire->addHookAfter('Page(template=contact|sample)::changed', function(HookEvent $event) { $page = $event->object; $what = $event->arguments(0); $old = $event->arguments(1); $new = $event->arguments(2); $page_changes = $event->wire('page_changes') ?: []; $page_changes[$page->id][$what] = [ 'old' => $old, 'new' => $new, ]; $event->wire('page_changes', $page_changes); }); // Send email if there are page changes after the request is finished $wire->addHookAfter('ProcessWire::finished', function(HookEvent $event) { $page_changes = $event->wire('page_changes'); if($page_changes) { // Send the email using the values in $page_changes ... } });2 points
-
Cross referencing a similar topic with, possibly, an answer to your question @Spiria2 points
-
Hello @ all Today I want to share an inputfield/fieldtype to store 2 or 3 dimensions of an object. This fieldtype was inspired by the amazing fieldtype "Fieldtype Dimensions" from SOMA. This fieldtype was introduced in 2013 - so its time for a relaunch. This new fieldtype offers more possibilities than the old one. This inputfield/fieldtype let you enter max. 3 dimensions (width/height/depth) of an object (fe a product), but you can select if you want to display inputs for 2 or 3 dimensions. 2 dimension can be used fe for wallpapers or photos, 3 dimensions fe for furnitures or other objects. There are several configuration options for this fieldtype in the backend. set type (2 or 3 dimensional) set size unit as suffix after each inputfield (default is cm) set max number of decimals (default is 2) show/hide a hint to the user how much decimals are allowed If the number of decimals will be changed, the database schema for each dimension column will also change after saving the field in the backend. For example: If the schema for each dimension field in the DB is f.e. decimal(65,2) and you will set the number of decimals in the configuration to 3, then the schema in the DB will also change to decimal(65,3) after saving the inputfield. You can download this inputfield at https://github.com/juergenweb/FieldtypeObjectDimensions There you will find more detailed information and explanation too. If you find any bugs or you have an idea to improve it (also code improvements) please report it on Github. Have a nice day! UPDATE 14.06.23 / VERSION 1.2.2 I have re-written the complete fieldtype to be compatible with PHP 8.2 and refactored some of the methods and the database scheme. If you have downloaded the fieldtype before, please deinstall the old one and make a new install. I have added this fieldtype to the Processwire module directory. After it has been published, please download it from there.1 point
-
For a basic approach: $breadcrumbs = $page->title; foreach($page->parents() as $parent) { $breadcrumbs = "<a href='{$parent->url}'>{$parent->title}</a> / " . $breadcrumbs; }1 point
-
I would go this way, without invoking ready.php or other resources: <div class="grid"> <?php foreach($page->grid_ext as $item): ?> <div id="pteg_<?= $item->id ?>"> <?php // specify the template viewfilename like this, if it is a single viewfile: $viewFilename = $wire('config')->paths->templates . 'blocks/myblockviewfile.php'; // or if you have different files get them from template properties: $viewFilename = $item->template->altFilename ? $item->template->altFilename : $item->template->name; $viewFilename = $wire('config')->paths->templates . 'blocks/' . $viewFilename . '.' . $wire('config')->templateExtension; // check if viewfile is available if(!is_readable($viewFilename)) { echo logSectionError('Missing Template-View-File!', '<strong>' . basename($viewFilename) . '</strong>'); continue; } // now pack a bag with all needed variables for the block render template file: $viewBag = []; $viewBag['item'] = $item; $viewBag['page'] = $item; // if you use the $page var in your template file, pass here the current item-page to it ! $viewBag['pages'] = $pages; // optionally if you need other vars, add them here $viewBag['config'] = $config; // " // and render the block echo "\n " . wireRenderFile($viewFilename, $viewBag); ?> </div> <?php endforeach; ?> </div> https://processwire.com/api/ref/functions/wire-render-file/1 point
-
I'm totally agree with your opinion. Even it's beta.. We could start to implement it, use it, find bugs, help to fix it etc. We could start our projects and show something to our clients, get familiar with the system.1 point
-
You have just said a whole load of things I don't understand since my 20 years that I started developing. This is why I choose ProcessWire, I dont understand it now, I know its more than likely covered in the future.1 point
-
This is awesome. Thank you.1 point
-
Good article and postgresql looks interesting with its search capabilities, thanks. Though none of these really solve what I was after here. I experimented quite as bit with stemming and different stemming libraries. Though they all did roughly the same thing. When it came to searching, stemming just wasn’t that useful. WireWordTools originally had a stemming library and methods, and the appropriate fulltext queries included the word stems with wildcards. In the end, it just wasn’t helpful most of the time. And in the few cases where it was worthwhile, it was redundant, though far less thorough, than what we already had with inflection and lemmatisation. So while stemming can have its uses, it’s not even half way there, if trying to build a smart search. Cool nevertheless that they have it built-in apparently. As far as accent support, ranking and fuzzy search, these are all things that MySQL does as well, though maybe there are differences in how they do them. For instance, MySQL supports “sounds like” and also supports pluggable parsers for fulltext searches. Fuzzy search also isn't what I'm after here, but certainly interested in exploring in the future. For me the most useful thing by far is boolean mode searches, particularly in InnoDB, which has a full-text engine modeled on Sphinx. Boolean mode searches are really very powerful, enabling you to specify what’s required, what’s excluded, matching of words or phrases, partial matching of words with wildcards, specifying noise words, isolating distance between words, adjusting ranking up or down on a per-word basis, grouped expressions and nested subexpressions. All while being incredibly fast. I’m pretty thrilled with what MySQL supports here and what it brings to ProcessWire. Postgresql looks very nice too, but for our needs, I don’t feel we are lacking anything relative to it. I think anyone that would say that as a general thing is not very familiar with what MySQL fulltext supports, or maybe is thinking of fulltext support where it was back a long time ago. For ProcessWire and the scale that most use it at, MySQL fulltext is really a sweet spot, enabling PW to deliver enormous power and capability when it comes to search features.1 point
-
Unfortunately not. The mysqli wrapper uses the object oriented interface, so there isn't even an easy point to add that part in the core library between instantiating the module and invoking mysqli_real_connect(). Your best bet is to look at the stack trace to see which module causes the dump (enable $config->debug in site/config.php) and either find a replacement or post an issue in the module's git repo to get it converted to PDO.1 point
-
Using SSL should be quite straight forward, assuming that everything is configured correctly on the server side. The enforcing happens on the server the moment you issue an ALTER USER your-processwire-user@your-mysql-server REQUIRE SSL The moment you do that, you'll get a database error when you access your site. To enable PHP to talk over an encrypted MySQL connection, you now need to point it to the MySQL server's CA certificate. Copy that to a location where the web server can read it and add an entry in site/config.php (adapt the path to match your ca cert location): $config->dbOptions = array( \PDO::MYSQL_ATTR_SSL_CA => 'C:/temp/mysql-ca.pem' ); There may be scenarios where the name you use to access the server doesn't match the name in the certificate and you get the error "SQLSTATE[HY000] [2002]". The same error occurs when you use a self-signed certificate in the server (that's the case when you leave things to default after installing MySQL on most distributions). In that case, you need at least one of the following PHP versions: PHP 7.2, 7.3, 7.4 or 8 all versions PHP 7.1 >= 7.1.4 PHP 7.0 >= 7.0.18 The reason is that earlier versions of the MySQL PDO module didn't have the flag to disable certificate verification. You need to expand your entry in site/config.php: $config->dbOptions = array( \PDO::MYSQL_ATTR_SSL_CA => 'C:/temp/mysql-ca.pem', \PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false ); Most (hopefully all) PW modules should be using the PDO interface by now, but you may stumble upon one that still makes use of the old mysqli wrapper. Those won't work with an SSL connection.1 point
-
Hi @Melakh, Welcome to the forums. Sorry, not an answer to your question. However, since this question has been asked two or three times before, but without a solution, I am going to be naughty and tag probably two of the most knowledgeable people in these forums with respect to databases. Sorry both! @BitPoet, @LostKobrakai, for tagging you like this. Could you please weigh in on this issue if you can? Many thanks. ? Here are two previous similar questions:1 point
-
Ehy @teppo I'm really digging Wireframe and I really think that it's a brilliant work. Thank you also for mentioning my old TemplateEngineBlade module in the list of alternatives. I'm currently restyling one of my websites and I decided to use Wireframe for the purpose. Everything is going great so far! I also decided to create a renderer module that uses the Blade template engine, because I don't like Twig that much. Check it out https://github.com/mauricius/WireframeRendererBlade1 point
-
BTW @alexmercenary the Tracy Console can of course not handle the output of a $pdf->show() call since that sends the generated PDF directly to the browser! Just replace it by $pdf->save() and you get a correct result:1 point
-
This is related to the Wireframe::page() static utility method (https://wireframe-framework.com/docs/static-utility-methods/) but not specifically covered in the docs, I think. This is also one of the things I struggled trying to explain briefly in the changelog ? The general idea is that since Wireframe works through the Alternate Template Filename setting of templates, in earlier versions you couldn't do things like $pages->get(1234)->setLayout(null)->render() and expect the output to come from a Wireframe view UNLESS the Alternate Template Filename for the template this page uses had the alt filename pointing to a Wireframe bootstrap file (i.e. /site/templates/wireframe.php). After this update the syntax mentioned above will — in most cases at least — work right out of the box. And even in cases where it won't work (such as when you're fetching data from ProcessWire via a command-line script), Wireframe::page(1234)->setLayout(null)->render() will almost certainly work. Typical use case for me are pages that are not supposed to be directly accessible, like a contact page that lives under a shared "bucket" (e.g. /data/contacts/lastname-firstname/) and is only ever made visible when rendered as part of another page's markup. If I only need to output a few fields from the page I can do that directly in the view file for the containing page, but if I need to reuse this data all over the site, I prefer to define a view file for the contact (e.g. /site/templates/views/contact/embed.php) and render it using that: <!-- some page that lists contacts --> <?php foreach ($page->contacts as $contact): ?> <?= $contact->setLayout(null)->setView('embed')->render() ?> <?php endforeach; ?> Hope this makes more sense ?1 point
-
Great work @teppo! Could explain a bit this feature "- Support for rendering pages that have not been "routed" to Wireframe using the altFilename template setting." Or just point the docs - did not fins corresponding article there.1 point
-
Heya! Just released Wireframe 0.9.0. Here's the changelog for this version: ### Added - New EventListenerTrait. Currently used by Components only. Adds support for listening to and emitting events. - Support for Renderer modules for adding templating engine support for view files, component view files, etc. - New Page methods Page::viewTemplate(), Page::getViewTemplate(), and Page::setViewTemplate(). - New method Component::getData() for manually defining the data passed to the component view. ### Changed - Controller::init() and Controller::ready() are now hookable methods. - Component::setView() and Component::getView() are now final methods, preventing accidental overrides. - Layout file is no longer necessary; if it's missing, the page can be rendered using just a view file. The component system is a bit more mature now, and there are a couple of new features: Component::on('event-name', callable $callback) can be used to listen to events emitted by a Component instance, and in a Component class events can be emitted with $this->emit('event-name', array $args). This is mostly just syntactic sugar on top of the hook system, but it seemed fun and potentially useful, so... ? The Component base class extends WireData, so by default what gets sent to the component view when a component is rendered is the internal $data array. Since 0.9.0 it's possible to alter this behaviour by implementing getData() method which returns the data that the component should expose to its view. Another "big" update is support for renderers. These are add-on modules that add support for different rendering / templating engines to Wireframe, and the first example is the Wireframe Renderer Twig module. I haven't really used a templating engine in a while so it's possible that I've missed something important, but in my limited tests the Twig engine seemed to work quite well right out of the box. I'll likely add a separate module for Latte at some point, just to make sure that the logic works for other engines as well ? By the way, it looks like I forgot to post here about Wireframe 0.8.0. It was released last month, and here's the related changelog entry: ### Added - Support for Components, along with a new static factory method Wireframe::component($component_name, $args). - Support for rendering pages that have not been "routed" to Wireframe using the altFilename template setting. - New static getter/factory/utility method Wireframe::page($source, $args). - New static utility method Wireframe::isInitialized(). ### Changed - Wireframe::$initialized is now a static property. This was a necessary change so that Wireframe::isInitialized() could be implemented effectively. On a related note I'm considering tagging the next release as 1.0.0. We've been using Wireframe on production sites for a while now, and I can't recall any truly breaking changes so far, so I think it's already quite stable ?1 point
-
Hey folks! I've been a bit quiet here, but that's mostly because I've been busy building stuff with ProcessWire and Wireframe ? Just wanted to give a quick heads-up for a new feature called components that I'm currently testing (it's in the dev branch of the module already), in case anyone wants to comment on it before it gets merged to the master branch. Wireframe components are classes extending an abstract base class (\Wireframe\Component), and they can either render output directly by implementing the render() method, or they can be rendered using a separate Component View file. This is probably a familiar concept to most, but the general idea is that while partials ("dumb" files with no way to process params, and no clean way to separate code from markup) are enough if you just have some relatively static snippet that you need repeatedly, components add an extra layer where you can a) specify which params they accept, b) process those params, and c) include any additional "business logic" that should be triggered when the component is rendered. Here's a simplified example of how this comes together: /site/templates/components/Card.php (class for the Card component) <?php namespace Wireframe\Component; /** * Card component */ class Card extends \Wireframe\Component { /** * Constructor method * * @param \ProcessWire\Page $item Page related to current Card. */ public function __construct(\ProcessWire\Page $item) { // Pass properties to view $this->title = $item->title; $this->summary = $item->summary; $this->image = $item->get('image|hero_image'); } } /site/templates/components/Card/default.php (default view for the Card component) <?php namespace ProcessWire; ?> <div class="card"> <?php if ($image): ?> <img src="<?= $image->size(640, 480)->url ?>" alt="<?= $image->description ?>"> <?php endif; ?> <h3><?= $title ?></h3> <?php if ($summary): ?> <p><?= $summary ?></p> <?php endif; ?> </div> ... and for fetching and rendering the component, there's a little static helper in the Wireframe module class: <?php foreach ($cards as item): ?> <?= Wireframe::component('Card', [$item]) ?> <?php endforeach; ?> Note that Wireframe::component() actually returns an instance of the component class, not a string, but since \Wireframe\Component::__toString() calls \Wireframe\Component::render(), what we're doing here is essentially the same as echoing out the result of (new \Wireframe\Component\Card($card))->render() ? So, anyway, that's basically what I've been working on here. I'd be happy to hear if you have any comments on this addition – I haven't yet merged it to master since I'm still experimenting with it, and I'd like to avoid as many breaking changes in the master branch as I can. So far this has worked great for me, but to be honest my requirements have been pretty basic. Thoughts?1 point
-
Just released Wireframe 0.7.0. This version is all about caching: when requesting Controller methods from view (<?= $this->some_controller_method ?> etc.) the return value is now cached (runtime cache). Additionally if method names are added to protected $cacheable_methods property of the controller class, along with an applicable expire time (i.e. "protected $cacheable_methods = [ 'method_name' => 3600 ]"), Wireframe automatically caches the value using WireCache (persistent cache). Caching is usually a good thing, but not always preferred, which is why runtime caching can be prevented by adding the method name to (protected) Controller property $uncacheable_methods (protected $uncacheable_methods = [ 'method_name' ]). Persistent caching is always opt-in. Changelog: ### Added - Runtime caching support for Controller method return values. Values are cached *unless* the name of the method is found from Controller::$uncacheable_methods. - Persistent caching support for Controller method return values. Values are cached only when found from the Controller::$cacheable_methods array. ### Changed - In the View class all internal requests for Controller properties are routed through View::getFromController().1 point
-
Hey folks! I've been a bit quiet here about Wireframe, but the thing is that I've finally got a couple of "real sites" (as in not my own projects) to implement it on, and that has brought up some new requirements and a few issues. I haven't had the time to dig into a whole lot of really new stuff (components and such), but I have made a lot of other updates to the framework. As such, Wireframe 0.6 was released late yesterday. (A release on Friday the 13th, consisting of a total of 13 commits – not being superstitious here.) I've been updating the docs at wireframe-framework.com as well, but some parts remain a bit outdated. A lot of what happened in this version doesn't really affect the use of Wireframe, but some things do – and one change may even break some existing implementations: It used to be possible to set the view file or layout from Controller with $this->view->layout = "some-layout" or $this->view->view = "json". This has been deprecated and removed in favour of a setter/getter API: $this->view->setLayout("some-layout") and $this->view->setView("json"), and getLayout() / getView() for reading the value. In addition to some obvious benefits from type hinting etc. this also makes it harder to accidentally change something when you thought you were just passing a variable to the View ? There are now three ways to perform actions and pass data from a Controller to the View: Controller::init() (triggered as soon as the Controller class is loaded), public methods (which are made accessible in the View as $this->method_name), and a new addition Controller::render() (called right before the page is rendered). In most cases where one might've used the init() method before, render() is a better choice, as there's less chance that code will get executed "unnecessarily". In addition to existing Page::layout() and Page::view() methods there are now specific setters/getters: Page::setLayout("layout-name"), Page::getLayout(), etc. Original "unified setter+getter" methods may actually get removed at some point, as they're often ambiguous and make code arguably less readable. Quite a few other changes as well, some of which improve performance and others that make the API more polished. Some bug fixes too, though those mostly apply to what I'd consider "border cases" ? Here's the full changelog for Wireframe 0.6.0: ### Added - New Page methods Page::getLayout(), Page::setLayout(), Page::getView(), and Page::setView(). - New Controller::render() method, executed right before a page is actually rendered. - New ViewData class for storing (internal) data required by the View class. - New getter/setter methods for ViewData properties for the View class. - New method Wireframe::getConfig() for getting current config settings. - New method ViewPlaceholders::has() for checking if a placeholder has already been populated. ### Changed - Various View-related features moved from Wireframe module and ViewPlaceholders class to the View class. - Removed access to local get* and set* methods via the PHP's magic setter method __set() and getter method __get() in the View class. - Redirect feature no longer fails if provided with a WireArray data type; in these cases the first item is used as the redirect target. - Improvements to PHPDoc comments. ### Fixed - An issue with Config class where the "all directories exist" message was sometimes displayed unintentionally. - An issue where View Placeholder values might've been overwritten because existence of earlier value was checked inproperly. - An issue where empty / null view file would be automatically replaced with value "default". On a related note, for this version I decided to give sonarcloud a try. For those who don't know it, it's a sort of a code quality inspector, and it's free for public projects. It didn't have a whole lot to complain about at this point, but it's good to have some sort of validation in place just in case. I will also be digging deeper into reported "code smells", as some of them definitely make sense to me ?1 point
-
Hey folks – a quick update: Wireframe 0.5.0 was released couple of days ago. Compared to 0.4.x this version mainly fixes bugs and improves performance – nothing particularly major, but if you're using Wireframe, it's a recommended update. On a loosely related note, Tracy Debugger has been really helpful in figuring things out, identifying bottlenecks, etc. Brilliant module ?1 point
-
That changes things quite a bit. Personally I've never been a part of this kind of team – as strange as it may sound, I've worked in teams where there are backend developers and so-called full-stack developers, but never a "pure" front-end developer ? You've definitely given me something to think about here! Features that are not tied to a specific template have in my use cases usually been partials with very little "logic" behind them, but this would actually be a nice use case for shared (sub)controllers as well, which is something I'll likely dive into soon. Basically the idea is to have a controller that isn't tied to a single template, but rather can be used by multiple templates. Also controllers that inherit other controllers – "base controllers", or whatever they might be called – is another way to achieve shared features. Overall there's a lot you can do with current codebase, but since there are different use cases, it's very much about finding a balance between "not opinionated enough" and "too opinionated" ? As for layouts, I've found the concept really useful, and since I use them in pretty much all projects I work on, this is something I wanted to have built-in and ready-to-use within Wireframe. Placeholders are a key part of this, as they provide an easy way to embed views (of which there may be one or more for each specific template) within commonly shared layouts –aAnd because layouts serve a different purpose from view files (individual views for templates) and partials (smaller pieces of content intended to be embedded within layouts or view files), I've opted to store them separately. This is again one of those cases where it's all about finding the right balance and figuring out what should be available out of the box and what to leave for individual developers to figure out on their own, and I feel that current split between layouts/views/partials is a reasonable one – but because I know there are different opinions, much of this is actually already configurable. Also, since layouts are optional, one can always opt out from using them ?1 point
-
I get your point, and agree – to a point. When I first came across the idea of render functions (with that specific name it was some bit of code from Ryan I believe), this was exactly what I thought ? Since then I've used render-functions in numerous projects, and while in some cases it still feels a bit "dirty", in real world it can be a tremendously helpful strategy and hasn't really caused me any notable headaches so far – quite the opposite. These days I don't have a major issue with code that generates markup as long as it's clearly separated into its own container, i.e. "siloed" properly. While I don't encourage mixing business logic with presentation, this is one of those cases where the line is a bit blurry. Also, as a minor note I don't think that we should separate logic and presentation based on the language alone. PHP can be used to create "presentational" content, so overall it's more about what you do than how you do it. Something like Twig is supposed to be "purely presentational", but you wouldn't believe the complexity of some of the logic I've seen implemented in/with it. (But this is a topic for another discussion – templating languages vs. using PHP as a templating language, and so on and so forth.) Awesome! As far as I can tell this is actually really close to this rough idea I mentioned earlier – or, more precisely, it would be one possible use case for (or variation of) it: > Another idea I've been toying with would be subcontrollers (or child controllers, or partial controllers, or whatever terminology makes most sense) I'm not entirely sure if it actually needs to be a separate concept ("chunks", or whatever that would be called), but that's not necessarily a bad idea, if it makes the concept easier to grasp. Technically it should already be possible to instantiate a new Controller, provide it with a View file, and then render the output within, say, another Controller. That's what Wireframe itself does for the page, though it all happens automatically. Another thing that might not be obvious yet (I'll have to check the docs relating to this) is that there are two use cases for views: They provide alternative ways to render a Page. For an example the default view might render markup (HTML) for the entire page, and another might render an RSS feed for a list of news items. They can be used to populate View Placeholders: if you request <?= $placeholders->aside ?> in a layout file used for the "home" template and add a view file at views/home/aside.php, Wireframe will automatically populate the "aside" placeholder with the content of current page rendered with that view file. Anyway, I'll definitely dig into this topic a bit more and come back with some sort of solution, hopefully – thanks for linking to the TemplateEngineFactory example ? Thanks – this list was quite helpful. For the record, here's how I've handled these examples in my past projects: For menus I've used MarkupSimpleNavigation, and later MarkupMenu. In the boilerplate profile I do have partials for these, but they just call the render function of a markup module. Breadcrumbs is in my case usually a simple list of parents, thus I've used a "dumb" partial file with a foreach loop. Here's an example. Sidebar, again, tends to be either a single RTE field (something like sidebar, aside, or perhaps right_column or left_column), or sometimes a predefined list of multiple fields. Again a valid use case for so-called dumb partial files, but this is actually exactly the use case for which I originally added the ability to use View files as View Placeholders. Repeating elements covers a wide area of different content, but in my projects these have usually meant one of two things: A news list or something similar, with predefined header, list of items, and often some sort of "footer" area as well. These use cases I've usually solved with render functions. Repeater, RepeaterMatrix, or some other repeatable fieldtype. "Dumb" partials with some foreach rules, or native field rendering (particularly useful for RepeaterMatrix). Note that I'm not saying that your use cases are invalid, or that the list above would be the "correct" way to handle these. It's just that I can see why this hasn't been a notable issue for me – but this also helps me understand the kind of use cases you've run into, and thus figure out how to continue from here on ?1 point
-
This is just a rough idea, not sure if it's going to go anywhere but I'm actually wondering if I should extend the $partials object a bit? Currently it's actually a bit silly – basically an "object oriented" way to replace <?php include 'partials/menu/top.php' ?> with <?php include $partials->menu->top ?>. If each property could be used as a function, this would allow us to pass the partial arguments: <?= $partials->menu->meta([ 'description' => 'some text' ]) ?>, etc. Or we could pass in a string, in which case a Controller method would be used to pass the data to the partial. Again, just thinking out loud here. Not sure if this makes any sense, but I'm kind of liking the idea ? Another idea I've been toying with would be subcontrollers (or child controllers, or partial controllers, or whatever terminology makes most sense). These could solve situations where you end up needing the same stuff from template to template. You can always create custom base controllers and extend them, but this might allow for easier composition.1 point
-
Thanks, Ivan! ? I haven't figured out the details yet, but at some point I'm going to look into adding templating language support. For the time being all options are open, so don't really have anything else to share at this point than "I will look into it eventually". 1. Currently partials are intended as simple drop-in (include) files with very little logic. I do have some ideas in my backlog that come pretty close to this topic, but I'll have to give them a bit more thought before implementing. Wouldn't want to put something in now, and then regret it right away... ? I've often preferred render functions, i.e. functions that generate markup, in case I need to bake some logic into smaller bits and pieces of the site. A "RenderUtils" class with multiple render methods would be one solution, and of course you can already use ProcessWire's own features to render a partial: $page->renderValue(), $files->render(), TemplateFile::render(), etc. In the long term perhaps we could add some kind of a helper class to the framework for handling these situations – just not quite sure yet how to approach this. If you could give me an example or two of what sort of situations you tend to run into, I'd be grateful – would be good to know that I'm actually solving the right problem ? 2. Not Wireframe specifically, but I did build a few rather large sites with pw-mvc and RepeaterMatrix. In those cases I ended up using field templates (/site/templates/fields/) for the bulk of the RepeaterMatrix stuff. Worked quite nicely, really. I'll add a note to write a bit about this to the "Patterns and practices" page.1 point
-
Nice! Would be interesting to hear if you can think of anything particularly cool that your version did and Wireframe doesn't do. Always looking for new ideas ? Small update to the docs site: added a page for patterns and practices. Currently only one page there (utility classes), but will be adding more as I figure out what should be there. Doesn't make sense to bundle everything with the module or even the site profiles, so needed some place to stash this sort of stuff.1 point