modifiedcontent

How to find usernames by userid array, return as key value array

10 posts in this topic

I am trying to integrate another script, Questions2Answer, with Processwire user management. The script needs an array with key/value pairs for user->name => user->id 

The script provides an array $userids with active user->ids that looks like this var_dumped for a page with two users:

array(2) {
  [0]=>
  int(1107)
  [1]=>
  int(41)
}

How can I take $userids, find the corresponding $user->names in Processwire as values and then return that to Q2A as a clean key/value array?

This is probably basic PHP, but I have tried so many variations that I now completely lost the plot. Any pointers appreciated.

 

Share this post


Link to post
Share on other sites

This is untested, but you can use something along the lines of this

<?php
$userIds = [1, 2, 3]; // list of ids

// build a selector like id=1|2|3|4
$userList = users()->find("id=" . join('|', $userIds));

$names = $userList->getProperty('name');
$ids = $userList->getProperty('id');

// create an array of [username => userid]
$namesToIds = array_combine($names, $ids);

// or use array reduce
// you need basic PHP arrays, which you can get with WireArray::getArray() method
$namesToIds = array_reduce($userList->getArray(), function ($carry, $user) {
    // perform some other checks
    // ...

    $carry[$user->name] = $user->id; // fill array with name => id pairs
    return $carry;
}, []); // start with an empty array

 

2 people like this

Share this post


Link to post
Share on other sites

Thank you abdus !

I had come across array_combine, but had no idea how to use it. I have now tried something like this:

function qa_get_public_from_userids($userids) {

global $users;
	
// build a selector like id=1|2|3|4
$userlist = $users->find('id=' . join('|', $userids));

$names = $userlist->getProperty('fullname');

// create an array of [username => userid]
$useridtopublic = array_combine($userids, $names);

return $useridtopublic;
}

That still doesn't work; $userlist is not an array, but a "piped string" (?) of user ids. Same as $userids, but another format.

Can $users->find be used with multiple selectors? Or did you really mean to use 'users()->find'? users()->find produced server errors for me.

The $names line should probably be a foreach loop?

How do you get a key/value array out of a foreach loop? That is one of my main questions that I keep running into.

Will try again tomorrow...

Share this post


Link to post
Share on other sites

When building selectors, you can combine multiple values by OR (pipe | character). This is a way to say "find me users with id 1 or 2 or 3 ...", and PW should return every user whose id is in that list.

Since "id=1|2|3" itself is a selector, yes, you can combine it with other terms as well.

array_combine takes in two parameters, first one is for keys, second is values, and creates a new array from those keys and values. So I used it with usernames as keys and ids as values to get [username => userid] type of array. But you can achieve the same result with plain foreach loop as well.

Using your sample code you'd use

<?php
function qa_get_public_from_userids($userids) {
	// userids is an array of integer ids [13, 456, 74] etc
    
    // global $users;
    // you can use wire() function instead of globals to access PW variables inside functions
    $userlist = wire()->users->find('id=' . join('|', $userids));


    // usernames are stored in 'name' property
    // Unless you need [fullname => id] array, you should use 'name'

    // create an array of [username => userid]
    $nameWithId = [];

    foreach ($userlist as $u) {
        $nameWithId[$u->name] = $u->id;
    }

    return $nameWithId;
}

Also the reason you're getting errors from users() function is they're a part of Functions API, which is disabled under a switch.

 

 

2 people like this

Share this post


Link to post
Share on other sites

I keep getting 'PHP Fatal error:  Call to undefined function wire() ...', with or without '$config->useFunctionsAPI = true;' in the config.php

This version had no error, but returns an empty (0/null) array:

Spoiler

function qa_get_public_from_userids($userids) {

global $users;

// build a selector like id=1|2|3|4
$userlist = $users->find('id=' . join('|', $userids));

$useridtopublic = [];

foreach ($userlist as $u) {
        $u->id = $useridtopublic[$u->fullname];
    }

return $useridtopublic;
}

 

I have been trying variations of this for the last two days, going in circles.

I have a custom field 'fullname', so ignore that, could be 'name' instead.

Will try again later...

I'd like to try array_combine or something like that. I'd need two valid arrays. var_dump($userids) returns a healthy looking array. Getting that second array of fullnames is my problem. Or would it work if I can get wire() to work?

$userlist is not an array, so that foreach can never work?

Share this post


Link to post
Share on other sites
10 minutes ago, modifiedcontent said:

Call to undefined function wire()

Do you have namespace

<?php namespace ProcessWire;

declared on top of your files?

 

What shows up when you var_dump($userlist) inside the function?

1 person likes this

Share this post


Link to post
Share on other sites

$userlist is not an array - at least my version via $users-> and global. var_dump($userlist) produces a server error. echo $userlist displays a piped string of ids.

I can't get wire() to work in the external script.

In which file should I add 'namespace ProcessWire'? The function is in another script that bootstraps PW by including the index. Shouldn't that be enough?

The var_dump(wire()->users->find('id>0')) results do not look like anything my script could use. Is there no simple way to convert a piped string into an array?

Share this post


Link to post
Share on other sites

You should see the details of the error when you're logged in. For instance when I

<?php
var_dump(wire()->users->find('id>0')); // lists all users

I get an output like this


