我有以下对象$db_items
,我将子对象$db_items->song
作为参数传递给函数。
$db_items = (object) [
"song" => (object) [
"valid" => false,
"errors" => [],
"inserted" => false,
],
"album" => (object) [
"valid" => false,
"errors" => [],
"inserted" => false,
],
// ...
];
function log_status($item, $item_name) {
if ($item->inserted) {
echo tr([
td($item_name),
td("<span class=\"icon-true\">"),
td(),
]);
} else {
echo tr([
td($item_name),
td("<span class=\"icon-false\">"),
td(ul($item->errors)),
]);
}
}
log_status($db_items->song, "Song");
log_status($db_items->album, "Album");
我想摆脱"Song"
中的log_status()
参数。有没有办法在$db_items->song
函数中获取song
- log_status()
的对象名称?$obj_name = get_obj_name($item); // song, album, or w/e. depends on the passed argument
$item_name = capitalize($obj_name); // Song
?类似的东西:
get_class($db_items->song)
我已尝试stdClass
但它返回song
,而不是 let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard))
。
答案 0 :(得分:0)
$db_items
是一个stdclass
对象,而歌曲是该对象的一个属性,它本身就是一个stdclass
对象。您投放到(object)
的任何内容都属于stdclass
类型。所以我看到两个选择:
将$db_items
保留为数组并执行:
$name = key($db_items); // returns "song"
或者使用你拥有的对象:
$name = key(get_object_vars($db_items)); // returns "song"
答案 1 :(得分:0)
如果您不想重复&#34; song&#34;,您可以让该函数将整个对象作为参数,将song
作为单独的参数传递,并让它获得属性值动态。
function log_status($items, $field) {
$item = $items->$field;
$item_name = ucfirst($field);
if ($item->inserted) {
echo tr([
td($item_name),
td("<span class=\"icon-true\">"),
td(),
]);
} else {
echo tr([
td($item_name),
td("<span class=\"icon-false\">"),
td(ul($item->errors)),
]);
}
}
log_status($db_items, "song");
log_status($db_items, "album");
答案 2 :(得分:0)
这是更合适的方法。对名称/类型使用类常量可以更容易地记住它们并避免匹配大小写,拼写等的各种令人讨厌的错误。您甚至可以在设置类型时在类中添加一些验证以确保它是一个是允许的。使用受保护的属性而不是公共保护代码的封装,这意味着您可以提供一个不变的界面,其中函数的内容无关紧要,以编码行。
它更复杂,但这就是我的推动方式.....除此之外,它还为您提供了一个扩展Item
功能的地方,使其保持整齐有序。
你可以更进一步,为顶级对象添加一个类,并为歌曲,专辑添加子类...设置几个接口,然后你就像工厂模式,如我在评论中提到过。
https://en.wikipedia.org/wiki/Factory_method_pattern
只取决于您需要设置的时间和维护方式。
$db_items = (object) [
"song" => new Item( Item::SONG, false, false ),
"album" => new Item( Item::ALBUM, false, false )
// ...
];
function log_status($item ) {
if ($item->getInserted()) {
echo tr([
td($item->getType()),
td("<span class=\"icon-true\">"),
td(),
]);
} else {
echo tr([
td($$item->getType()),
td("<span class=\"icon-false\">"),
td(ul($item->getErrors())),
]);
}
}
class Item{
protected $_valid;
protected $_errors;
protected $_inserted;
protected $_type;
const SONG = 'song'
const ALBUM = 'album'
public function __construct( $type, $valid, $inserted, $errors = array()){
$this->setType( $type );
$this->setValid( $valid );
$this->setInserted( $inserted );
$this->setErrors( $errors );
}
public function setValid( $valid ){
$this->_valid = $valid;
}
public function getValid(){
return $this->_valid;
}
public function setType( $type ){
....... etc continue on with simpler getter / setters
}
答案 3 :(得分:-1)
See the PHP Variable Scope,试试这个例子:
<?php
$db_items = (object) [
"song" => (object) [
"valid" => false,
"errors" => [],
"inserted" => false,
],
];
function log_status() {
global $db_items;
print_r($db_items->song);
}
log_status();
编辑:
$db_items = (object) [
"song" => (object) [
"valid" => false,
"errors" => [],
"inserted" => false,
],
"album" => (object) [
"valid" => false,
"errors" => [],
"inserted" => false,
]
];
function log_status($db_items, $item) {
echo $item."<br>";
print_r($db_items->$item);
}
foreach ($db_items as $key => $item) {
log_status($db_items, $key);
}