IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
Neaktivní uživatel:18.7.2019 19:25

Ahoj,
nevíte proč nefunguje kód uvedený níže? Problém je v tom že když do něj dám 6 hodnot, uloží jen 1-2 poslední, což taky nechápu jelikož by to mělo být deterministické. (jsou to stejné hodnoty). Žádný error to nehází. Všechny hodnoty jsou datového typu string, jedná se primárně o přihlašovací údaje k DB. Pokud Vás napadne lepší řešení, tak to klidně mohu udělat podle vašeho řešení.

class Config {
  private $path = __DIR__ . "/config.json";
  function load () {
    $f = fopen ($this->path, "r");
    unset ($GLOBALS["_config"]);
    $GLOBALS["_config"] = json_decode (fread ($f, filesize ($this->path)), true);
    fclose ($f);
  }
  function __construct () {
    if (!isset($GLOBALS["_config"])) {
      $this->load ();
    }
  }
  function get ($name) {
    if (isset ($GLOBALS["_config"][$name])) {
      return $GLOBALS["_config"][$name];
    } else {
      return null;
    }
  }
  function set ($name, $content) {
    $d = $GLOBALS["_config"];
    $d[$name] = $content;
    $f = fopen ($this->path, "w");
    fwrite ($f, json_encode ($d));
    fclose ($f);
    $this->load ();
  }

}

Zkusil jsem: Googlit, zírat do kódu, zkoušet

Chci docílit: Uložení přihlašovacích údajů k DB.

Odpovědět
18.7.2019 19:25
Neaktivní uživatelský účet
Avatar
Jan Kerhart
Člen
Avatar
Odpovídá na Neaktivní uživatel
Jan Kerhart:19.7.2019 2:25

Ahoj,
nahraď funkci fread() za file_get_contents() a smaž řádek 4 a 7 a mělo by to fungovat :)

unset ($GLOBALS["_config"]);
$GLOBALS["_config"] = json_decode (file_get_contents($this->path), true);

Co se týče řešení obecně, tak

  • Vyvaruj se používání $GLOBALS a podobných nesmyslů, pokud k tomu nemáš dobrý důvod. Použij raději klasický privátní atribut. (A nenapadá mě žádný případ, kdy by bylo $GLOBALS nutno použít.)
  • U každé metody by měl být uveden modifikátor přístupu (public, private, protected)
  • Natvrdo napsat cestu k souboru do třídy není úplně ideálním řešením, třída potom není univerzální a nejde ji použít na jiném místě.
  • Pokud soubor neexistuje, vyhodí to warning.
  • Pokud byla mezi načtením souboru a zápisem hodnoty v souboru provedena nějaká změna, tak se smaže. Pozn: V mém řešení se naopak změna neprojeví ve stávající instanci. Pokud by toto bylo nežádoucí, je možné to jednoduše upravit.

Já osobně bych to řešil asi nějak takto:

namespace MatejStrnad\Settings;

use Exception;

class SettingsManager
{
    /**
     * @var array Stores current settings.
     */
    private $data;
    /**
     * @var string Path to settings file.
     */
    private $filePath;

    /**
     * SettingsManager constructor.
     * @param string $filePath Path to settings file.
     */
    public function __construct($filePath)
    {
        $this->filePath = $filePath;
        $this->load();
    }

    /**
     * Loads settings from file.
     */
    public function load()
    {
        if (file_exists($this->filePath)) {
            $this->data = json_decode(file_get_contents($this->filePath), true);
        } else {
            $file = fopen($this->filePath, 'w');
            fclose($file);
        }
    }

    /**
     * Gets setting value.
     * @param string $key Settings key to return.
     * @return string|null
     */
    public function getValue($key)
    {
        if (isset($this->data[$key])) {
            return $this->data[$key];
        } else {
            return null;
        }
    }

    /**
     * Saves value to settings file.
     * @param string $key Settings key to set.
     * @param string $value Value of the key.
     * @throws Exception
     */
    public function setValue($key, $value)
    {
        $fileContents = json_decode(file_get_contents($this->filePath), true);
        $fileContents[$key] = $value;
        $file = fopen($this->filePath, 'w');
        if (fwrite($file, json_encode($fileContents)) === false) {
            throw new Exception("Write error!");
        }
        fclose($file);
    }
}

Pokud to ale budeš používat pouze pro ukládání údajů od databáze, tak mi to přijde zbytečně složité. V tomto případě bych asi použil jen obyčejnou statickou třídu:

class Settings
{
    public static $database = array(
        'host' => "192.168.1.123",
        'user' => "root",
        'pass' => "12345",
        'db' => "system"
    );

    public static $projectName = "Jméno projektu";

}

A použiješ ji jednoduše takto:

echo(Settings::$projectName); //Vypíše název projektu
$ip = Settings::$database['host']; //Uloží adresu do proměnné

Nevýhoda tohoto řešení je, že nejde jednoduše nastavení měnit z aplikace, to ale u údajů od databáze většinou nepotřebujeme. Velkou výhodou je ale zase to, že kdyby se někomu podařilo nějak tento soubor načíst (např. chybou v jiné třídě), tak jeho obsah stejně uživatel neuvidí, protože se soubor jen načte v php a uživateli se jeho obsah neodešle...

Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
 
Nahoru Odpovědět
19.7.2019 2:25
Avatar
Jan Kerhart
Člen
Avatar
Odpovídá na Jan Kerhart
Jan Kerhart:19.7.2019 2:54

Pozn. Ještě mě napadlo, metoda setValue by se dala pěkně zjednodušit pomocí metody file_put_contents, ale funkce je stejná:

public function setValue($key, $value)
    {
        $fileContents = json_decode(file_get_contents($this->filePath), true);
        $fileContents[$key] = $value;
        if (file_put_contents($this->filePath, $fileContents) === false) {
            throw new Exception("Write error!");
        }
    }
Editováno 19.7.2019 2:56
 
Nahoru Odpovědět
19.7.2019 2:54
Avatar

Člen
Avatar
Odpovídá na Jan Kerhart
:19.7.2019 10:20

Mám otázku napríklad na túto metódu:

public function getValue ($key) {
  if (isset($this->data[$key])) {
    return $this->data[$key];
  } else {
    return null;
  }
}

Nešla by zapísať aj takto?

public function getValue ($key) {
  return $this->data[$key] ?? null;
}
 
Nahoru Odpovědět
19.7.2019 10:20
Avatar
Jan Kerhart
Člen
Avatar
Odpovídá na
Jan Kerhart:19.7.2019 13:02

Ano, určitě šla. Jen pozor na to, že tento tzv. "null coalescing operator" je podporován až od verze PHP 7 a mnoho (špatných) hostingů používá stále ještě PHP 5.x. Ale pokud máš kvalitní hosting, kde si můžeš vybrat a nebo mají PHP aktualizované, tak určitě. Na starším PHP by to šlo zapsat také třeba ternálním operátorem:

return isset($this->data[$key]) ? $this->data[$key] : null
 
Nahoru Odpovědět
19.7.2019 13:02
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 5 zpráv z 5.