Jump to content


nik

Member Since 25 Mar 2012
Offline Last Active Today, 05:27 PM
-----

#35699 If statement inside recursive function

Posted by nik on Today, 12:53 AM

If I've understood right you only need to get rid of the <ul>...</ul> wrapping the initial function call and modify the if-statement inside the function just a little bit to let it proceed on the first round even if there are no records found. Like this:

<?php

function listProducts($productCat,$level=0) {

    $result = wire('db')->query("SELECT id, product, productcat FROM products WHERE productcat='$productCat' ORDER BY subcat");
    if($level > 0 && $result->num_rows == 0) return;
    
    echo "<ul class='sortable'>\n";
    while (list ($id, $product) = $result->fetch_row()) {   
        
        echo "<li id='item_{$id}'>\n";
        echo "<div class='dd-handle'>{$product}</div>\n";
        
        listProducts($id,$level+1);
        
        echo "</li>\n";
    }
    echo "</ul>\n";

}
?>

<div> 
    <h5>Products</h5>
    <?php echo listProducts(0);//call the function ?>
</div>

 

As a side note, I usually build a simple safety net when using recursive functions just to be on the safe side if (when) there's suddenly broken data in the database. Here that would mean adding one line at the beginning of the function:

// ~25 levels of product categories could be considered an error, I think.
// Use something big enough to allow any legitimate data but small enough to allow the server stay alive.
if($limit > 25) throw new WireException("Recursion gone wild");

 

While it's not necessary, it's a small price to pay for peace of mind :).




#34988 Handling Categories on a Product Catalogue

Posted by nik on 15 May 2013 - 07:05 AM

@renobird, @diogo: ...or just use "has_parent=/shoes/". :)


#34930 Module: AfterSaveActions

Posted by nik on 14 May 2013 - 04:36 PM

Thanks for the report guys!

 

Redirect url on page save has changed a couple of months ago a bit and my regex was too picky. This is fixed now. I also fixed the action when field is being edited in some other context than default one. Module version is now 0.0.7 both in GitHub and modules directory.




#34798 PageReferencesTab

Posted by nik on 13 May 2013 - 04:51 PM

Thanks @arjen & @adrian for the report. And thanks @soma for giving the right solution :). It definitely was a bug in this very module.
 
I've updated the module to check id has been given as a GET parameter before using it to get the page being edited. This seems to solve the problem you guys were facing, just like soma said. New version is in GitHub and version number has been updated in the modules directory as well.
 
@arjen: Soma was right also regarding that bitwise-and (naturally ;)). That line, and two similar ones elsewhere, checks if the template has the system flag set. Property 'flags' of a template is a bit field where there's possibly more than one flag (bit) set at a time. So it wouldn't be correct for example just to see if the flags value equals to the value of system flag, but it has to be done using a bitwise operator.

Sidenote: actually in this very case there's only the system override flag that could co-exist with the system flag, but still that's the correct way of checking if a flag has been set :).




#34641 Most selector operators throwing errors

Posted by nik on 11 May 2013 - 08:04 AM

...but here it actually is an array, thus the name  :).

 

When PHP sees we're dealing with strings the string representation of a variable is used. In this case the trigger is an unescaped dollar sign between double quotation marks, but it could be the concatenation operator '.' as well. To get such a representation, the __toString() method of the class (PageArray in this case) is automagically called. See http://www.php.net/m...bject.tostring.

 

The __toString() method has been implemented to return a single page id (Page or PageArray with one item) or a list of page id's with a '|' (pipe) as a separator.

 

I was trying to clarify the situation but I'm not sure if that's what happened after all :D.




#34606 Check if a given page has children

Posted by nik on 10 May 2013 - 02:04 PM

What you've got as a result is a PageArray so you'd need to check the count like this (edit: ..and change find to get as diogo says below):
if(count($info) >= 1) {
    // do stuff
}
If there are potentially lots of children, it would be better to do it for example like this:
$childCount = $pages->count("parent.title=previous caption winners");
if($childCount >= 1) {
    // do stuff
}
This way you wont end up fetching all the children just to count them. :)


#34034 Module: Testrun selectors + find() from admin (ProcessSelectorTest)

Posted by nik on 02 May 2013 - 01:21 AM

Thanks for the report diogo! Your good explanation made it really easy to spot the problem. There clearly was a bug with single page Page fields: they were not handled correctly at all. :)

The bug is now fixed and version 1.1.2 of the module has been released.


#33948 ProcessWire 2.3 features

Posted by nik on 30 April 2013 - 04:25 PM

"Recommended by Mr. Log Himself", it seems. We're not getting off-topic, are we?


#33945 ProcessWire 2.3 features

Posted by nik on 30 April 2013 - 04:11 PM

