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" или как то еще ананимное объявление можно использовать?
  • Вопрос задан
  • 253 просмотра
Решения вопроса 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) вызывает функцию-конструктор объекта.
Можно сделать заполнение в конструкторе класса, но тогда придётся создать хотя бы один экземпляр класса прежде, чем использовать статическое свойство.
Ответ написан
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы
01 мая 2024, в 02:11
5000 руб./за проект
01 мая 2024, в 00:29
2000 руб./за проект
01 мая 2024, в 00:20
15000 руб./за проект