Autor Zpráva
Jankosar
Profil
Dobrý den,
mám jistý problém v mém PHP kódu. Nejsem si zcela jistý, v čem spočívá, ale protože se problém táhne přes asi 2000 řádků v několika souborech, pokusím se uvést pouze ty části, kterých se to pravděpodobně dotýká.

Mám vytvořenou třídu pro tvorbu HTML hlavičky. Funguje jednoduše: vytvořím si objekt této třídy, nastavím mu všechny parametry a pak mi funkce Head::vytvor() vrátí HTML kód celé hlavičky. Takhle vypadá začátek třídy:

<?php
class Head
{
  //definice proměnných
  private $title;
  private $description;
  private $author;
  private $encoding;
  private $keyword;
  private $css;
  private $js;
  
  
  //konstruktor
  function __construct()
  {
    ;
  }
  
  //set-funkce
  function set_title($title)
  {
    $this->title=$title;
  }
  function set_description($description)
  {
    $this->description=$description;
  }



atd............................


tuto třídu mám celou definovanou v souboru head.php.
V souboru index.php pak deklaruji objekt této třídy takto:

include('head/head.php');
  $head=new Head();


Tento objekt $head potom použivám jednak v souboru index.php a pak v dalších souborech includovaných do index.php, což funguje poměrně bez problémů. Potíže ale nastanou ve chvíli, kdy se pokouším k tomuto objektu přistupovat z nějaké funkce. Příklad (soubor lsloupec.php includovaný do index.php):

Tohle funguje skvěle:
$head->set_title('tralala');
function lsloupec()
{
  $return='';
  
  //----------Články------------//
  $menu_clanky=new Menu('Články');
  {
    $menu_clanky->add_polozky('O rase','o_rase','');
    $menu_clanky->add_polozky('Rozhovory','clanky','rozhovory');
    $menu_clanky->add_polozky('Rady nováčkům','clanky','rady_novackum');
    $menu_clanky->add_polozky('Herní principy','clanky','herni_principy');
  }
  $return.=$menu_clanky->vytvor();
  $return.='<br><br>';
  
  



Kdežto tohle vyhazuje chybu:
function lsloupec()
{
  $head->set_title('tralala');
  $return='';
  
  //----------Články------------//
  $menu_clanky=new Menu('Články');
  {
    $menu_clanky->add_polozky('O rase','o_rase','');
    $menu_clanky->add_polozky('Rozhovory','clanky','rozhovory');
    $menu_clanky->add_polozky('Rady nováčkům','clanky','rady_novackum');
    $menu_clanky->add_polozky('Herní principy','clanky','herni_principy');
  }
  $return.=$menu_clanky->vytvor();
  $return.='<br><br>';
  
  


Tady je celý výpis chyby:
Fatal error: Call to a member function set_title() on a non-object in /home/free/ic.cz/k/kosar-vyvoj/root/www/novy/lsloupec.php on line 4



Celá funkce lsloupec() je deklarována až poté, co je vytvořen objek head.

Nevíte prosím někdo, jak by se tohle dalo řešit? Tuším sice, že by se to možná dalo řešit jakýmsi předáváním ukazatele na objekt jako argumentu volání funkce, ale já těch funkcí používám opravdu hodně, i těch objektů bude trochu více. Takže budu vděčný za jakékoliv nápady a rady.

Předem děkuji všem
__construct
Profil
Pletú sa Ti pojmy funkcia a metóda (pred pár dňami to tu bolo rozoberané)
Každopádne ak chceš z funkcie (nie metódy) pristupovať k nejakému objektu musíš si v nej vytvoriť inštanciu tej triedy ... Pokiaľ chceš k tomu objektu pristupovať z vnútra iného objektu (z metódy - nie funkcie) stačí si vytvoriť inštanciu v rámci objektu a pristupovať k nej cez
$this->objekt->metoda();

//edit: odporúčam prečítať tento článok
Jankosar
Profil
rozdíl mezi funkcí a metodou je mi celkem jasný, teď vidím, že jsem to nahoře trochu spletl (zmátla mě ta chybová hláška)

Jinak tebou navrhované řešení by v tomto případě příliš nepomohlo. Já už mám vytvořenou jednu instanci třídy Head a v ní mám uložena všechna data. Pokud bych si vytvořil další instanci třídy, nemohl bych přistupovat k datům té první instance.

I když teď mě napadá, že kdybych všechny atributy třídy označil jako static, tak by jsem potom mohl měnit data v jakékoliv instanci a fungovalo by to skvěle....

Co myslíte?

PS: ten článek mám dávno načtený
Majkl578
Profil
V tom případě by ti pomohla globálně dostupná instance. Vhodným řešením by mohla být jakási servisní třída, která by spravovala instance (hotovým příkladem může být třída Nette\Environment, která toto obstarává jako služby).
Při správném návrhu by to mohlo být poměrně čisté řešení problému.
Mastodont
Profil
Jankosar:
V podstatě máš tři základní možnosti, jak řešit globální dostupnost:
1. Předávat všechny potřebné jiné objekty do funkce jako parametr, do jiného objektu obvykle v konstruktoru (dependency injection - stovky článků, v poslední době silně prosazováno hlavně kvůli TDD)
2. Globální registr vracející potřebné objekty nějakou getX metodou. Registr sám je statická třída.
3. Globální statické třídy pro jednotlivé potřebné objekty.
Jankosar
Profil
Děkuji všem za rady, myslím, že už začínám mít představu, co tento problém obnáší a jaké jsou možnosti ho řešit.
Majkl578: Nedělám zas tak velikou aplikaci, abych tam dával přímo tuto třídu, ale asi vytvořím něco vlastního a značně primitivnějšího

Mastodont: to 2. nebo 3. bude asi ideální

buď by se to dalo udělat takhle:
class Get
{
  static private head;
  static private neco;
  static private cosi;
  
  __construct()
  {
    $this->head=new Head();
    $this->neco=new Neco();
    $this->cosi=new Cosi();
  }
}


a pak k nim přistupovat takto:
$get=new Get();
$get->head->set_title("Titulek");



nebo by bylo skoro lepší, kdyby se to obešlo bez té obslužné třídy. Můžete mi prosím ještě trochu přiblížit, jak jste to myslel s tím bodem č 3?
Děkuji.
Majkl578
Profil
Jankosar:
abych tam dával přímo tuto třídu
Ona by sama stejně nefungovala. A ani to nebylo záměrem.

Pokud chceš použít takový přístup jaký jsi popsal, asi by bylo vhodné použít singleton třídy Get a její overloading s lazy vytvářením instancí.
Jankosar
Profil
Majkl578:
"(hotovým příkladem může být třída Nette\Environment, která toto obstarává jako služby)"
Tak vzhledem k tomu, že tato třída "toto obstarává", tak nevidím důvod, proč by se nedala použít.

Jinak se mrknu na to cos psal. Nejsem zas moc pokročilý v PHP, tak si o tom budu muset něco počíst.
__construct
Profil
[#6] Jankosar:
Toto nie je správne:

class Get {
  static private head;
  static private neco;
  static private cosi;
  
  __construct() {
    $this->head=new Head();
    $this->neco=new Neco();
    $this->cosi=new Cosi();
  }
}

$get=new Get();
$get->head->set_title("Titulek");

- Hodilo by Ti to fatal error .. k privátnej metóde sa dá pristupovať iba zvnútra ..
- na statické metódy sa odkazuje dvoma dvojbodkami
Trieda::statickaMetoda($argument);
Jankosar
Profil
Tak jsem to vyřešil docela dobře. Děkuji všem za rady. Udělal jsem to nakonec tak, že jsem celou třídu předělal na statickou a přistupuji k ní tedy staticky. Doufám, že s tím nebudou nějaké komplikace.
Ještě jednou děkuji všem.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0