Dier_Sergio_Great
@Dier_Sergio_Great
Увлеченный человек

Как в PHP в классе свойствам назначать значения по умолчанию объекты.?

class Curs{
public static $currencies = [
		['name_cur'=>'Рублей','short_cur'=>'₽','code_cur'=>'RUB','ratio_cur'=>1,'default_cur'=>1,'display_cur'=>1,],
		['name_cur'=>'Dollar','short_cur'=>'$','code_cur'=>'USD','ratio_cur'=>1,'default_cur'=>1,'display_cur'=>1,],
		['name_cur'=>'Euro','short_cur'=>'€','code_cur'=>'EUR','ratio_cur'=>1,'default_cur'=>1,'display_cur'=>1,],
		['name_cur'=>'Pound','short_cur'=>'£','code_cur'=>'GBP','ratio_cur'=>1,'default_cur'=>1,'display_cur'=>1,],
		['name_cur'=>'円','short_cur'=>'¥','code_cur'=>'JPY','ratio_cur'=>1,'default_cur'=>1,'display_cur'=>1,],
		['name_cur'=>'元','short_cur'=>'Ұ','code_cur'=>'CNY','ratio_cur'=>1,'default_cur'=>1,'display_cur'=>1,],
	];
}


Как свойству задать не много мерный массив, а массив объектов, чтобы каждый подмассив был объектом?
public static $currencies = [
		(object)['name_cur'=>'Рублей','short_cur'=>'₽','code_cur'=>'RUB','ratio_cur'=>1,'default_cur'=>1,'display_cur'=>1,],
		(object)['name_cur'=>'Dollar','short_cur'=>'$','code_cur'=>'USD','ratio_cur'=>1,'default_cur'=>1,'display_cur'=>1,],
...........
	];

Можно ли как то указать что там массив объектов? Может использовать "new class" или как то еще ананимное объявление можно использовать?
  • Вопрос задан
  • 321 просмотр
Решения вопроса 3
Всё зависит от того какая цель. Я бы сделал это через обычный enum
Вариант 1 (enum)

<?php

enum CurrenciesEnum: string
{
    case RUB = 'RUB';
    case USD = 'USD';
    case EUR = 'EUR';
    case GBP = 'GBP';
    case JPY = 'JPY';
    case CNY = 'CNY';

    private const DATA = [
        'RUB' => ['name' => 'Рублей', 'short' => '₽', 'ratio' => 1, 'default' => 1, 'display' => 1],
        'USD' => ['name' => 'Dollar', 'short' => '$', 'ratio' => 1, 'default' => 1, 'display' => 1],
        'EUR' => ['name' => 'Euro', 'short' => '€', 'ratio' => 1, 'default' => 1, 'display' => 1],
        'GBP' => ['name' => 'Pound', 'short' => '£', 'ratio' => 1, 'default' => 1, 'display' => 1],
        'JPY' => ['name' => '円', 'short' => '¥', 'ratio' => 1, 'default' => 1, 'display' => 1],
        'CNY' => ['name' => '元', 'short' => 'Ұ', 'ratio' => 1, 'default' => 1, 'display' => 1],
    ];

    public function code(): string
    {
        return $this->value;
    }

    public function name(): string
    {
        $this->insureValue();
        return self::DATA[$this->value]['name'];
    }

    public function short(): string
    {
        $this->insureValue();
        return self::DATA[$this->value]['short'];
    }

    public function ratio(): string
    {
        $this->insureValue();
        return self::DATA[$this->value]['ratio'];
    }

    public function default(): string
    {
        $this->insureValue();
        return self::DATA[$this->value]['default'];
    }

    public function display(): string
    {
        $this->insureValue();
        return self::DATA[$this->value]['display'];
    }

    private function insureValue(): void
    {
        if (!isset(self::DATA[$this->value])) {
            throw new InvalidArgumentException($this->value);
        }
    }
}

echo CurrenciesEnum::RUB->code(), PHP_EOL;
echo CurrenciesEnum::RUB->name(), PHP_EOL;
echo CurrenciesEnum::RUB->short(), PHP_EOL;


Вариант 2 (enum)

<?php

enum CurrenciesEnum
{
    case RUB;
    case USD;
    case EUR;
    case GBP;
    case JPY;
    case CNY;

    public function code(): string
    {
        return $this->name;
    }

    public function name(): string
    {
        return self::getField($this->name, 'name');
    }

    public function short(): string
    {
        return self::getField($this->name, 'short');
    }

    public function ratio(): string
    {
        return self::getField($this->name, 'ratio');
    }

    public function default(): string
    {
        return self::getField($this->name, 'default');
    }

    public function display(): string
    {
        return self::getField($this->name, 'display');
    }

