modifiedcontent

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

Recommended Posts

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
abdus    622

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

 

  • Like 2

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
abdus    622

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.

 

 

  • Like 2

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
abdus    622
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?

  • Like 1

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
abdus    622

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
Zeka    282

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

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

 

  • Like 2

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;

}

 

  • Like 1

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 sirhc
      Hi all,
      Im trying to install this core module and got the error of not having the ImageMagick library installed.
      But if im checking for the version of my ImageMagick installed on my server via SSH im getting this response;
      identify -version
      Version: ImageMagick 6.9.4-9 Q16 i386 2016-06-21 http://www.imagemagick.org
      Copyright: Copyright (C) 1999-2016 ImageMagick Studio LLC
      License: http://www.imagemagick.org/script/license.php
      Features: Cipher DPC 
      Delegates (built-in): bzlib freetype gslib jng jpeg png ps tiff xml zlib
      Does this even mean the library is installed? And if yes, why cant i install my module?
      Pleaassee help me
      Greetz.
    • By rocket
      Noob to Processwire. Trying to convert some older sites to Pwire. I am having trouble including a legacy form class into my templates:
      If I embed the php directly in the template, it works. But if I use include statements, the form object returns null.
      This works:
          use formbuild\Form;
          session_start();
          $form = new Form(init1, 'init2', ...');
          $form->param1 = ...;
          $form->param2 = ...;
          $form->param3 = ...;
       
          $form->render();
      -----------------------------------------------------------------------------------------
      This fails:
          include_once ($config->paths->templates."forms/form1.php");
          $form->render();
      ____________________________________________________________________
      My referencing is OK, no error message. The only code that cannot reside in the include file are the following lines:
          use formbuild\Form;
          $form = new Form(init1, 'init2', ...');
      My PhP is rusty, maybe that is the problem, but it could be something about Pwire, namespace maybe. I have tested it outside Pwire and no problems.
      Please advise. Thanks.
       
       
    • By louisstephens
      I believe I have hit a roadblock on this one. I am trying to pass an array to a "cc" in wiremail (using wiremailsmpt to extend). Everything else is working, but I am getting an "invalid email address" for $cc_recipient[0]. I looked in wiremail, and it is checking to see if it is a valid email address before sending (which my variable is not). Is there a way around this by chance?
    • By louisstephens
      I have a foreach loop on a dashboard page where I sorting the pages titles to different columns based on a date field. Unfortunately, I am doing it with multiple different if statements for the sorting (with multiple foreach loops), as I needed something quickly for testing. I thought it would be nice to implement wireSMTP to send an email out to alert the users that created the pages, which I got working in no time. However, now I have hit a roadblock. The dashboard page has a javascript function that refreshes the page every few hours to get the changes in the date, which then triggers the $mail to fire the email out. 
      I guess my question is there a way to limit the emails to be sent out only once the date/time has changed once instead of it firing every time the page refreshes?
    • By louisstephens
      I was working on a simple "to-do" style template that has a form on a page. Once the form is submitted, I use the API to  create a new subpage under a pre-existing page, but I notice that it does resubmit the form data (as to be expected) if a user were to refresh the page. Is there a way to prevent this behavior so duplicate content will not be posted by using something like exit(), or is this not proper due to usability?  I guess I am curious as to how other developers handle the same hurdle.