..and now I can let go of trying to come up with a less questionable name for a planned module listing active hooks! Working title was Hook*r.


#33535 $pages->get("/features")->find("field1<field2...

Posted by nik on 22 April 2013 - 10:06 AM

The post isellsoap linked to above has Ryan's explanation on why it's not straightforward to compare two fields - and yes, there's a solution also. But I'd like to propose another solution as well in case you'd need better performance or native pagination (lots of pages for example).

You could add a helper field "f1_f2_difference" and populate it on page save with the difference of field1 and field2 (field2-field1). Then you'd be able to do this:
echo $pages->find("has_parent=/features/, f1_f2_difference>0");
 
There's an example of pretty much the same thing in the final post of this thread and for some more information read also this thread.

But you've got a working solution already so there's probably no need to take this route :).

--
@adrian: your suggestion would be fine when the fields are in the same database table (like created and modified are). Here field1 and field2 are presumably custom fields and thus in their own tables. An SQL JOIN would still do it, but using selectors gives the advantage of grants and visibility being taken care of.


#33148 Search field in the first repeater

Posted by nik on 17 April 2013 - 03:52 AM

I'm afraid there's no selector you could use to filter based on nth record in a repeater. But there are other ways to get there. I'm assuming you've got a template "trip" with a repeater field "cities_repeater", correct? I'm asking because you're talking about a repeater but the structure (and get()->children()) looks like you've got pages inside each other.
 
So, one option is to find all trips via Berlin, loop through the results and pick only those that have Berlin as a starting location. If the amount of trips starting from a city isn't going to grow too much (so that you don't need to paginate the results) and the amount of trips via a city doesn't get too high either, this would probably work out just fine.
 
On the other hand, you can make the trips searchable with a selector based on their starting city with a little autoload module and a hook. Create a new field "starting_city", add it to the trip template and make it hidden. Then create a module hooking after Pages::save. In the hook check for the trip template and then populate starting_city with the first element of cities_repeater. And remember to save only the starting_city field to avoid an infinite loop :). See Pete's example and Soma's comments in this thread for a code example.
 
Now that you've got starting_city in a separate field it's a walk in the park to write the selector you're after:
$trips = $pages->find("parent=/trips/, starting_city=berlin");
Do remember that in order to get that hidden field populated for all the trips, the hooking module must be installed before any trips are actually created. If you've already got the data in place, then you need to get the module working and either save each trip (no changes needed, just edit+save and the hook will kick in) or create a little script that populates the field for the first time.


#33114 Image Field description not saving

Posted by nik on 16 April 2013 - 01:25 PM

Hi Ovi, and welcome to the forums!

That sure sounds weird, but looks like I'm not able to reproduce what you've described here. I've tried both 2.3 master and dev branches with a few different combinations of image fields.

Which version of PW are you running? Do you have debug-mode on (in site/config.php: $config->debug = true;)? Have you checked the error log (site/assets/logs/errors.txt) and Javascript warnings/errors in the browser before/during save? Any traces of warnings let alone errors there?

Any modules installed, apart from those coming with the standard package - selfmade custom ones maybe? Default admin theme in use?

Does it make a difference if you reorder the image fields? I mean is it always the same field that is working, regardless of it being the first one in the edit form? You could also try and leave only a minimal set of fields to the template: title and both image fields, but nothing more. Still behaving badly?

Sorry, quite a many questions - but those are the things I'd try at this point :).


#32995 MySQL LIMIT with ProcessWire API

Posted by nik on 15 April 2013 - 04:39 AM

Yes, something like that. I'd put it this way:

  • When using tables in another database, PW selectors can't help you so just use plain SQL. If you like, you can use PW's Database class for connecting, some escaping and debug timers, but other means of getting there are ok too.
  • When using data from pages in PW, use PW selectors and you'll get most likely the best performance with all the tricky things like grants taken care of.
    • If the selector engine can't offer what you need, you're still able to use plain SQL. But go down that road only if you really need to and preferably know what you're doing :).



#32993 MySQL LIMIT with ProcessWire API

Posted by nik on 15 April 2013 - 03:45 AM

@kongondo: It looks like you're trying to implement something that's in core already. Take a look at http://processwire.com/api/selectors/, especially "Limiting the number of results returned by a selector". There's a description of limit, start and even end, should you ever need it.

 

In short: enable page numbers for your template and use only limit without start in your selector. You can get the total number or rows matched from $values->getTotal() and even render a pager using $values->renderPager() if you like.




#32852 Display a list based on custom field

Posted by nik on 13 April 2013 - 06:49 AM

In addition to what @DaveP said you need to change $entry->title to $drink->title, as there's no variable called $entry there. That's a little typo in diogo's example left from the first version.