Jump to content

Select/sort by text length?


theoretic
 Share

Recommended Posts

Hi friends! And thanks for Processwire )

Maybe I'm missing something, but it appears that PW doesn't have a dedicated selector for text length.

Possible selector:

$selectedUsers = $users->find("name.length<=5,sort=name.length");

Expected output:

Bob
Andy
Maria

( Steven and Andrea will be skipped because that names are too long )

Of course it's possible to filter the find() results using some custom function, but having a native selector instead could be a better practice.

So does that silver bullet really exist? If no, I think it could be useful to many happy PW developers )

Link to comment
Share on other sites

A short&quick&dirty module that adds .length (switching back and forth between regular Text fields and "Text with .length Selector" should not cause any troubles):

<?php namespace ProcessWire;

class FieldtypeTextWithLength extends FieldtypeText {

	public static function getModuleInfo() {
		return [
			'title'			=>	__('Text with .length Selector', __FILE__),
			'summary'		=>	__('Like FieldtypeText, but with a subfield selector .length for string length comparison', __FILE__),
			'version'		=>	'0.0.1'
		];
	}
	
	public function getMatchQuery($query, $table, $subfield, $operator, $value) {
		
		$database = $this->wire("database");
		
		if($subfield === 'length') {
			
			$table = $database->escapeTable($table);
			$value = $database->escapeStr($value);
			
			$query->where("LENGTH({$table}.data){$operator}$value");
		} else {
			parent::getMatchQuery($query, $table, $subfield, $operator, $value);
		}
		
		return $query;
	}
	
}

 

  • Like 3
  • Thanks 2
Link to comment
Share on other sites

Wow @BitPoet that's real bit poetry ? I've taken your example and did some research in the code and found this as an alternative solution:

<?php
$wire->addHookAfter("PageFinder::getQuery", function (HookEvent $event) {
  // get the DatabaseQuerySelect object
  $query = $event->return;
  
  // modify the query to only find names with length < 6
  $query->where("LENGTH(pages.name)<6");
  
  // remove the hook after first execution
  $event->removeHook(null);
});

// find users with names < 6 chars
bd($wire->pages->find("template=user"));

It's important to add the hook immediately before the $pages->find() call. And it's important to remove the hook so that it only executes once.

  • Like 4
Link to comment
Share on other sites

On 11/22/2023 at 1:30 PM, bernhard said:

@BitPoet that's real bit poetry

Thanks! Appreciated!

? about it, in times of utf8(mb4) one might want to use CHAR_LENGTH instead of LENGTH. The first one counts the code points, i.e. visible characters, while the latter returns the bytes. LENGTH('?') is 4.

  • Like 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...