    private static function getField(string $currency, string $field): string
    {
        $data = [
            self::RUB->name => ['name' => 'Рублей', 'short' => '₽', 'ratio' => 1, 'default' => 1, 'display' => 1],
            self::USD->name => ['name' => 'Dollar', 'short' => '$', 'ratio' => 1, 'default' => 1, 'display' => 1],
            self::EUR->name => ['name' => 'Euro', 'short' => '€', 'ratio' => 1, 'default' => 1, 'display' => 1],
            self::GBP->name => ['name' => 'Pound', 'short' => '£', 'ratio' => 1, 'default' => 1, 'display' => 1],
            self::JPY->name => ['name' => '円', 'short' => '¥', 'ratio' => 1, 'default' => 1, 'display' => 1],
            self::CNY->name => ['name' => '元', 'short' => 'Ұ', 'ratio' => 1, 'default' => 1, 'display' => 1],
        ];

        if (!isset($data[$currency])) {
            throw new InvalidArgumentException($currency);
        }

        return $data[$currency][$field];
    }
}

echo CurrenciesEnum::RUB->code(), PHP_EOL;
echo CurrenciesEnum::RUB->name(), PHP_EOL;
echo CurrenciesEnum::RUB->short(), PHP_EOL;



Вариант 3 (storage)


Класс Currency
final class Currency
{
    public function __construct(
        readonly string $code,
        readonly string $name,
        readonly string $short,
        readonly int $ratio = 1,
        readonly int $default = 1,
        readonly int $display = 1,
    )
    {
    }
}


Класс CurrencyStorage
final class CurrenciesStorage
{
    private static self|null $instance = null;

    /** @var Currency[] */
    private array $currencies = [];

    private function __construct()
    {
    }

    public static function getInstance(): self
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    public function add(Currency $currency): void
    {
        $this->currencies[$currency->code] = $currency;
    }

    public function has(string $code): bool
    {
        return isset($this->currencies[$code]);
    }

    public function get(string $code): Currency|null
    {
        return $this->currencies[$code] ?? null;
    }

    public function all(): array
    {
        return $this->currencies;
    }
}


Потом при инициализации своего модуля тебе нужно будет создать инстанс сторажда и заполнить его дефолтными значениями:
$storage = CurrenciesStorage::getInstance();
$storage->add(new Currency('RUB', 'Рублей', '₽'));
$storage->add(new Currency('USD', 'Dollar', '$'));
$storage->add(new Currency('EUR', 'Euro', '€'));


// Получить данные по одному объекту
echo $storage->get('RUB')->code, PHP_EOL;
echo $storage->get('RUB')->name, PHP_EOL;
echo $storage->get('RUB')->short, PHP_EOL;

// Получить все объекты
var_dump($storage->all());


Данный код в объектном стиле, в IDE будут работать подсказки, у стораджа есть тайпхинтинк (соответственно туда ничего кроме currency нельзя буде запихнуть). Плюс работает инкапсуляция, т.к. свойства у currency readonly их нельзя будет изменить в другом коде
Ответ написан
ThunderCat
@ThunderCat Куратор тега PHP
{PHP, MySql, HTML, JS, CSS} developer
1) Почему статика? В общем случае статические классы плохой тон, так как повышают неконсистентность системы и непредсказуемость поведения.
2) Да, можно задать анонимный класс, но делать это в конструкторе.
<?php
class Curs{
  public $currencies;
    function __construct($curencyArray){
      $this->currencies =  new class($curencyArray){
        function __construct($arr){
          foreach($arr as $crn){
            $this->{strtolower($crn['code_cur'])} = (object)$crn;
          }
    	}
	  };
   }
};
$currencies = [
    ['name_cur'=>'Рублей','short_cur'=>'₽','code_cur'=>'RUB','ratio_cur'=>1,'default_cur'=>1,'display_cur'=>1,],
    ['name_cur'=>'Dollar','short_cur'=>'$','code_cur'=>'USD','ratio_cur'=>1,'default_cur'=>1,'display_cur'=>1,],
    ['name_cur'=>'Euro','short_cur'=>'€','code_cur'=>'EUR','ratio_cur'=>1,'default_cur'=>1,'display_cur'=>1,],
    ['name_cur'=>'Pound','short_cur'=>'£','code_cur'=>'GBP','ratio_cur'=>1,'default_cur'=>1,'display_cur'=>1,],
    ['name_cur'=>'円','short_cur'=>'¥','code_cur'=>'JPY','ratio_cur'=>1,'default_cur'=>1,'display_cur'=>1,],
    ['name_cur'=>'元','short_cur'=>'Ұ','code_cur'=>'CNY','ratio_cur'=>1,'default_cur'=>1,'display_cur'=>1,],
  ];

$curs = new Curs($currencies);
var_dump($curs->currencies->usd);
/*
object(stdClass)#4 (6) {
  ["name_cur"]=>
  string(6) "Dollar"
  ["short_cur"]=>
  string(1) "$"
  ["code_cur"]=>
  string(3) "USD"
  ["ratio_cur"]=>
  int(1)
  ["default_cur"]=>
  int(1)
  ["display_cur"]=>
  int(1)
}
*/

или в любой другой конфигурации...
Ответ написан
Комментировать
Сделайте статический гетер который при первом вызове и будет инициализировать все объекты.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Статические переменные и свойства классов можно инициализировать только константами и константными выражениями, но не функциями. В вашем случае (object) вызывает функцию-конструктор объекта.
Можно сделать заполнение в конструкторе класса, но тогда придётся создать хотя бы один экземпляр класса прежде, чем использовать статическое свойство.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы