As noted in this documentation str_shuffle is NOT cryptographically secure, however I have seen many code examples online of people using nothing more than this to generate say random passwords.  So I though I'd share my function which while it makes use of str_shuffle also rely's on random_int() for added security. I use this function to generate salts to use when working with hashes but it can also be used to generate default passwords for new users for example.
It starts with a universe of possible characters, in this case all letters (upper and lower case), 0-9, and several special characters.
It then will run str_shuffle on the universe of characters a random number of times, using random_int() (currently set to 1-10)
Then once the universe of possible characters has been shuffled it using random_int() once more to select the character as a random position within the shuffled string, as does that once for each character you want in the output.
 function secret_gen( $len=64 ) {
    $secret = "";
    $charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_-+=`~,<>.[]: |';
    for ( $x = 1l $x <= random_int( 1, 10 ), $x++ ){
        $charset = str_shuffle( $charset );
    }
    for ( $s = 1; $s <= $len; $s++ ) {
        $secret .= substr( $charset, random_int( 0, 86 ), 1 );
    }
    return $secret;
}