Jump to content

bernhard

Members
  • Posts

    6,671
  • Joined

  • Last visited

  • Days Won

    366

Everything posted by bernhard

  1. ~488 websites listed here using ProCache: https://nerdydata.com/search?query=%2Fsite%2Fassets%2Fpwpc%2Fpwpc
  2. thx @szabesz, cheating like that would definitely be an option (and also not too hard in that case). just thought there might be some magical pw-way of doing that
  3. $exhibitions->append($exhibition->getForpage());
  4. Hey @adrian, glad you gave it a try 1) No, I guess this was just for development. PR welcome (really need to work on other projects atm, see rockgrid and rockfinder for example and some client work). 2) Everybody who wants to (or needs to) remove the branding can contact me via PM 3) I agree. I've used Nette Live Validation in an older project and this looked a lot better, but I've just not had the time to implement it. This might be more complex when thinking about supporting different css frameworks. Or it might be as easy as loading this script: https://github.com/contributte/live-form-validation. I don't know and I wanted to go with the default tools as I'm short on resources for this module. And the most important part was that it works and is quick to setup and save, of course If you come up with a better solution I'm happy to merge it, but at the moment, I'm sorry, I have other priorities.
  5. Can you be more precise please? What kind of calculations are you talking about? I'll try an answer with a guess This is a quick test i did with 10.000 fake invoices. The result is great (but see later). Here the setup for the Tracy Console: $selector = 'parent=/invoices, limit=2'; // the limit is for demo of the sql $finder = new RockFinder($selector, ['value', 'date']); $finder->sort = false; $sql = $finder->getSQL(); d($sql, [6,999]); This finds all invoices and returns their "date" (a datetime field) and their "value" (random number between 1 and 100). The resulting SQL is this: SELECT `pages`.`id` AS `id`, `value`.`value` AS `value`, `date`.`date` AS `date` FROM `pages` /* --- join value --- */ LEFT JOIN (SELECT `pages_id` AS `pageid`, `value`.`data` AS `value` FROM `field_value` AS `value`) AS `value` ON `value`.`pageid` = `pages`.`id` /* --- end value --- */ /* --- join date --- */ LEFT JOIN (SELECT `pages_id` AS `pageid`, `date`.`data` AS `date` FROM `field_date` AS `date`) AS `date` ON `date`.`pageid` = `pages`.`id` /* --- end date --- */ WHERE `pages`.`id` IN (42063,42064) Now the funny part: You can do all kinds of custom SQL with that returned SQL statement, for example grouping the invoices by month and building a sum of their values: $results = $this->database->query("SELECT sum(value) as monthsum, DATE_FORMAT(date, '%Y-%m') as date FROM ($sql) AS rockfinder group by date"); And here the absolutely awesome result: So you get aggregated data for 12 months in no-time (166ms!!) with some VERY basic SQL. I'll think about how this can be made even easier in the future. Maybe by providing a method that does the query and returns the result. I'm open to suggestions. The maybe greatest thing about that is that you do not need to take care about processwire page statuses. That has always been a real pain when working with SQL because it makes things so complex. You always need to think about adding WHERE pages.status < ... and so on. That sucks. Now you just build your custom "view" with RockFinder and do some simple SQL on that result. You get the idea? Edit: I put $finder->getSQL() inside the timer, now it took 280ms - still great IMHO. And see how easy it is to add an invoice-count for that month for example
  6. I've setup a gallery field on one site. I forgot to set a maxSize for those images, so the gallery images have >5MB per Image, which is of course not ideal. I changed the settings now to a max of 1024x1024 px - but the images are still in max resolution on the server. On the frontend gallery I changed the links to $img->maxSize(1024,1024) so the users will get the resized images, but I would like to save some space on the server and recreate (resize) the already uploaded images to fulfill this maxsize restriction. Any ideas how this can be done easily? Thanks
  7. I guess Tracy is not loaded when your init fires. You can try to attach your hook in ready() instead of init(). Sidenote: You should also be able to use the d() shortcut method without the Tracy class
  8. The "option" to sort on the server side is of course always there. But I set it to use sorting by default now. I think the worse performance will not matter in most of the cases. If it does, the user will realise it and can easily turn it off. It would be worse to think everything works as expected and then get some unexpected results due to sorting turned off while you think it should actually return a sorted resultset ( like from a selector containing the sort keyword ). Thanks for your feedback.
  9. Sorry guys for all those posts... Found the performance-killer: It is the ORDER BY field(`pages`.`id`, 52066,52067,52068,52069,52070 ... ) part. Without retaining the sort order of the pages->findIDs it is a LOT faster (4s without sort compared to 60s with sort and 75 using findMany): 91300 items: rockfinder = 4385.5ms | findmany = 74213.9ms | 5.91% I'll add this as an additional option and switch sort order OFF by default since sorting will be done by RockGrid anyhow No problem at all. I need this stuff for my own work, so any help is welcome but of course not expected PS: again the tests without sort order 11 items: rockfinder = 4ms | findmany = 6.9ms | 57.97% 1000 items: rockfinder = 35.7ms | findmany = 744.2ms | 4.8% 5000 items: rockfinder = 165ms | findmany = 1675.4ms | 9.85% 10002 items: rockfinder = 327ms | findmany = 3359.5ms | 9.73% 35000 items: rockfinder = 1745.2ms | findmany = 28547.7ms | 6.11% 91300 items: rockfinder = 4385.5ms | findmany = 74213.9ms | 5.91% Now that looks a lot better, doesn't it?
  10. Another performance test using findMany() So this looks like findMany() is a lot faster, but this is not true because creating the proper array of data takes longer than with RockFinder: $selector = 'parent=/data'; $finder = new RockFinder($selector, ['title', 'headline', 'summary']); t(); $result = $finder->getObjects(); d($rf = t()*1000, 'query time in ms (rockfinder)'); d(count($result), 'items'); d($result[0], 'first item'); t(); $result = $pages->findMany($selector); //$finder->getObjects(); d($fm = t()*1000, 'query time in ms (findmany)'); d($count = count($result), 'items'); d($result[0], 'first item'); t(); $arr = []; foreach($result as $p) { $arr[] = (object)[ 'id' => $p->id, 'title' => $p->title, 'headline' => $p->headline, 'summary' => $p->summary, ]; } d($fm2 = t()*1000, 'create array'); d($arr[0]); d("$count items: rockfinder = " . round($rf,2) . "ms | findmany = " . round($fm+$fm2,2) . "ms | " . round($rf/($fm+$fm2)*100, 2) . "%"); Result: Some other tests: $selector = 'parent=/persons'; // 11 items: rockfinder = 3.8ms | findmany = 7ms | 54.29% $selector = 'parent=/dogs'; // 1000 items: rockfinder = 41ms | findmany = 722.1ms | 5.68% $selector = 'parent=/cats'; // 5000 items: rockfinder = 221.4ms | findmany = 1660.8ms | 13.33% $selector = 'parent=/invoices'; // 10002 items: rockfinder = 526.6ms | findmany = 3385.3ms | 15.56% $selector = 'parent=/data'; // 35000 items: rockfinder = 7161.4ms | findmany = 27722.9ms | 25.83% $selector = 'parent=/data2'; // 91300 items: rockfinder = 59523.6ms | findmany = 76495.8ms | 77.81% What is very interesting (and not good), is that the time needed for RockFinder increases disproportionately when querying > 10.000 pages; 10.000 items = 500ms, but 3x10.000 pages = 7.000ms Maybe any sql experts have an idea?
  11. Another update is online (branch DEV3): https://gitlab.com/baumrock/RockSqlFinder/tree/dev3 This is a major upgrade, a complete rewrite and finally a really good solution imho: I changed the syntax to object-notation in preference of nested associative arrays and it's a lot cleaner and easier to setup and read now. I rewrote the logic completely. It is NOT recursive any more but it takes away a LOT of complexity. You can add "fields" to your find-operation and those "fields" are fully customizable classes. The module ships with predefined classes for FieldtypeText (easy as it is just a column in the DB), FieldtypeFile (that shows concatenated filenames and descriptions) and FieldtypeRepeater (that shows concatenated data of the repeateritem's fields). The user can add custom FieldFinders in /site/assets/RockFinder (this will be the final name of the module). Possibility to add custom separators for concatenated fields Easy to create custom SQL by wrapping the created SQL in your own statement (SELECT ... FROM $finder->getSQL() GROUP BY ...) Examples: Query 10.000 invoices and return their date and value: Query all persons and show content of images (fieldtypeimage) and repeater (fieldtyperepeater): Same example but with image descriptions and all repeateritem's fields: Find 35.000 pages: This takes significantly longer than finds until 10.000 items. Maybe @adrian or @theo you have time to compare these results on your setups? Todos: Support for FieldtypePage (and other fieldtypes?) Support for Multilanguage (should not be hard, I've developed it with that in mind) Aggregation functions like sum(), avg(), min(), max() Support for closures? What do you guys think?
  12. thx, this works looking forward to hearing their feedback!
  13. I'm doing a complete rewrite (again ). What I have so far is this: <?php namespace ProcessWire; class RockFinderField extends Wire { private $name; // name of the final object property private $field; // name of the field to query private $closure = null; // closure to calc value /** * constructor */ public function __construct($name, $field) { // set the final column name for this field if(is_string($name)) $this->name = $name; else $this->name = $field; // check the field type if(is_callable($field) AND !is_string($field)) { $this->closure = $field; } else { $this->field = $field; } } } And in the module I do this: foreach($fields as $key => $value) $this->fields[] = new RockFinderField($key, $value); bd($this->fields);
  14. Ok, thx. My class is indeed extending Wire... Maybe there is a possibility to check for the number of properties the debugInfo object returns and in case it is 0 it falls back to the original object dump?
  15. Same here: I think they are really great! It makes the setup so much cleaner and more readable and also more flexible. For example I'm using a region "scriptsbottom" at the end of my <body> and whenever an included section needs some javascript I just write the markup and append the script to that region: // _main.php <region id="header"></region> [...] <script><region id="scriptsbottom"></region></script> // slider.php <section id="header">... my great slider markup ...</section> <region pw-append="scriptsbottom"> $('#slider').init(); </region> IMHO this is much more readable than using delayed output with php variables and then "messing" around with $config->scriptsbottom .= '$(\'#slider ... ' (doing some crazy escaping or ob_get_clean() or the like.
  16. Hey @adrian, what do you think of adding a check if debugInfo is available for the requested object and if not, set it to "false" automatically? I'm working on my RockFinder module and wanted to debug my subclass. This was the result: Switching "debugInfo" to false I get this: Which is of course much more helpful. Luckily I remembered about that because we were talking about it here, but if someone missed that it could be quite hard to find out what is going on and why the information does not show up... Also it is quite annoying to always set ['debugInfo' => false] for every quick d($myobject)
  17. Thx, I know all those options. Don't know exactly what I meant with my comment I think I was talking about some kind of staging/dev setup... Not related to vscode of course
  18. Phew... This was quite hard but finally I made progress. Please see the dev branch if you want to play around @flydev : https://gitlab.com/baumrock/RockSqlFinder/tree/dev#notes (other parts of the readme are outdated meanwhile, It's just some notes for myself and old examples..., sorry no more time today). This is an example query with a join. This is necessary for pagefields when you want to get not only the page id's but also the related page's fields information like "title": Next step is to make CONCAT operations possible so that the join will return a concatenated string of ids and titles (miau, cat ..., mimimimi). This should also make aggregations like sum() possible (see here: https://gitlab.com/baumrock/RockSqlFinder/tree/dev#notes -> not much change needed for the resulting sql). The new version of the module is completely recursive, so I hope (haha...) that support for image fields with description (in this case it's not a related table but on the same table like the imagefield) easy. We will see... PS: Actually I just realized that defining the field "cats" is stupid when we define a join named 'cats'. Because I'm removing this field later anyhow... need to change this. You see there will be some more changes in the future, sorry...
  19. thanks for the headsup glad you found it! I'm right now working on a complete rewrite of the module. The syntax will change a little bit but be a lot more flexible. I'm working on a recursive version that should make it possible to easily query pages that are referenced by pagefields. This is a huge timesaver when working with mysql because this joins can really be a tedious task. This setup should also make it possible to do easy aggregations via custom SQL statements. That's why I think I will not need your aggregation functions for $pages api Hmm... Thinking about it... Maybe this could be helpful in some situations. Maybe you want to share it in the dev board with all of us? I hope I can push an update this week.
  20. awesome! this helps a lot, thanks
  21. just merged @gebeer's changes to support multiple renderers in separate files and he also added a bootstrap renderer thank you!
  22. yes, you can $session->redirect() after processing your form, then it will clear your post data. next thing to take care of is when the form is submitted and there is a validation error on the server, the form for the user needs to be re-populated with the values already submitted
  23. Hi @SamC, great to see you are making progress 2 things: 1) I'm always sending forms to the same page an in that template I do something like this: if($config->ajax AND $input->post->submit) { // process form } // regular template code Usually this makes the setup easier. 2) As you see there is a LOT to consider with forms. That's why I built the RockForms module using Nette Forms, because that takes care of all this stuff. I'm not saying "stop learning and use my module" here But the nette docs might be an interesting read for you. You'll come across the things mentioned above (CSRF, validation etc.). And besides that, it is the only library I found that does validation on the client side and on the server side with one single setup of the form
  24. Another option could be to use repeaters in your template. This might or might not be better and depends a lot on your situation... The TOC would be really simple then. Find operations might be harder...
  25. Sorry, no idea. Only situation where I know that it is slow is when it loads pages because of closures. Do you have the current version? Is this check available in your module? https://gitlab.com/baumrock/RockSqlFinder/commit/17464b0397ed5f3d62bc86177d0c2395f33b5d9e Thanks, no need at the moment
×
×
  • Create New...