Asked  7 Months ago    Answers:  5   Viewed   38 times

This failed:

 define('DEFAULT_ROLES', array('guy', 'development team'));

Apparently, constants can't hold arrays. What is the best way to get around this?

define('DEFAULT_ROLES', 'guy|development team');

//...

$default = explode('|', DEFAULT_ROLES);

This seems like unnecessary effort.

 Answers

60

NOTE: while this is the accepted answer, it's worth noting that in PHP 5.6+ you can have const arrays - see Andrea Faulds' answer below.

You can also serialize your array and then put it into the constant:

# define constant, serialize array
define ("FRUITS", serialize (array ("apple", "cherry", "banana")));

# use it
$my_fruits = unserialize (FRUITS);
Wednesday, March 31, 2021
 
keisar
answered 7 Months ago
69

UPDATE:

This is now available in PHP 5.6 https://php.net/manual/en/migration56.new-features.php


No you can't assign an Array to PHP constant.

In http://www.php.net/manual/en/language.constants.syntax.php

Constants may only evaluate to scalar values

This is the reason.

Scalar values for examples are int, float, string

Wednesday, March 31, 2021
 
BrunoRamalho
answered 7 Months ago
13

I think this is in the realm of being a micro-optimization. That is, the difference is small enough that it isn't worth using one solution over the other for the sake of performance. If performance were that critical to your app, you wouldn't be using PHP! :-)

Use whatever is more convenient or that makes more sense. I put config data into constants if only because they shouldn't be allowed to change after the config file is loaded, and that's what constants are for.

Wednesday, March 31, 2021
 
jeremyharris
answered 7 Months ago
86

Clearify the question: What is the advantage of a configuration container over globally define()ed configuration contstants?

The advantages are all the advantages that OOP offers: Data Abstraction and Encapsulation, Inheritance, Polymorphism and better design pattern integration.

The readers of this thread seem a little confused and focus on your class rather than the main question. To also clearify this, let me give you an example:

class Configuration
{
    protected $someValue;
}

class ConfigurationDev extends Configuration
{
    protected $baseUrl = 'http://devel.yoursite.com/';
}

class ConfigurationLive extends Configuration
{
    protected $baseUrl = 'http://www.yoursite.com/';
}

index.php:

<?php
$config   = new ConfigurationDev;
$tracking = new Tracking($config);
...

class Tracking:

class Tracking
{
    public function __construct(Configuration $config) {
        if ($config instanceof ConfigurationLive) {
            // We are in live environment, do track
        } else {
            // Debug Notice: We are NOT in live environment, do NOT track
        }
    }
}

Explanation of the scenario:

Imagine you want to track users, but only on the live system, not on your development system. The Tracking class expects a live configuration but aborts (without impact) if its not the live config.

Your class with const is not the best, because const implies you do not want to change the variables. Do not use the variable for values that may change. You shouldn't use static stuff either because it mostly conflicts with dependency injection. Pass real objects!

Your function public static function getValueDependingOnURL() should be placed in a Helper class, not in a Constant/Configuration container either.

class Helper
{
    protected $config;

    public function __construct(Configuration $config) {
        $this->config = $config;
        return $this;
    }

    public function getValueByUrl($url) {
        if ($url == 'something') {
            return $config->getMinValue();
        } else {
            return $config->getMaxValue();
        }
    }
}

Now you can have different sets of configuration which the helper class relies on:

$config = new ConfigurationLive;
$helper = new Helper($config);
$value  = $helper->getValueByUrl($_SERVER['REQUEST_URI']);

There is a lot of best practice design pattern stuff, code style and OOP in my examples, learn about those and you will gain a much higher level of software engineering than the readers of your question. Good luck!

Saturday, May 29, 2021
 
macha
answered 5 Months ago
18

The cleanest way to do this would be to extend phpunit with a new assertion method. But here's an idea for a simpler way for now. Untested code, please verify:

Somewhere in your app:

 /**
 * Determine if two associative arrays are similar
 *
 * Both arrays must have the same indexes with identical values
 * without respect to key ordering 
 * 
 * @param array $a
 * @param array $b
 * @return bool
 */
function arrays_are_similar($a, $b) {
  // if the indexes don't match, return immediately
  if (count(array_diff_assoc($a, $b))) {
    return false;
  }
  // we know that the indexes, but maybe not values, match.
  // compare the values between the two arrays
  foreach($a as $k => $v) {
    if ($v !== $b[$k]) {
      return false;
    }
  }
  // we have identical indexes, and no unequal values
  return true;
}

In your test:

$this->assertTrue(arrays_are_similar($foo, $bar));
Tuesday, July 27, 2021
 
apokryfos
answered 3 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :