php - 如何从 PHP 中的多维数组输出 CSV 文件中缺失属性的空格
问题描述
我在输出空格并确保我所有的 CSV 数据都输出到正确的位置时遇到了一点问题,我想知道我该怎么做。
我正在尝试将我的 LDAP 服务器搜索的输出格式化为 CSV 格式,但问题是某些条目的属性无序,或者某些条目完全缺少属性。
这是一些数据的示例
Array
(
[0] => Array
(
[dc=example,dc=com] => Array
(
[o] => example.com
[objectclass] => Array
(
[0] => simpleSecurityObject
[1] => dcObject
[2] => organization
)
[dc] => example
)
)
[1] => Array
(
[uid=newton,dc=example,dc=com] => Array
(
[sn] => Newton
[objectclass] => Array
(
[0] => simpleSecurityObject
[1] => dcObject
[2] => organization
)
[uid] => Newton
[mail] => newton@ldap.forumsys.com
[cn] => Isaac Newton
)
)
)
请注意,在第一个 ([0]) 数组中,我有一个名为“o”和“dc”的条目,而在第二个中,我没有它们。
所以本质上,我想输出这个:
distinguishedname,o,objectclass,dc,sn,uid,mail,cn
dc=example,dc=com,example.com,{simpleSecurityObject,dcObject,organization},example, , , ,
uid=newton,dc=example,dc=com, ,{simpleSecurityObject,dcObject,organization}, , ,Newton,newton@ldap.forumsys.com,Isaac Newton
我不太确定如何做两件事:
- 确保所有缺少的属性都替换为“”,使其显示为空
- 确保将正确的属性放在正确的位置。例如,“o”可能是一个条目中的第三个属性,但它可能是另一个条目中的第六个属性。如何确保我的 CSV 数据按以下顺序排列:
distinguishedname,o,objectclass,dc,sn,uid,mail,cn
这是一些以 CSV 格式输出所有数据的代码,但我不确定如何制作空字段并使它们对齐.. 输出只是所有数据的打印。
<?php
$movies = array(
"dc=example,dc=com" => array(
"o" => "example.com",
"objectclass" => array("simpleSecurityObject", "dcObject", "organization"),
"dc" => "example"),
"uid=newton,dc=example,dc=com" => array(
"sn" => "Newton",
"objectclass" => array("simpleSecurityObject", "dcObject", "organization"),
"uid" => "Newton",
"mail" => "newton@ldap.forumsys.com",
"cn" => "Isaac Newton")
);
function echo1($n){
echo "<pre>";
echo $n;
echo "</pre>";
}
$i=0;
$hi1 = "";
$attributes_list = array("dn", "objectclass", "cn", "userpassword", "description", "sn", "uid", "mail");
echo "<pre></pre>";
$comma_separated = implode(",", $attributes_list);
echo $comma_separated;
foreach ( $movies as $movie => $val ) {
//echo "<pre></pre> \n Entry #$i";
//This prints the name of all the arrays.
//echo1($movie);
echo "<pre></pre>";
echo $movie.",";
$i = $i + 1;
//Checks if the value of the key value pair is an array.
if(is_array($val)){
//Since it's an array, we access its key value pairs again
foreach ( $val as $key => $value ) {
//Check to see if value of key value pair is array
if(is_array($value)){
//Prints the name of all the arrays
echo $key." ";
//Prints all key value pairs of the array
$value_array = implode(",", $value);
print_r($value_array);
//If $value isn't an array, just prints the key value pairs
} else{
/*This is the original code for easier readability
$hi = "$key : $value";
echo1($hi);*/
$hi1 = $hi1.$value.",";
echo $hi1;
}
}
//If $val isn't an array, prints the key value pairs
} else{
foreach ( $val as $key => $value ) {
$hi = "The key is: $key The value is:$value";
echo1($hi);
}
}
echo '</dl>';
}
?>
这是输出:
dn,objectclass,cn,userpassword,description,sn,uid,mail
dc=example,dc=com,example.com,objectclass simpleSecurityObject,dcObject,organizationexample.com,example,
uid=newton,dc=example,dc=com,example.com,example,Newton,objectclass simpleSecurityObject,dcObject,organizationexample.com,example,Newton,Newton,example.com,example,Newton,Newton,newton@ldap.forumsys.com,example.com,example,Newton,Newton,newton@ldap.forumsys.com,Isaac Newton,
编辑:
使用 Nigel Ren 的代码,我得到了这个输出。
distinguishedname,o,objectclass,dc,sn,uid,mail,cn
o,{}
objectclass,,{},,,,,,simpleSecurityObject,dcObject,organization
dc,{}
sn,{}
objectclass,,{},,,,,,simpleSecurityObject,dcObject,organization
uid,{}
mail,{}
cn,{}
这是我尝试过的确切代码:
<?php
// Start with the column list and split into an array
$headers = explode(',', 'distinguishedname,o,objectclass,dc,sn,uid,mail,cn');
// Create template record with the fields you want to end up with
$header = array_fill_keys($headers, null);
$output = [];
$details = array(
"dc=example,dc=com" => array(
"o" => "example.com",
"objectclass" => array("simpleSecurityObject", "dcObject", "organization"),
"dc" => "example"),
"uid=newton,dc=example,dc=com" => array(
"sn" => "Newton",
"objectclass" => array("simpleSecurityObject", "dcObject", "organization"),
"uid" => "Newton",
"mail" => "newton@ldap.forumsys.com",
"cn" => "Isaac Newton")
);
foreach ( $details as $detail ) {
foreach ( $detail as $name => $entry ) {
// Set the values in the template header from the current entry
$newEntry = array_merge( $header, $entry );
// Add the name in
$newEntry ['distinguishedname'] = $name;
// Process the object class from an array to a string
$newEntry ['objectclass'] = "{".implode(",", $newEntry ['objectclass'])."}";
$output [] = $newEntry;
}
}
// Write file out
$fh = fopen("ad.csv", "w");
fputcsv($fh, $headers);
foreach ( $output as $row ) {
fputcsv($fh, $row);
}
fclose($fh);
?>
编辑 2020 年 7 月 1 日:
这是我得到的输出
firstname,lastname,email,phone,uid
,,,,,"{top,dcObject,organization}",ec_testing,test123,"{organizationalPerson,person,top,user}"
,,,,,"{simpleSecurityObject,organizationalRole}",admin,"LDAP administrator",{SSHA}0NhB8bVqiqCfUjU7AGE2mtrfj3Q58mj5
,,,,,organizationalUnit,people
,,,,,organizationalUnit,"groups "
,,,,tnguyen,"{top,account,posixAccount,shadowAccount}",tnguyen,16859,100,/home/tnguyen,/bin/bash,tnguyen,{crypt}x,0,0,0
,,,,,"{top,organizationalRole,simpleSecurityObject}","{replica,test}",aDifferentSecret,"Bind object used for replication using slurpd"
,,,,,"{php testing,phptest}",person,TestEdit
,,,,,person,"This is just a test to add an entry in Java",javatest,replacetest
,,,,,gotest,person,Google,"this is to test if replacing works in GoLang"
这是我使用的代码:
foreach ( $details as $name => $entry ) {
// Set the values in the template header from the current entry
$newEntry = array_merge( $header, $entry );
// Add the name in
foreach ( $newEntry as &$entry ) {
if ( is_array($entry)) {
$entry = "{".implode(",", $entry)."}";
}
}
unset($entry);
//$newEntry ['distinguishedname'] = $name;
$output [] = $newEntry;
}
我希望输出像
firstname,lastname,email,phone,uid
,,,,
,,,,
,,,,
,,,,
,,,,tnguyen
,,,,
,,,,
,,,,
,,,,
这是一个不好的例子,因为如果不是所有属性,所有条目都缺少大部分,但你明白了。
我试过的是这样的:
foreach ( $details as $name => $entry ) {
// Set the values in the template header from the current entry
if(in_array($entry, $header) || in_array($name, $header)){
$newEntry = array_merge( $header, $entry );
}
// Add the name in
foreach ( $newEntry as &$entry ) {
if ( is_array($entry) && in_array($newEntry, $header)) {
$entry = "{".implode(",", $entry)."}";
}
}
unset($entry);
//$newEntry ['distinguishedname'] = $name;
$output [] = $newEntry;
}
但它只是输出我的标题,而不仅仅是空条目。
firstname,lastname,email,phone,uid
解决方案
以下代码创建一个模板数组,以便每条记录包含所有值,然后用于将每条记录中的值array_merge()
复制到模板中。任何不在记录中的值都将保持为空,以确保保持对齐(代码注释中的更多描述)......
// Start with the column list and split into an array
$headers = explode(',', 'distinguishedname,o,objectclass,dc,sn,uid,mail,cn');
// Create template record with the fields you want to end up with
$header = array_fill_keys($headers, null);
$output = [];
foreach ( $details as $detail ) {
foreach ( $detail as $name => $entry ) {
// Set the values in the template header from the current entry
$newEntry = array_merge( $header, $entry );
// Add the name in
$newEntry ['distinguishedname'] = $name;
// Process the object class from an array to a string
$newEntry ['objectclass'] = "{".implode(",", $newEntry ['objectclass'])."}";
$output [] = $newEntry;
}
}
// Write file out
$fh = fopen("ad.csv", "w");
fputcsv($fh, $headers);
foreach ( $output as $row ) {
fputcsv($fh, $row);
}
fclose($fh);
这与样本数据给出了......
distinguishedname,o,objectclass,dc,sn,uid,mail,cn
"dc=example,dc=com",example.com,"{simpleSecurityObject,dcObject,organization}",example,,,,
"uid=newton,dc=example,dc=com",,"{simpleSecurityObject,dcObject,organization}",,Newton,Newton,newton@ldap.forumsys.com,"Isaac Newton"
请注意, usingfpustcsv()
的优点是如果字段包含逗号(分隔符),那么它将把它们放在引号中以确保它们只是一个字段。
编辑:
$headers = explode(',', 'distinguishedname,o,objectclass,dc,sn,uid,mail,cn');
$output = [];
foreach ( $details as $name => $entry ) {
echo $name.PHP_EOL;
$newEntry = [];
foreach ( $headers as $header ) {
$value = $entry[$header] ?? null;
if ( is_array($value) ) {
$value = "{".implode(",", $value)."}";
}
$newEntry [$header] = $value;
}
$newEntry ['distinguishedname'] = $name;
$output [] = $newEntry;
}
推荐阅读
- css - CSS:谷歌搜索框的选择器
- json - 我如何将 json 对象与 python 变量进行比较
- api - 如何处理来自 API 请求的错误 Flutter
- amazon-cognito - 需要 AWS Cognito SAML 签名
- r - 使用解析文本 R 重命名数据框
- sql - 如何在 Postgres SQL 中查找连续的日期
- swift - UIGraphicsImageRenderer 没有在循环中返回图像
- javascript - 在 Google App Script 中根据条件禁用按钮
- jpa - 使用 JPA + MySQL 进行货币操作的正确方法是什么?
- javascript - 无法使用我的数组项使用 JQuery 预填充我的表单输入