Jump to content

sforsman

Members
  • Posts

    131
  • Joined

  • Last visited

  • Days Won

    5

Posts posted by sforsman

  1. Excellent write-up Ryan!

    Here's a quick tip. If you are processing large amounts of data, you should always use PW's field joining options to achieve maximum performance. Even if you only use a single field, you should get around 50% faster execution when the field is joined straight away. With two fields joined, the execution time will be cut into half (i.e. 100% increase in speed).

     
    Let's say you need to export the e-mail addresses of thousands of customers. Here's a simplified example using "on-demand" join
     
    // Prepare a pointer for writing the output
    $fp = fopen('customers.csv', 'w') or die('Failed opening the file for writing');
    
    // Ask PW to join two fields (the regular find() also supports this).
    $options = ['loadOptions' => ['joinFields' => ['customer_email', 'customer_number']]];
    
    // Searching for imaginary customers
    $selector = 'template=customer';
    
    // Find the pages using the new method
    foreach($pages->findMany($selector, $options) as $page) {
      // Write the data in CSV format
      fputcsv($fp, [$page->customer_number, $page->customer_email]);
    }
    
    // Free the pointer
    fclose($fp);

    As a reminder, you can also force some fields to be always joined (through PW admin).

    @Joer: That is pretty much what the implementation of findMany() does behind the scenes. However splitting the job into smaller batches still makes sense if you use multiple workers to process the data (e.g. for MapReduce or whatever) or if the execution time of your script is limited.
    • Like 16
  2. PW definitely works with FastCGI. Our configuration was a bit different though and we haven't experienced any problems like you described. For an example we were running PHP-FPM through UDS instead of TCP. We also map requests through SetHandler, not via ProxyPassMatch. It's basically the same way as Heroku runs it's PHP Dynos.

    I could be able to help, if you can be more specific about the redirects. For an example, does the browser show the full path as the location? E.g. the address bar says http://<mysite>/parent1/parent2/child'>http://<mysite>/parent1/parent2/child, but the content is wrong (i.e. the content of the homepage, which means the problem is related to the rewrite). Or does the user actually get redirected to http://<mysite>/, when he/she tries to access http://<mysite>/parent1/parent2/child'>http://<mysite>/parent1/parent2/child?

    Maybe it's the easiest to start by checking what happens when you go to http://<mysite>/index.php?it=/parent1/parent2/child Obviously replace the example names with real values first. The point of the test is to confirm GET-parameters are actually passed to PHP-FPM and that's why it's very important you "manually" pass the it-argument to the index.php -script.

    Seeing the PHP-FPM configuration - and it's logs - might also help debugging your problem, but please try the above first and let me know.

    • Like 1
  3. Before any tips I would like to understand why do you have these "section"-parents, when it seems that the user actually browses a merged list of all the artwork under the "base"-parent? Either way, you definitely have too much code and database queries just to resolve a position. I'm sure I will be able to help you if you could tell me a little bit more about the ideas behind the structure you have chosen.

    • Like 1
  4. Have you actually been able to reproduce the problem?

    I'm asking this because it's not clear to me if it was the user who posted the data like that, or if that's how the data gets stored in the database, or if you mean that when you try to print the value of the field in your program, it comes out as < instead of < on your screen. It's not even clear if the user who posted the data used a custom form or the PW admin.

    To answer your question, there is of course http://php.net/manual/en/function.html-entity-decode.php, which can also be used through PW like this

    $sanitizer->unentities($text);
    

    However I don't think it's the right approach - to me it sounds like you have a problem elsewhere. Maybe you are encoding the value twice. Could you please post us some bits of code which demonstrates your problem? I'm quite sure we can then easily help you fix your problem. It would also help if you could paste the raw value of the field directly from the database.

    • Like 3
  5. I'm pretty sure your problem is in PHP's session.cookie_lifetime setting. You can check the value with

    echo ini_get('session.cookie_lifetime');

    There are many ways to change it - for an example you can just put this in your config.php

    ini_set('session.cookie_lifetime', 86400);
    • Like 3
  6. First you should check if the folder and the files have correct permissions (i.e. that they are writable by the web server). Just to be sure, you should also check if your error logs (PW + web server) have any more information.

    Of course you can just try fixing the permissions with

    chmod -R a=rwX /homepages/42/d264496819/htdocs/new/site/assets/

    ...and then attempt uploading again.

    • Like 2
  7. What you need to understand is that in your example, you are storing the messages/errors in the session. This means you should be redirecting the user to display the message. Or to be precise, for them to be populated in $notices.

    If you want to add a message to the current request, you should use the "regular" message/error -methods. You can do this through most PW objects. For an example, change your line 67 to

    $form->error(__('There are errors in the form'));

    As a bonus, when redirecting, PW automatically stores such notices in the session . This means you could do

    $form->message(__('User registration sucessfull'));
    

    ...and the message wouldn't be lost. However in my opinion, it's cleaner to use $session->message() on line 98 because you are calling $session->redirect() on the next line.

    • Like 1
  8. Without commenting the actual implementation decisions, the reason for this behavior is that you haven't defined an action for the form. In such case, InputfieldForm will default the action to './', which then causes the described behavior.

    As Martijn already commented, this has nothing to do with save(), but only with the actual form that is rendered (and eventually posted). In a way, it doesn't have anything to do with PHP either. You would have probably noticed the problem, if you had viewed the HTML of the page.

    Anyway, to fix the issue, you can do this for an example

    $form->attr('action', $_SERVER['REQUEST_URI']);
    
  9. Good work! Regarding best practises, the only suggestion I have is that the tutorial should be changed to use environment variables for the database connection. This has several benefits, for an example

    • It would be very easy to launch a separate development site, which uses a different database, because all you need to change is the environment variable when launching the development web container
    • You could easily use the same config.php as a template for new sites
    • You don't have to store sensitive information in your version control
    • The config.php becomes more cloud compatible (i.e. a twelve-factor app)

    Also since the MySQL-container is linked to the web-container, the config.php can directly use the environment variables set by Docker.

    An example config.php would be

    $config->dbHost = getenv("MYSQL_PORT_3306_TCP_ADDR");
    $config->dbName = getenv("MYSQL_DBNAME");
    $config->dbUser = getenv("MYSQL_DBUSER");
    $config->dbPass = getenv("MYSQL_DBPASS");
    $config->dbPort = getenv("MYSQL_PORT_3306_TCP_PORT");
    

    Obviously launching the web container(s) would need to include these variables too, e.g.

    docker run -e "MYSQL_DBNAME=mypwdb" -e "MYSQL_DBUSER=mypwdbuser" -e "MYSQL_DBPASS=mypwdbpass" --name celedev-site -p 8088:80 --link database:mysql --volumes-from celedev-data -d php-5.6-pw-celedev
    

    Just my two cents :)

    • Like 7
  10. If methods are really meant to be used only by a single PageType, isn't it better to go the inheritance route?

    For some cases, it's a matter of preference. What's also cool about the inheritance route, is that you can use type hinting in your methods and functions. It makes the code more readable and also protects from errors. Also there is always some overhead (even though very small) when you are executing hooked methods.

    The thing that always bugged me about the hooking way is, that a added methods are available to all Pages, which is almost never what I want it to be.

    As you already noticed, you can use conditional hooks. And you can of course check the template of the Page in question inside the hook as well.

    Anyway, I would go with inheritance in your case. First and foremost because you don't need any autoloading modules, and you never have to wonder 'where the heck did I put that hook'. In my opinion it makes your application more manageable.

    • Like 2
  11. Simply put, there is absolutely no reason to go with Drupal in the situation you described. ProcessWire can easily handle your requirements. As a bonus, you will have fun at it!

    I'll also clear few misconceptions. ProcessWire can easily handle hundreds of thousands of pages, so you don't need to worry about that. What you need to worry about is the design of your templates, fields and relations. Making wrong selections there can severely impact the performance of the site. And even then, the community is happy to help if you face performance issues :)

    User registration won't be a problem either since users in PW are basically just pages. You can even extend the built-in 'user'-template with more fields.

    • Like 4
  12. So everywhere that a page is instantiated in PW, it will use the alternate class for that page?

    Yeah, exactly :) Well to be precise, it will use the alternate class for every page that is using the template for which you have changed the Page Class. The ProcessWire users are implemented exactly like this, so it's definitely a core feature. Also since the classes extend Page, the objects will be valid to any methods that expect Page-objects.

  13. Haha here's the quickie then

    ALTER TABLE `field_<the_name_of_the_float_field>` MODIFY data DECIMAL(12,2);
    UPDATE fields SET type='FieldtypeDecimal' WHERE id=<the_id_of_the_float_field>;
    

    If you need more than two decimals (or more than twelve digits in general), you can safely increase the precision through the module afterwards.

    • Like 3
  14. @thetuningspoon:

    There is only one way to extend the Page -class, e.g.

    <?php
    
    class MyPage extends Page
    {
      public function myFunction()
      {
        return "I have been created for great endeavours"
      }
    }
    
    ?>
    

    After you have made sure the class exists (preferrably through autoloading), you just enter the name of the class into the 'System' -tab of the template in question (under "Page Class Name").

    • Like 5
  15. @doolak:

    It is important to realize that the JSON-data returned by the module will be decoded into a "dummy" PHP object (an instance of stdClass), based purely on the raw information that can be seen in the JSON-representation. Such an object has nothing to do with ProcessWire's objects/classes. So the consuming service has absolutely no idea of any other properties other than those that are given to it by the module. You can basically compare it to an array. Hence you cannot use any properties related to a ProcessWire class, such as FieldtypeImage.

    The simplest option is to build the URL manually, e.g.

    <img src="http://xyz.de/site/assets/<?php echo ($post->id . '/' . $post->mf_termin_image->basename); ?>">
    
    • Like 4
  16. Hey Pete! Altering the underlying column from a FLOAT to DECIMAL is safe - the other way around not so much, especially with high precision deicmals.

    It would also be quite trivial to implement a conversion UI directly in the module (i.e. so that the module lists FieldtypeFloats and lets you select which fields to convert into FieldtypeDecimal). Let me know if this feature would help your case - I'm back in the game so, once again, I have time to contribute to this lovely community :)

    • Like 3
  17. Are there any good practices dealing with this kind of situations?

    First I'd rather find out what you are trying to achieve here :) It would be terribly slow to filter results based on a block of PHP code instead of a field in the database. If you need filtering and pagination based on this "property", you should implement it, whatever it is that you are implementing, as a database-field (one way or another). If you just think about it for a moment, you would otherwise need to fetch every single page in the database and then execute the hook to evaluate the value of the property and then decide whether the page should be included in the result or not. I would say there isn't a good practise to do that. But I'm pretty sure that what you are trying to do could be implemented as a field. Just fill us in a bit more!

×
×
  • Create New...