编码php时,尽量避免使用尽可能多的警告。关于数组,有一个问题让我困扰了很长一段时间。
在处理数组及其值时,我经常在进入“实际工作”之前检查空值。
if(array_key_exists('bla', $array){
if( !empty($array['bla']) {
# do something
}
}
我的问题是:
这是很多代码,只是检查我是否有值可以使用。是否有一些更短的方法来检查数组中可能存在或不存在的值?
答案 0 :(得分:5)
请不要使用empty
,除非您确定这是您想要的:
如果
FALSE
存在并且具有非空的非零值,则返回var
。否则返回TRUE
。以下内容被认为是空的:
""
(空字符串)0
(0为整数)0.0
(0作为浮动)"0"
(0为字符串)NULL
FALSE
array()
(空数组)$var;
(声明的变量,但没有值)
本手册没有明确列出“if var
不存在”案例,但这里有几个:
$array['undeclaredKey']
(现有数组,但未声明密钥)$undeclaredVar;
(未声明的变量) 通常array_key_exists
检查就足够了。
答案 1 :(得分:3)
你可以简单地做
if (!empty($array['bla']) {
# do something
}
我一直在drupal中使用它,并且是检查是否可用并避免任何类型警告的好方法。
答案 2 :(得分:2)
只是做:
if (!empty($array['bla'])) {
如果密钥不存在,则不会发出警告。
答案 3 :(得分:1)
不确定为什么还没有人提到,但你可以这样做:
// Before
if(array_key_exists('bla', $array){
if( !empty($array['bla']) {
// After (if element of array is scalar)
// Avoids warning and allows for values such as 0
if ((true === isset($array['bla'])) && (mb_strlen($array['bla']) > 0)) {
// After (if element of array is another array
// Avoids warning and ensures element is populated
if ((true === isset($array['bla'])) && (count($array['bla']) > 0)) {
如果你真的想要更好地检查vars,你可以创建一个标准化的API,下面是我创建的一些方法,以避免变量检查的清单函数调用:
class MyString
{
public static function populated($string)
{
//-----
// Handle various datatypes
//-----
// Don't want to assume an array as a string, even if we serialize then check
if (is_array($string)) {
return false;
}
if (is_object($string)) {
if (!is_callable(array($string, '__toString'))) {
return false;
}
$string = (string) $string;
}
//-----
return (mb_strlen($string) > 0) ? true : false;
}
}
class MyArray
{
public static function populatedKey($key, $array, $specificValue = null, $strict = true)
{
if ((is_array($array)) &&
(array_key_exists($key, $array))) {
if (is_array($array[$key])) {
return (count($array[$key]) > 0) ? true : false;
}
elseif (is_object($array[$key])) {
return true;
}
elseif (mb_strlen($array[$key]) > 0) {
if (!is_null($specificValue)) {
if ($strict === true) {
return ($array[$key] === $specificValue) ? true : false;
} else {
return ($array[$key] == $specificValue) ? true : false;
}
}
return true;
}
}
return false;
}
}
// Now you can simplify calls
if (true === MyArray::populatedKey('bla', $array)) { // Do stuff }
if (true === MyString::populated($someString)) { // Do stuff }
有一种方法可以对猫进行换肤,但是标准化这样的调用会增加快速应用程序开发(RAD),保持调用代码干净,并有助于自我文档(语义逻辑)。
答案 4 :(得分:1)
如果要检查非空值,则可以使用/// <summary>
/// This class contains extensions methods for the <see cref="MessageSender"/> class.
/// </summary>
public static class MessageSenderExtensions
{
private const string BrokeredMessageListCannotBeNullOrEmpty = "The brokeredMessageEnumerable parameter cannot be null or empty.";
private const string SendPartitionedBatchFormat = "[MessageSender.SendPartitionedBatch] Batch Sent: BatchSizeInBytes=[{0}] MessageCount=[{1}]";
private const string SendPartitionedBatchAsyncFormat = "[MessageSender.SendPartitionedBatchAsync] Batch Sent: BatchSizeInBytes=[{0}] MessageCount=[{1}]";
private const int MaxBathSizeInBytes = 262144;
/// <summary>
/// Sends a set of brokered messages (for batch processing).
/// If the batch size is greater than the maximum batch size,
/// the method partitions the original batch into multiple batches,
/// each smaller in size than the maximum batch size.
/// </summary>
/// <param name="messageSender">The current <see cref="MessageSender"/> object.</param>
/// <param name="messages">The collection of brokered messages to send.</param>
/// <param name="trace">true to cause a message to be written; otherwise, false.</param>
/// <returns>The asynchronous operation.</returns>
public async static Task SendPartitionedBatchAsync(this MessageSender messageSender, IEnumerable<BrokeredMessage> messages, bool trace = false)
{
var brokeredMessageList = messages as IList<BrokeredMessage> ?? messages.ToList();
if (messages == null || !brokeredMessageList.Any())
{
throw new ArgumentNullException(BrokeredMessageListCannotBeNullOrEmpty);
}
var batchList = new List<BrokeredMessage>();
long batchSize = 0;
foreach (var brokeredMessage in brokeredMessageList)
{
// Hack because the size of the brokered message does not take into account the size of the properties
var messageSize = GetObjectSize(brokeredMessage.Properties) + brokeredMessage.Size;
if ((batchSize + messageSize) > MaxBathSizeInBytes)
{
// Send current batch
await messageSender.SendBatchAsync(batchList);
Trace.WriteLineIf(trace, string.Format(SendPartitionedBatchAsyncFormat, batchSize, batchList.Count));
// Initialize a new batch
batchList = new List<BrokeredMessage> { brokeredMessage };
batchSize = messageSize;
}
else
{
// Add the BrokeredMessage to the current batch
batchList.Add(brokeredMessage);
batchSize += messageSize;
}
}
// The final batch is sent outside of the loop
await messageSender.SendBatchAsync(batchList);
Trace.WriteLineIf(trace, string.Format(SendPartitionedBatchAsyncFormat, batchSize, batchList.Count));
}
/// <summary>
/// Calculates the lenght in bytes of an object and returns the size.
/// </summary>
private static int GetObjectSize(object objectToTest)
{
var bf = new BinaryFormatter();
using (var ms = new MemoryStream())
{
bf.Serialize(ms, objectToTest);
return ms.ToArray().Length;
}
}
}
。
您还可以使用!empty($array['bla'])
,在以下情况下返回isset($array['bla'])
:1)未定义密钥或2)如果为密钥存储的值为false
。检查数组是否包含键(即使其值为null)的唯一简单方法是使用null
。
即使密钥存在,array_key_exists()
的呼叫也是安全的(行为类似于empty()
),因此您无需通过isset()
保护密码。
我很惊讶没有提到这一点,但是获取密钥值而不产生警告/错误的最短方法是使用Error Control Operator:
array_key_exists()
这允许您获取任何键的值,如果该键不存在,则返回值的可能性为// safely fetch from array, will return NULL when key doesn't exist
$value = @$array['bla'];
。