Jump to content

bernhard

Members
  • Posts

    6,314
  • Joined

  • Last visited

  • Days Won

    318

Everything posted by bernhard

  1. bernhard

    Wireframe

    Totally agree and please don't forget to validate all my requests before implementing (as you already do) ? I'm just throwing in ideas and questions as they arise. What would really be great would be some kind of illustration of the process that one has to go through when adding content to a site (layout). As you said: Decisions, decisions ? They should be made as simple as possible ? built with https://www.yworks.com/products/yed (free and all major platforms); Of course this is totally simplified and missing other decisions that have to be made, like "could it be reused in other projects? --> build a module" Hm. One thing that made me really curious about wireframe was this: Thx for the clarification! This feels like a quite big limitation for me. What if I have some piece of code that is needed on several templates (controllers are out) that has some business logic? Should I create a pw module for that? I think that's often too much overhead (you need to install it, define moduleinfo stuff etc). Imho there should be an easy way to handle such situations. Components sound great, but accessing methods should also be easy. I've now tried this: <?php namespace Wireframe\Component; class Slider extends \Wireframe\Component { public function __construct() { $this->component = $this; } public function foo() { return "foo!"; } } <p class='uk-container'>I am a slider! <?= $component->foo() ?></p> I am a slider! foo! Ok, that would be a quite easy solution. I'm wondering 2 things though: Couldn't (shouldn't) that or something like that happen automatically? Just like it's done in controller view files? Shouldn't Controllers and Components work the same with the only difference that one is applied automatically to the loaded template and the other one has to be loaded manually via Wireframe::component('foo') ? Or are there any other important differences that I'm missing? --- Thx for all your efforts on this!! ? Looking forward ?
  2. bernhard

    Wireframe

    @Zeka wrote me that this snippet does not work for him... That's because I have a custom pageClass loader in RockMigrations that triggers the init(): https://github.com/BernhardBaumrock/RockMigrations/blob/a034abce7e7fa5436756a2506d9d5f17d8a1b361/RockMigrations.module.php#L1733 So the ready() method in that case would not be triggered still, but you can easily trigger that yourself. the key is that you keep the hooks in the class itself for maintainability!
  3. bernhard

    Wireframe

    Hi @teppo Thx, it made click in my head ? I'll write about my journey and come up with suggestions at the end of the post: First try: <body> <?php if($page->is(['template' => [GemeindeGuru::tpl_teaser]])) { echo $partials->{GemeindeGuru::tpl_teaser}->body; } else { echo Wireframe::component("Header"); echo Wireframe::component("Search"); echo Wireframe::component("Slider"); } ?> </body> Nice, this already works ? 2nd try: <body> <?php switch($page->template->name) { case GemeindeGuru::tpl_teaser: echo $partials->{GemeindeGuru::tpl_teaser}->body; break; default: echo Wireframe::component("Header"); echo Wireframe::component("Search"); echo Wireframe::component("Slider"); break; } ?> </body> A lot better imho, but what if I wanted to add a custom 404 design? I'd need to duplicate the switch case: <body> <?php switch($page->template->name) { case GemeindeGuru::tpl_teaser: echo $partials->{GemeindeGuru::tpl_teaser}->body; break; case GemeindeGuru::tpl_404: echo $partials->{GemeindeGuru::tpl_404}->body; break; default: echo Wireframe::component("Header"); echo Wireframe::component("Search"); echo Wireframe::component("Slider"); break; } ?> </body> Not bad as well, but I wanted something better ? Next try: <body> <?php $body = $partials->{$page->template->name}->body; if($body) echo $body; else { echo Wireframe::component("Header"); echo Wireframe::component("Search"); echo Wireframe::component("Slider"); } ?> </body> ProcessWire\WireException Partial file not found: C:/laragon/www/kaumberg/site/templates/partials/home.php Fast-forward: I did some more testing and realized that I was actually mixing up partials and placeholders! The final (and great) version looks like this: // layouts/default.php <body> <?php if($placeholders->body) echo $placeholders->body; else { echo Wireframe::component("Header"); echo Wireframe::component("Search"); echo Wireframe::component("Slider"); } ?> </body> // views/home/body.php echo Wireframe::component("Header"); echo Wireframe::component("Search"); echo Wireframe::component("Slider"); echo Wireframe::component("News"); echo Wireframe::component("Contact"); echo Wireframe::component("Footer"); // views/teaser/body.php <div class='uk-height-viewport uk-flex uk-flex-center uk-flex-middle'> <div class='uk-text-center'> <div><img src='mylogo.svg' class='logo'></div> <div class='teaser'><?= $page->title ?></div> </div> </div> This simply means: If the view file /views/[template]/body.php exists, render it, otherwise render the default sections. That should make it really easy to create custom layouts for some templates whily still having all other assets and scripts in place (like seo, styles, analytics etc). I think I'm happy with this setup ? I realized, that I was missing the link between $placeholders->foo and /views/[template]/foo.php I read the docs again and I saw that this information IS already there ? My personal addition to this sentence: If you know where you have to look ? This illustration makes a lot of sense now. But I didn't get it quickly I have to admit. Here's my conclusion and suggestion: IMHO your docs are great explaining "how it works", but they could be improved in regards of "how I can work with it". In my experience this can make a huge difference in the experience of someone looking at it the first time. It's basically what you said earlier: Exactly that! I think if the docs where split into two sections, the first being "quickstart" and the second being what you already have, that would be brilliant. I know that what I'm asking for is a lot of work, but if we (you ?) want to build some kind of standard, it should be as easy as possible for everybody to adopt to it ? Finally I've got a question/request that you have to review from a technical point of view. As stated above, it took some time for me to grasp this easy concept: $placeholder->default loads /views/MyTemplate/default.php $placeholder->head loads /views/MyTemplate/head.php If you look at the rest of wireframe this becomes quite obvious: echo Wireframe::component("Header") --> /components/Header/default.php echo $partials->menu->top() --> /partials/menu/top.php echo $placeholders->body --> /views/[template]/body.php This really confused me when starting with wireframe! I'd expect placeholders to live in /placeholders or, the other way round, the variable to be called $views echo Wireframe::component("Header") --> /components/Header/default.php echo $partials->menu->top() --> /partials/menu/top.php echo $views->body --> /views/[template]/body.php These 3 lines would make it obvious what options you have in your layout file. But maybe that's because I've already a better understanding of what's going on, so maybe other newcomers could comment on this? What I was really missing was a guide that helps me go through a typical web project: You got a design, you got a PW installation, you installed Wireframe, what then? Now after 2 days of testing this was the way that worked great for me (so far): Set wireframe as alternate template file for all templates that should be handles via wieframe (for this walkthrough we take home.php and basic-page.php of the default site profile). Create a default layout: /layouts/default.php <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title><?= $page->title ?></title> </head> <body> <h1>I am the default layout</h1> </body> </html> Open the root page of your site and the 404 page --> both should display the default layout We want a common page header and footer that is displayed on all templates. Shared markup with little to none business logic is best placed in a partial. Create 2 files: /partials/header.php <div style='border: 1px solid blue; padding: 20px;'>I am the page header</div> /partials/footer.php <div style='border: 1px solid red; padding: 20px;'>I am the page footer</div> Now you can output these partials in your layout's body: <body> <?= $partials->header ?> <h1>I am the default layout</h1> <?= $partials->footer ?> </body> What if we wanted a slider on the frontpage? And ONLY on the frontpage? That's what view files are for and they are accessed via $placeholders. (Don't you think that this is really misleading?) /views/home/slider.php <div style='padding: 20px; border: green;'>I am a SLIDER</div> And add it to the layout: <body> <?= $partials->header ?> <?= $placeholders->slider ?> <h1>I am the default layout</h1> <?= $partials->footer ?> </body> Now open both pages on the frontend and you'll see that the slider does only show up on pages having the [home] template. That magic is simply applied via file structure /views/[template]/slider.php Ok now we want to add the current local time of the user visiting the page. That will obviously need some PHP logic and as we want to separate concerns as much as possible we do NOT want to put that code into a partial. Instead, we create a component that consists of business locig (a PHP class extending \Wireframe\Component and a view file that is responsible for the output. <?php namespace Wireframe\Component; class LocalTime extends \Wireframe\Component { public function render() { return "<div> Your timezone: <strong>XXX</strong><br> Your local time: <strong>XXX</strong> </div>"; } } And add it after the footer of our layout: <body> <?= $partials->header ?> <?= $placeholders->slider ?> <h1>I am the default layout</h1> <?= $partials->footer ?> <?= Wireframe::component('LocalTime') ?> </body> Nice! We get the output at the bottom of all of our pages! We know that doing lots of output within php classes is ugly, so we refactor our setup a little and adopt another concept of wireframe: View files for components: /components/LocalTime.php <?php namespace Wireframe\Component; class LocalTime extends \Wireframe\Component { } /components/LocalTime/default.php <div> Your timezone: <strong>XXX</strong><br> Your local time: <strong>XXX</strong> </div> Of course, this is no a lot better for now, but it is a lot more future proof! Check your frontend, it should still display the same markup for your local time. Now we can add the "business logic" to our component: <?php namespace Wireframe\Component; use ProcessWire\WireData; use ProcessWire\WireHttp; class LocalTime extends \Wireframe\Component { public function __construct() { $http = new WireHttp(); $data = new WireData(); $data->setArray($http->getJSON("http://worldtimeapi.org/api/ip")); $this->timezone = $data->timezone; $this->unix = $data->unixtime; } } And update our view to output the component properties (note how they magically become available as view variables!): <div> Your timezone: <strong><?= $timezone ?></strong><br> Your local time: <strong><?= $unix ?></strong> </div> Go to your frontend and see the magic! Your timezone: Europe/Vienna Your local time: 1598007959 What, you don't want a unix timestamp? Ok... let's provide a formatter method so that you can easily output the time in different formats: <?php namespace Wireframe\Component; use ProcessWire\WireData; use ProcessWire\WireHttp; class LocalTime extends \Wireframe\Component { public function __construct() { $http = new WireHttp(); $data = new WireData(); $data->setArray($http->getJSON("http://worldtimeapi.org/api/ip")); $this->timezone = $data->timezone; $this->unix = $data->unixtime; } public function date($format = "d.m.Y H:i:s") { return date($format, $this->unix); } } @teppo now I got stuck again ? How would I display that formatted date in my view file for this component? Or would I need to provide the date format as variable for the constructor ( echo Wireframe::component('LocalTime', ['format' => 'Y-m-d']); ) PS: Regarding the last question. Controllers do expose methods to views. Is there a similar concept for components? I did implement the local time as component because this does not belong to a single template (then it would have been a controller, right?)
  4. To be honest I don't see anything better in "your" world compared to "mine". My world is basically the PW API, so I don't see why it would be better to learn another language/syntax that does the same but works a little different. PW API can be used everywhere, works out of the box, is documented, tested, maintained etc... But I'm open to suggestions for improving the RockMigrations API further ?
  5. bernhard

    Wireframe

    Thx @teppo, greatly appreciated! Thx, that clarifies it. $page->wire->view does also work ? Well, the great thing about custom pageClasses is that they do also work on the backend. You can use them for hooking the pageedit form for example. Or today I did some custom redirects when a page is save+exit'ed. This really belongs to the page object imho, so it makes sense to have everything in a class extending the Page class. I'm not sure yet where to draw the line between page classes and controllers for wireframe... ? Hm, may I ask for one more advice so that I can continue working on that tomorrow... My need is quite common, I think: Templates: home foo bar Then I want to have 2 layouts: frontpage body sections: header, search, slider, quotes, news, ..., cta, footer default body sections: header, search, main, footer The links should be: home.php --> frontpage foo.php --> default bar.php --> default My question is about how you structure such a setup. When using custom "dump" layout files, the <head> for both layouts would be duplicated (same assets, same title, same meta tags etc). If I added a third layout I'd have 3x the same code... Or do you do something like this? <head> <?= $partials->head->title ?> <?= $partials->head->seo ?> <?= $partials->head->assets ?> </head> I guess placeholders come into play a little later on the road when I start outputting template specific things? Like news-cards with page content of that news-page? Sorry for all those beginner questions ?
  6. bernhard

    Wireframe

    Thx, here is my working version ? class TeaserPage extends Page { public function init() { $this->addHookBefore("Wireframe::render", function($event) { if(!$event->page instanceof self) return; $event->view->setLayout('teaser'); }); } } Hm. That confuses me a little. What I'm doing is basically just creating a "coming soon" page. So I'd really just need a template for that. Let's call it "teasertpl". Now to keep things managable in bigger projects I learned that custom pageClasses are a HUGE help. There are always little tweaks we have to do, right? And we all love PW and hooks, right? But in my experience this can quickly get extremely chaotic. My first approach was to split ready.php into several sections and do this: // ready.php include('foo.php'); // all foo related things include('bar.php'); // all bar related things The problem with that approach? One day you need to add a hook on init() instead of ready() and all the trouble begins... Using pageClasses on the other hand is really clean (and also easy): class MyPage extends Page { public function init() { // add init hook } public function ready() { // add ready hook } } I love that approach, because you can even use class constants like MyPage::foofield and you can quickly open that file in VSCode via CTRL+P, type "MyPage", boom --> all there! Want to hook the page edit screen for MyPage pages? Add a buildForm hook on that pageClass! Want a custom random pagename? Add a saveReady hook. Want to auto-publish MyPage pages? One additional line in the saveready hook. ? And you get all that by just setting the pageClass in RockMigrations: $rm->migrate([ 'templates' => [ 'my-page' => ['pageClass' => 'MyPage'], ], ]); Ok sorry, I got a little off-topic, but that was the context ? Back to your statement... Ok, so I have this single "teaser" template and want to render "layouts/teaser.php". I dont have (want/need) a Controller, because that's really just a single page with a logo. Where would you place the setLayout() ? In wireframe.php like this? $page->view->setLayout('teaser'); This throws an error Call to a member function setLayout() on null Maybe I'm missing something again? I must admit that it does not feel like I really got the concept yet ? Or would I use a view for something like this that uses the default layout? My idea was to have one default layout for all other templates of this website and one for this "coming soon" page. The 404 page would also be a candidate for a custom layout where I don't need any menus, headers, footers etc.; Or would you create ONE layout for all that and then show/hide sections based on the page (template) that is currently viewed? Thx a lot for you help! I'm really looking forward to implementing a streamlined workflow for my projects. Yesterday I had to work on an old project and I got lots of "where did I place this, where did I define that, what the ** did I do here?" moments ?
  7. bernhard

    Wireframe

    Thx again @teppo ? I hope you don't mind if I throw some suggestions here while I'm exploring wireframe ? One more suggestion for the docs: I think this docs page is a little bloated. Don't get me wrong, I really appreciate the huge amount of informations, but for me it would be easier to start from the minimum working setup and then expand from that. See the docs here: https://wireframe-framework.com/docs/view/components/ It seems to be quite complicated to create components, while all you actually have to do is this: /components/Card.php <?php namespace Wireframe\Component; class Card extends \Wireframe\Component { } /components/Card/default.php I am a Card component! /layouts/default.php echo Wireframe::component("Card"); Once I got that via try&error your "advanced" example was great ? PS: Maybe add a note that /components/Card/default.php could be replaced by adding a render method in /components/Card.php ?
  8. bernhard

    Wireframe

    Thx for the quick headsup @teppo Yeah, I thought so, that's why I was asking ? Yeah, that's what I tried! Please see edit3 in the above post! I've just tried making the page a regular PW page and still it does not work ? // init Wireframe $wireframe = $modules->get('Wireframe'); $wireframe->init(); // render the page $page->setLayout('teaser'); echo $wireframe->render([ // 'site_name' => 'Lorem Ipsum', // 'lang' => 'en', // 'home' => $pages->get(1), ]);
  9. bernhard

    Wireframe

    Hi @teppo, could you please give me a quick hint what would be the best way to set a layout for a custom pageclass? I'm creating a page via RockMigrations and it has the PageClass TeaserPage: class TeaserPage extends Page { public function __construct(Template $tpl = null) { parent::__construct($tpl); $this->_wireframe_layout = 'teaser'; } } This works, but $this->setLayout('teaser') does not. I get an Error Method TeaserPage::setLayout does not exist or is not callable in this context The docs say that the layout can be defined via hook, but I could not find an example? Thx Edit: The solution above is not possible: You must assign a template to the page before setting custom field values (_wireframe_layout) Edit2: class TeaserPage extends Page { public function init() { $this->addHookBefore("Wireframe::render", function($event) { bd('fired'); bd($event->page->getLayout(), 'layout'); $event->page->setLayout('teaser'); bd($event->page->getLayout(), 'layout'); }); } } This hook fires but does not change the layout? Edit 3: Even this does not work?! // init Wireframe $wireframe = $modules->get('Wireframe'); $wireframe->init(); // render the page if($page->template == GemeindeGuru::tpl_teaser) { $page->setLayout('teaser'); } echo $wireframe->render([ // 'site_name' => 'Lorem Ipsum', // 'lang' => 'en', // 'home' => $pages->get(1), ]);
  10. bernhard

    Wireframe

    Any reason why the resources folder is not created via config? Not sure if that is good news for me ? Should I wait for that or will the update be smooth? Thx for the info though ?
  11. bernhard

    Wireframe

    Hi @teppo finally did some more testing, this was my experience: Installed the module, smooth Created default site structure, smooth Set alternate template file for home.php, smooth Empty frontpage --> what now? https://wireframe-framework.com/getting-started/ stops at this step! Ok, it does not stop, but it leads to https://wireframe-framework.com/docs/ -> this is all great informations, but it does not help getting a quick grasp of how to output something on the frontpage... Please don't get me wrong. Your docs are great, but for me (and maybe others) I think some small improvements can make the experience even greater. Maybe something like this (based on my efforts from today): --- Here's a rough, unpolished tutorial for getting started with wireframe and getting the concepts on the road: Follow https://wireframe-framework.com/getting-started/ until the end Set alternate template file for home.php Create /layouts/default.php and visit the homepage --> you'll see the default layout <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Default Layout</title> </head> <body> <h1>Wireframe default layout</h1> </body> </html> Congratulations, that's your first layout! Now add some php variables: <p>My name is: <?= $view->myName ?></p> Of course, why should the layout know the name? We need a controller that tells the view what value is in the myName property! Create /controllers/HomeController.php <?php namespace Wireframe\Controller; class HomeController extends \Wireframe\Controller { public function myName() { return 'Bernhard'; } } What about my favourite CMS? <p>My favourite CMS is: <?= $view->cms ?></p> <?php namespace Wireframe\Controller; class HomeController extends \Wireframe\Controller { public function myName() { return 'Bernhard'; } public function cms() { return "ProcessWire"; } } Ok, I got it - and that's great stuff! ? Now set the alternate template for "basic-page" to "wireframe". Visit a "basic-page" site (eg the 404 page) and you'll see the default layout: The variables are empty, because the HomeController is only loaded on the home template and that's for some good reasons. Read about views in the docs: https://wireframe-framework.com/docs/view/views/ Partials to the rescue ? We modify the default layout: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Default Layout</title> </head> <body> <h1>Wireframe default layout</h1> <?php include $partials->name ?> <?php include $partials->cms ?> </body> </html> And the partials: // partials/name.php <p>My name is <strong>Bernhard</strong>.</p> // partials/cms.php <p>My favourite CMS is <strong>ProcessWire</strong>.</p> Let's make that dynamic! // name.php <p>My name is <strong><?= $name ?></strong>.</p> // cms.php <p>My favourite CMS is <strong><?= $cms ?></strong>.</p> // default.php <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Default Layout</title> </head> <body> <h1>Wireframe default layout</h1> <h2>Viewing template "<?= $page->template ?>"</h2> <?= $partials->name(['name' => 'Bernhard']) ?> <?= $partials->cms(['cms' => 'ProcessWire']) ?> </body> </html> Note that the partials are now echoed instead of included and we added the line that outputs the template of the viewed page! Note though, that partials are really just for simple chunks of code. At best even static ones. As soon as things get more dynamic, start using components instead of partials: https://wireframe-framework.com/docs/view/components/ What do you think?
  12. This doesn't look too different to how everything can be defined in RockMigrations... /** * Migrate issues related things * @return void */ public function migrate() { $this->log('Migrate Issues'); $this->rm()->migrate([ 'fields' => [ self::field_sections => [ 'type' => 'FieldtypeRockMatrix', 'icon' => 'files-o', 'tags' => self::tags, ], ], 'templates' => [ self::tpl_issues => [ 'childTemplates' => [ self::tpl_issue, ], 'tags' => self::tags, 'icon' => 'stack-overflow', 'parentTemplates' => ['home'], 'childNameFormat' => "title", 'fields' => [ 'title', ], 'noSettings' => 1, 'useRoles' => true, 'roles' => [self::role_admin], 'addRoles' => [self::role_admin], 'pageClass' => '\RockMag\Issues', ], self::tpl_issue => [ // no children allowed // children will only be added via rockmatrix field 'noChildren' => 1, 'parentTemplates' => [self::tpl_issues], 'tags' => self::tags, 'fields' => [ 'title', self::field_sections, self::field_pdf, ], 'pageClass' => '\RockMag\Issue', 'noSettings' => 1, 'noLang' => 1, // single language 'icon' => 'book', 'useRoles' => true, 'roles' => [self::role_admin], 'createRoles' => [self::role_admin], // may create pages 'editRoles' => [self::role_admin], // may edit pages 'addRoles' => [self::role_admin], // may add children (MagPage) ], ], ]); // create issues page if(!$this->getIssuesPage()->id) { $this->rm()->createPage("RockMag", null, self::tpl_issues, 1, ['hidden', 'locked']); } } But you get all your defined fields and templates with a single ->migrate() call ?
  13. Maybe worth a try: https://php-download.com/ PS: https://stackoverflow.com/questions/40545795/how-do-i-install-composer-php-packages-without-composer
  14. Yeah you can edit entries of course, but with a link that opens a panel or a new tab. Nothing that is great for bulk editing of many entries at once ?
  15. Thx for the kudos @Mikie but I think my modules will not make @fruid's clients happy. My modules are solving the problem of finding and/or displaying data, but are not doing anything in regards of bulk-editing data quickly ?
  16. Not sure, but you could create a test site using the blank or default site profile, then create 10k, 100k, ... pages and see if that has any impact on the page save timings.
  17. Some background info: https://github.com/processwire/processwire-issues/issues/579 Are you sure that the 10s delay is coming from the huge amount of folders?
  18. Thx! Good to know that. This should be quite an easy fix (something like changing getQuery() to getDebugQuery())...
  19. I think that should be a lot easier. You can setup any vhost you want on your server to access your website, eg website.com, website2.com, or as subdomain admin.example.com. So you setup 2 vhosts, one that points to the root dir with the folder containing your pw installation, so that you can access the frontend (example.com/app) and one that points directly to the app folder (eg admin.example.com) In admin.php you add some PHP to check for $config->httpHost and block access to the admin if the request comes from example.com or www.example.com. In ready.php you add some PHP that redirects requests coming from admin.example.com to admin.example.com/yourpwadminurl --> if anybody visits admin.example.com he/she will be redirected to admin.example.com/yourpwadmin --> users visiting example.com/app/yourpwadmin will be redirected to example.com/app (or blocked via 404, as you like)
  20. Quick idea, not well thought through: You could also create a custom DB table on which the client can work on and you write a script that pulls data from that table and populates pages via API (or synchronizes both).
  21. Hi @David Karich, happy to hear that ? Did you do a transition from RF2 to RF3 or are you using it in parallel? Would you mind sharing some details about how/why you are using RF with us? ?
  22. This one is actually important because it is misleading. @dotnetic could you please change that to "Aktion wird beim Speichern angewendet"?
  23. What do you guys think of changing that to Vertikal spiegeln Horizontal spiegeln Beides spiegeln 90° drehen (rechts) 90° drehen (links) 180° drehen S&W Sepia Actually I don't understand why we have the options for 270° rotation at all? -270 = +90, so why does it show up??
  24. Hahaha, read the post to the end before answering ?
  25. Hi @fruid, I understand your concerns. The db structure can look quite complex, especially if you are used to working with db tables and SQL select ... from ... etc; Teppo explained the reason for this structure. The great thing about this structure is that you get an abstraction layer that makes all the PW awesomeness possible. It transforms all the custom fields and data in the database into PHP page objects that can be used for easy and effortless markup generation. I'm talking about the great pw api ? echo $page->title; echo $page->headline; echo $page->image->size(200,200)->url; Display all that in multiple languages? Same code ? I think that's really genius! Are there downsides of this approach? Yes, as always. For example it is not easy for PW to do a "SELECT * FROM table_xy" to get a list of thousands of rows of data. That's because the magic of transforming the complex db structure into an easy to understand and use API has some costs. It needs to load all rows of data into memory and therefore this get's slow when working with lots of data. PW handles this by applying pagination wherever possible, so that it only loads chunks of data and stays fast. But still there might be situations where you simply need a good old "SELECT * FROM ..." and "foreach($pages as $page) $rows[] = [$page->title, $page->headline, ...]" is no option. That was quite a long introduction and explanation why I built RockFinder3 ? So at least the PULL part of your request is already doable ? What about the PUSH part (meaning updating data in the DB, doing "UPDATE ... , INSERT INTO ...")? First, you can still use native SQL commands on PW, it's quite easy: $result = $this->database->query("SELECT * FROM pages LIMIT 5"); var_dump($result->fetchAll(\PDO::FETCH_OBJ)); The problem is, that updating data can get quite complex because you need to update several tables, several fields, several languages... That's why such operations should really be done via API. That's of course a totally different approach if you are used to working with SQL commands, but it is the best option in 99,5% of the cases. There's a topic about that where I showed my findings: For the remaining 0,5%: You see, it can be quite easy. Is it a good idea? 99,5% no, because you don't get all the security features of PW that ensure that data is sanitized before storage etc. And you don't get the power of hooks. Updating pages via API will still trigger saveReady() and saved() hooks while direct SQL updates will not. Hope that helps ?
×
×
  • Create New...