Autor Zpráva
4ever
Profil
Mám třídu

class Mysql_class {
  public function prepareSQLArray($file, &$sqlObject) {
  list($db, $table, $stage) = $sqlObject->getSettings(); #vrací Fatal error: Call to undefined method stdClass::getSettings()
  }
}


A druhou třídu:

class SqlObject_class {
  public $prepared_data;
  public $db_name;
  public $db_table;
  public $stage;

  public function __construct ($db_name, $db_table, $stage){
  $this->db_name  = $db_name; 
  $this->db_table = $db_table;
  $this->stage = $stage;
  }

  public function getSettings(){
    return array ($this->db_name, $this->db_table, $this->stage);   
  }


V souboru index.php:
$mysql->prepareSQLArray($file, $sqlBasic);


$sqlObject->getSettings() vrací Fatal error: Call to undefined method stdClass::getSettings()

Tak si kladu otázku, jesltli se dá přes argument metody předat objekt i s funkcí. Data objektu přístupné jsou.
TomášK.
Profil *
4ever:
Ukaž ještě, jak vznikne hodnota $sqlBasic - poslední přiřazení do ní před zavoláním $mysql->prepareSQLArray($file, $sqlBasic);
Majkl578
Profil
Jistěže, stdClass totiž žádné metody nemá. V proměnné $sqlBasic nemáš objekt SqlObject_class (mimochodem, nevhodné jméno).

&$sqlObject
Objekty se referencí nepředávají.

Celé je to z principu špatně. Veřejné vlastnosti porušují zapoudřenost objektu, ideální je mít pro každou vlastnost getter a setter.
Co to má vlastně dělat?
4ever
Profil
$sqlBasic = new SqlObject_class($config->mysql->db->name[0],$config->mysql->db->tables[0], "init");
$sqlBasic->getSettings(); # TOTO CHYBU NEHLÁSÍ
$sqlBasic->main &= $main;  
$sqlBasic = $sqlDetaily; # Áááááá, tady je chyba
$sqlBasic->name = "BASIC";
$sqlDetaily->name = "DETAILY";


Měl to být takový balíček či token s informacemi, který jsem chtěl předávat mezi metodami dvou různých tříd. Je tam mimo jiné jméno databáze a tabulky.

Jeden balíček se jménem $sqlBasic je pro jednu tabulku, do které se mají ukládat data.

Druhý balíček se jménem $sqlDetaily je pro druhou tabulku, do které se mají ukládat další data.

Ještě existuje třída Main_class, která připravuje data a má se to předat do $sqlBasic nebo do $sqlDetaily ke zpracování (ale zpracování je ve třídě Mysql_class). Tedy v Main_class je metoda na převod mezi sloupci a pak se to má ve třídě Mysql_class připravit a vygenerovat SQL příkazy. Celkem dva.
4ever
Profil
už jsem tu chybu našel, viz komentář výše v kodu
4ever
Profil
Ještě jednu divnou věc jsem zpozoroval tak se chci na ní zeptat:

Funkční kód vrací jméno
$sqlBasic = new SqlTokenObject_class($config->mysql->db->name, $config->mysql->db->tables[0], "init");
$sqlBasic->main &= $main;
$sqlBasic->name = "BASIC";

$sqlDetaily = new SqlTokenObject_class($config->mysql->db->name, $config->mysql->db->tables[1], "init");
$sqlDetaily->main &= $main;
$sqlDetaily->name = "DETAILY";

die($sqlBasic->name)


vypíše BASIC

toto:
$sqlBasic = new SqlTokenObject_class($config->mysql->db->name, $config->mysql->db->tables[0], "init");
$sqlBasic->main &= $main;
$sqlBasic->name = "BASIC";
$sqlDetaily = $sqlBasic;
die($sqlBasic->name); # TADY
$sqlDetaily->name = "DETAILY";
$sqlDetaily->db_table = $config->mysql->db->tables[1];


Vypíše Basic

A toto:

$sqlBasic = new SqlTokenObject_class($config->mysql->db->name, $config->mysql->db->tables[0], "init");
$sqlBasic->main &= $main;
$sqlBasic->name = "BASIC";
$sqlDetaily = $sqlBasic;
$sqlDetaily->name = "DETAILY";
die($sqlBasic->name);   # TADY
$sqlDetaily->db_table = $config->mysql->db->tables[1];


Vypíše "DETAILY".

Čili příkazy

$sqlDetaily = $sqlBasic;
$sqlDetaily->name = "DETAILY";

Jakoby $sqlDetaily->name nastavilo současně i $sqlBasic->name = $sqlDetaily->name
Tori
Profil
Tady je příčina:
$sqlDetaily = $sqlBasic;
Proměnná splDetaily je teď referencí na sqlBasic, takže nastavení vlastnosti u sqlDetaily se projeví i u splBasic. (viz manuál)
4ever
Profil
Tori:
Nerozumím ti. Ten příklad zkouším, ale reference se tam uvádí jako $reference =& . A ta je pochopitelně vynulovaná. Kdežto $assigned je stále v paměti. Použil jsem přece operátor pro přiřazení.
Majkl578
Profil
Objekty se v PHP předávají vždy jako jakési odkazy odkazující vždy na původní místo, to je taky důvod, proč se při přiřazování objektů nepoužívají ampersandy a i přesto to funguje (tj. hodnota se mění na všech místech). Přiřazení objektu je tedy vlastně jen odkazem, pro vytvoření kopie se používá clone. Abys objekt zničil, musíš smazat všechny odkazy na něj (v tomhle případě vynulovat všechny proměnné, které na něj odkazují).

Tady je lépe vidět jak se to chová:
$a = new \DateTime();

debug_zval_dump($a); // refcount == 2

$aCopy = $a; // refcount++
debug_zval_dump($a); // refcount == 3
debug_zval_dump($aCopy); // refcount == 3

var_dump($a === $aCopy); // TRUE

unset($a);
debug_zval_dump($aCopy); // refcount == 2
4ever
Profil
Tak já se celou dobu bál, že když dávám objekt jako argument metodě, tak že se to kopíruje, pokud tam není referenční operátor.

OK tak to snad už chápu. Co se týče operátorů pro objekty - vyvozuju z toho, že oba operátory =,=& jsou pro přiřazování s tím rozdílem, že =& se chová jako klasický odkaz (když vynuluju původní objekt, tak kopie zmizí), kdežto = se chová víc jako kopie, v tom smyslu, že když vynuluju původní objekt, tak kopie nezmizí. Nebylo by pak bezpečnější a přehlednější používat ten druhý operátor =&?
Tori
Profil
4ever:
=& u objektů je zbytek z PHP 4 - tam se objekt považoval za primitivní dat.typ, jako např.řetězec, takže se předávala hodnotou. To znamená, že $a = $obj vytvořilo kopii (klon) objektu, kdežto $a =& $obj vytořilo odkaz na objekt. V PHP 5 se přístup změnil: = také vytváří odkaz na objekt, =& zůstalo v původním významu, a kopie objektu se vytváří klíč.slovem clone. (Viz manuál)
YoSarin
Profil
Tori:
$a =& $obj vytořilo odkaz na objekt
Z manuálu to spíš vyznívá takhle: $a =& $obj vytoří $a jako alias pro $obj (pardon za termín alias, ale lepší mě nenapadl). Jestli to čtu (a testuju) dobře, tak =& a = se chová rozdílně (alespoň u objektů)
4ever
Profil
Tori:
Tak to jsem řešil už v JavaScriptu když jsem se učil pracovat s JQuery (tuším že tam je na to nějaká metoda taky se slovem clone). Takže je mi to už jasné. Díky za vysvětlení.
4ever
Profil
YoSarin:
To slovo alias se mi líbí. To docela vystihuje podstatu =&. Takže vlastně se tím vytváří jen nový název pro tu samou věc.
Tori
Profil
YoSarin:
Jestli to čtu (a testuju) dobře, tak =& a = se chová rozdílně (alespoň u objektů)
Aha, tak to se omlouvám za dezinformace, jsem to pochopila jinak, a jelikož používám buď = nebo clone, tak jsem si rozdílu mezi = a =& nevšimla.
4ever
Profil
Tori:

Tak platí tvůj příspěvek [#7] ?

Napsala si:
$sqlDetaily = $sqlBasic;
Proměnná splDetaily je teď referencí na sqlBasic, takže nastavení vlastnosti u sqlDetaily se projeví i u splBasic.


Je to kopie? A jestli je to kopie, proč se chová podivně, že ?

Můj příspěvek: #6, třetí kód, 4. až 6. řádek ukazuje, že jde o referenci.

$sqlDetaily = $sqlBasic; // nastaví $sqlDetaily jako odkaz na $sqlBasic
$sqlDetaily->name = "DETAILY"; // nastaví defacto $sqlBasic->name
die($sqlBasic->name);   # vypíše DETAILY místo BASIC
Tori
Profil
4ever:
Aha, teď jsem si s tím trochu hrála a snad to už chápu. Takže:
= i =& z pohledu objektu vytvoří totéž - odkaz na jeden a tentýž objekt. Ale rozdíl je v zacházení s tou proměnnou samotnou.
$obj1 = $obj2;
$obj2 = null;
var_dump($obj1); // Tato proměnná stále existuje a odkazuje na původní objekt.

$obj1 =& $obj2;
$obj2 = null;
var_dump($obj1); // Tady už neexistuje, protože byla nejen "aliasem" pro objekt, ale i pro proměnnou $obj2

Mírně upravený příklad z manuálu:
class SimpleClass
{
    public $var = 'a default value';
    public function displayVar() {
        echo $this->var;
    }
}


$instance = new SimpleClass();
$reference  =& $instance;
$assigned   = $instance;
$xyz = clone $instance;

$instance->var = '$assigned will have this value';

echo 'instance: '; var_dump($instance);
echo '<br>reference: '; var_dump($reference);
echo '<br>prirazeni: '; var_dump($assigned);
echo '<br>klon: '; var_dump($xyz);
echo "<hr>Instance smazana.<hr>";

$instance = null;

echo 'instance: '; var_dump($instance);
echo '<br>reference: '; var_dump($reference);
echo '<br>prirazeni: '; var_dump($assigned);
echo '<br>klon: '; var_dump($xyz); 
A výsledky:
instance: object(SimpleClass)#1 (1) { ["var"]=> string(30) "$assigned will have this value" }  // new
reference: object(SimpleClass)#1 (1) { ["var"]=> string(30) "$assigned will have this value" }  // =&
prirazeni: object(SimpleClass)#1 (1) { ["var"]=> string(30) "$assigned will have this value" }  // =
klon: object(SimpleClass)#2 (1) { ["var"]=> string(15) "a default value" }  // = clone
---- Instance smazana. -----
instance: NULL  // new
reference: NULL  // =&
prirazeni: object(SimpleClass)#1 (1) { ["var"]=> string(30) "$assigned will have this value" }  // =
klon: object(SimpleClass)#2 (1) { ["var"]=> string(15) "a default value" } // = clone

Vaše odpověď

Mohlo by se hodit

Odkud se sem odkazuje


Prosím používejte diakritiku a interpunkci.

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

0