object(ProcessWire\PageArray)#330 (7) {
  ["hooks"]=>
  array(2) {
    ["PageArray::render"]=>
    string(60) "MarkupPageArray->renderPageArray() in MarkupPageArray.module"
    ["PageArray::renderPager"]=>
    string(56) "MarkupPageArray->renderPager() in MarkupPageArray.module"
  }
  ["count"]=>
  int(2)
  ["items"]=>
  array(2) {
    [0]=>
    string(23) "/pw/access/users/admin/"
    [1]=>
    string(23) "/pw/access/users/guest/"
  }
  ["total"]=>
  int(2)
  ["start"]=>
  int(0)
  ["limit"]=>
  int(0)
  ["selectors"]=>
  string(45) "id>0, sort=sort, parent_id=29, templates_id=3"
}

 

Share this post


Link to post
Share on other sites

Also, there is more API-styled way to get flat array of id => name 

$pages->find('id=' . join('|', $userids))->explode("name", ["key" => "id"]);

 

2 people like this

Share this post


Link to post
Share on other sites

Thanks Zeka! This works:

function qa_get_public_from_userids($userids) {

global $users;

$useridtopublic = $users->find('id=' . join('|', $userids))->explode('fullname', ["key" => "id"]);
	
return $useridtopublic;

}

 

1 person likes this

Share this post


Link to post
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

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By franciccio-ITALIANO
      Hi, I know the the templates in processwire are html files.
      I search it into foleder "site" of standard installation of processwire standard theme (blanck and that blue) but I don't find any html file to modify it by html code.
      So, I must modify it only by php code?
      Can I traduct php pages templates in html page?
    • By thmsnhl
      Hi everyone,
      I've recently hired at a new company and here I am evaluating the abilities of ProcessWire for our projects.
      I was able to meet almost every requirement so far, but there is one point I couldn't find an adequate solution for: outputting data to json.
      I am aware of modules like https://modules.processwire.com/modules/pages2-json/ (which does not seem to work for me) but I thought with a function like wireEncodeJSON this should be much cleaner. What I would like to achieve is outputting pages with according field values into an array to use this within javascript.
      My first attempt on this was:
      $jsontestOne = $pages->find(1001)->children(); echo wireEncodeJSON($jsontestOne); which outputs 
      [{}] and afterwards I tried that one:
      $jsontest = $pages->find("template=basic-page")->getArray(); echo wireEncodeJSON($jsontest); which outputs 
      [{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},...] Maybe you can point out where my mistake is.
       
      Thanks in advance!
    • By ridgedale
      Hi,
      I need to separate the header, footer and sidebar from the _main.php file.
      I've tried all of the following without success:
      <?php include ("header.php"); ?> <?php include ("/_header.php"); ?> <?php include ("./header.inc"); ?> <?php $header = pages()->get('/rcl-header.php'); // include header echo $header; ?> Any guidance would be appreciated.
    • By louisstephens
      I have been scratching my head on this one for a while, so I thought maybe someone could shed some light on this issue. I am using a grid layout (that I have created over the years) with a class for responsive images (very similar to bootstrap, but very stripped down). Using this, I created a gallery using a foreach loop, and included a "print button" to print each image. I got the classes and everything worked out, but I ran into a small problem with the print functionality. My images (which are around 2400px wide to fill the space) are just fine in the grid and on resize, but when I print, they "run off" the page. I understand that they are just too big to be printed in portrait mode, which led to me think that I could use $image->size(); to print a scaled down version of the image (which adds a bit more load time as now the site needs to load the image large scale and the scaled down version). However, I can't seem to wrap my head around serving just the scaled down version for print only (obviously display:none; doesn't do the trick). Has anyone tackled this before, or does anyone know of a more elegant solution to the conundrum that I have found myself in?
      The Foreachloop:
      $printclass = 1; foreach($page->galleries as $gallery) { $printclass++; $printimage = $gallery->gallery_image->width(600)->url; $out = ""; $out .= "<div class=\"row\">"; $out .= "<div class=\"grid-12\">"; $out .= "<img src=\"{$gallery->gallery_image->url}\" class=\"reimage\"/>"; $out .= "</div>"; $out .= "</div>"; $out .= "<div class=\"row\">"; $out .= "<div class=\"grid-12\">"; $out .= "<a href=\"#\" onClick=\"printCoupon('printable{$printclass}');\">Print</a>"; $out .= "</div> "; $out .= "</div> "; $out .="<div id=\"printable{$printclass}\"><img src=\"{$printimage}\"/></div>"; echo $out; }  
       
    • By timothy.m.wilson
      Good afternoon,
      I am attempting to loop through approximately 600 XML nodes. Each of those nodes has 2 child nodes (example below). One is an id for an existing page and the other contains values for a page reference field. I have put together a loop (below as well) to attempt to save each page with the label values. This all works....once. After getting the first XML node "label" saved to the correct page, nothing else is saved. I'm sure there is probably something that I have overlooked. But, I am also very new to this CMS. I'm hoping there is a veteran user who may be able to point me in the right direction. 
       
      <row>
          <id>1041</id>
          <labels>lifestyle|savings</labels>
        </row>
       
      foreach ($xml->row as $items) {
              
              //get page id to update and set output formatting to false
              $blog_page = $pages->get('id='.$items->id);
              $blog_page->of(false);
              //create array from pipe separated label values
              $labelsArray = explode('|', $items->labels);
              //loop through array to get page ids by page name
              $labelIDS = array();
              foreach ($labelsArray as $labelValue) {
                  $labelPage = $pages->get('name='.$labelValue);
                  array_push($labelIDS, $labelPage->id);
                  
              }
              //add labels to label field in post
              $blog_page->labels = $labelIDS;
              
              //save page
              $blog_page->save();
          
      }