Jump to content

I have difficulties to find the right selector...


titanium
 Share

Recommended Posts

I would like to find all pages which have a field with the name 'intro'. This intro's field value should be checked for a string length less than 10 - that should include the pages which have an empty value of introtext.

Pseudo code to make it clear:

$pages->find(strlen('intro') < 10)

How could I achieve that?  ???

Link to comment
Share on other sites

Hello. Best way i can think of is writing a custom module that actually stores the length of that field in a separate, int field.

Try this:

<?php

class PageIntroLength extends WireData implements Module {

    public static function getModuleInfo() {
        return array(
            'title' => 'Get Intro Length for filtering',
            'version' => 100,
            'summary' => 'Stores the intro length into a field',
            'singular' => true,
            'autoload' => true,
        );
    }

    public function init() {
        $this->pages->addHookBefore('save', $this, 'stroreIntroLength');
    }

    public function stroreIntroLength($event) {
        $page = $event->arguments[0];

        // we can specify a certain template that this module should run for. As it is, it will run for all pages. Just uncomment the line blow and replace "template_name_here" with the name of your template
        //if($page->template->name != 'template_name_here') return;

        // get the length of the intro and store it in a field named intro_length. YOU WILL HAVE TO CREATE THIS FIELD AND ATTACH IT TO THE TEMPLATE YOURSELF FOR THIS TO WORK.
        $page->intro_length = strlen($page->intro);
    }
}

Save this as PageIntroLength.module and upload it to your modules directory. Install the module (click check for new modules first.)

Don't forget to create the field (of type integer) that will store the length. You must name it "intro_length " without the quotes or this won't work.

Make the field hidden so the editors don't see it.

After you've done all that, each time you save a page, the intro_length field will get populated with an integer that represents the number of characters in the intro field.

Then you can filter like this:

$pages->find(intro_length < 10);

This code is untested, and i am very much a beginner, so if you have any problems just post here.

Please let me know how it works! :)

  • Like 3
Link to comment
Share on other sites

Not sure how many pages you have (so this could be slow) — perhaps limit to a particular parent page or template?

$ps = $pages->get("/")->children;

foreach ($ps as $p){
    if (strlen($p->intro) < 10){
        // do things
    } else {
        // do other things
    }
}

untested, and written in the browser.

Link to comment
Share on other sites

I would like to find all pages which have a field with the name 'intro'. This intro's field value should be checked for a string length less than 10 - that should include the pages which have an empty value of introtext.

Pseudo code to make it clear:

$pages->find(strlen('intro') < 10)

How could I achieve that?  ???

I'm not clear about this. Is your ultimate aim to check whether "introtext" is empty? Is "introtext" a field? If so, all you need is something like this for the current page...from that you get the idea of checking many pages...

if ($page->introtext) {// this checks if introtext is empty
// stuff
}

else {
      echo "move along! no intro to read here";
} 
  • Like 1
Link to comment
Share on other sites

Or you could use SQL directly like so:

$pageIDs = array();

$result = $db->query("SELECT id FROM pages INNER JOIN field_intro ON field_intro.pages_id = pages.id WHERE LENGTH(data)<10");

while($row = $result->fetch_row()) $pageIDs[] = $row[0];

$pageArray = $pages->getById($pageIDs); // $pageArray contains what you want

EDIT: If kongondo's assumption is correct that you are just looking for an empty intro field, then his approach is the way to go for sure!

  • Like 3
Link to comment
Share on other sites

yeah, I was a bit confused about the < 10.

 

I was also thinking the goal was to "find" all pages that have a value for intro_text.

Not just show show intro_text if populated.

Threw me off as well. You could still be right; OP will let us know ;)
  • Like 1
Link to comment
Share on other sites

Threw me off as well. You could still be right; OP will let us know ;)

It's a pleasure :-)

First let me thank you all for these different and very interesting approaches - there is so much to learn from! I like Ovi's module solution very much, it's something I would not think of. Maybe we should establish some kind of Processwire Coding Contest - every participant get's the same excercise, and the most "beautiful" or "creative" solution wins. ;-)

I was looking for all these pages, which intro_text field contains less than 10 chars; this includes the pages which have the field set, but its value is empty. Pages, which don't have the field set, should not be listed.

My initial solution was:

// get all pages, even the hidden ones, sort by name
$pages = $this->pages->find('include=hidden, sort=name');

if (count($pages)) {
	foreach ($pages as $page) {
		if ($page->template->fields->get('introtext') && strlen($page->introtext) < 10) {
			doSomething();
		} else {
			$pages->remove($page);
		}
	}
}

This works fine so far, it returns a page array which contains the pages I want. Unfortunately, it doesn't work in conjunction with the renderPager() method I would like to use afterwards. I suppose the reason for that is explained by soma here. That was the reason I was posting, because one needs a proper $pages->find(...) to get renderPager() to work, as far as I understand it.

Link to comment
Share on other sites

I think you could use your code (with an addition) to create a selector value to use with $pages->find. Then replace doSomething(); with 

$selector .= $page->id . "|";

and after the end of the foreach 

rtrim($selector, "|");

to knock off the last (redundant) pipe, should leave $selector containing something like 123|456|789 which you can then plug into $pages->find for renderPager().

(Completely untested, but should work, I think. (I hope.))

  • Like 1
Link to comment
Share on other sites

Seems like all of the solutions here are shorter than mine and so they are better from a KISS perspective. Like i said i'm a beginner who just learned to use the hammer so many problems are starting to look like nails to me :)

But just wanted to mention that with my solution you should be able to use renderPager() since you're not working with in-memory arrays.

I would be really curious to know how DaveP's solution plays out and how it compares in processing speed with mine - right now i have no idea which would be faster.

BTW, if you're looking to filter out all the pages who don't have the intro field from the module, just replace:

// we can specify a certain template that this module should run for. As it is, it will run for all pages. Just uncomment the line blow and replace "template_name_here" with the name of your template
        //if($page->template->name != 'template_name_here') return; 

with:

if (!$page->intro) return;
  • Like 1
Link to comment
Share on other sites

  • 5 years later...

It would be quite nice to have a native PW strlen() selector option.

Just today I was puzzled when I wanted to list all pages that have image descriptions. Strangely enough, I got way too many results with this selector:

images.description!='', parent=1234, template=foo, include=all

When I loop through all the page's images (or check manually) and do if(strlen($p->description) > 2) I get almost no results.

Link to comment
Share on other sites

On 6/21/2013 at 10:38 PM, DaveP said:

I think you could use your code (with an addition) to create a selector value to use with $pages->find. Then replace doSomething(); with 


$selector .= $page->id . "|";

 

Thanks, This is helpful.

  • Thanks 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...