Autor Zpráva
scorapka
Profil
Dobrý den,

koupil jsem si knihu Programujeme vlastní e-shop v PHP 5, Michael Peacock http://knihy.cpress.cz/programujeme-vlastni-e-shop.html
Stáhl jsem si zdrojové kody příkladů.
Vložil do svého adresáře www.
Vytvořil databázi a udělal vše co je v souboru ČTIMNE.txt
Po spuštění vyskakují chyby:

Strict Standards: Non-static method PHPEcommerceFrameworkRegistry::getSetting() should not be called statically, assuming $this from incompatible context in C:\www\ecom\registry\objects\template.class.php on line 180


Můžete také vyzkoušet ale prosím co znamená tato chyba?
Děkuji.


zkoušel jsem nastavit metodu na statickou (public static) ale nepomáha, dále to píše chybu:

Notice: Undefined offset: 0 in C:\www\ecom\models\basket\model.php on line 129


tady je ta chybná funkce, co hlásí chybu, že není statická...
 public function buildFromTemplates()
    {
        $bits = func_get_args();
        $content = "";
        foreach( $bits as $bit )
        {
            
            if( strpos( $bit, 'views/' ) === false )
            {
                $bit = 'views/' . PHPEcommerceFrameworkRegistry::getSetting('view') . '/templates/' . $bit;
            }
            if( file_exists( $bit ) == true )
            {
                $content .= file_get_contents( $bit );
            }
            
        }
        $this->page->setContent( $content );
    }
scorapka
Profil
tak díky za pomoc:(
Tori
Profil
scorapka:
zkoušel jsem nastavit metodu na statickou (public static) ale nepomáha, dále to píše chybu:
To je ale jiná chyba z úplně jiné třídy, ne?

Varianta 1: Jak vypadá ta metoda getSetting? Potřebuje / využívá na něco instanci Registry?
Varianta 2: jak vypadá třída Registry? Logicky bych podle názvu čekala, že to bude singleton, a tedy bude mít nějakou metodu Registry::getInstance() - má, nemá?
Kdyžtak se někdy k večeru kouknu na ty zdrojáky.
scorapka
Profil
Tori:
„zkoušel jsem nastavit metodu na statickou (public static) ale nepomáha, dále to píše chybu:
To je ale jiná chyba z úplně jiné třídy, ne?“
ano další chyba to je úplně jiné třídy. Abych byl konkrétnější, hodím sem úplný výpis chyb:

Strict Standards: Non-static method PHPEcommerceFrameworkRegistry::getSetting() should not be called statically, assuming $this from incompatible context in C:\www\ecom\registry\objects\template.class.php on line 180

Strict Standards: Non-static method PHPEcommerceFrameworkRegistry::getSetting() should not be called statically, assuming $this from incompatible context in C:\www\ecom\registry\objects\template.class.php on line 180

Strict Standards: Non-static method PHPEcommerceFrameworkRegistry::getSetting() should not be called statically, assuming $this from incompatible context in C:\www\ecom\registry\objects\template.class.php on line 180

Notice: Uninitialized string offset: 36 in C:\www\ecom\models\basket\model.php on line 163

Notice: Undefined variable: weightFound in C:\www\ecom\models\basket\model.php on line 127

Notice: Undefined offset: 0 in C:\www\ecom\models\basket\model.php on line 129

Notice: Undefined offset: 0 in C:\www\ecom\models\basket\model.php on line 132

Strict Standards: Non-static method PHPEcommerceFrameworkRegistry::getSetting() should not be called statically, assuming $this from incompatible context in C:\www\ecom\registry\objects\template.class.php on line 33

Strict Standards: Non-static method PHPEcommerceFrameworkRegistry::getSetting() should not be called statically, assuming $this from incompatible context in C:\www\ecom\registry\objects\template.class.php on line 180

Strict Standards: Non-static method PHPEcommerceFrameworkRegistry::getSetting() should not be called statically, assuming $this from incompatible context in C:\www\ecom\registry\objects\template.class.php on line 180

Strict Standards: Non-static method PHPEcommerceFrameworkRegistry::getSetting() should not be called statically, assuming $this from incompatible context in C:\www\ecom\registry\objects\template.class.php on line 180

Notice: Undefined offset: 0 in C:\www\ecom\registry\objects\page.class.php on line 130

Strict Standards: Non-static method PHPEcommerceFrameworkRegistry::getObject() should not be called statically, assuming $this from incompatible context in C:\www\ecom\registry\objects\template.class.php on line 111

Strict Standards: Non-static method PHPEcommerceFrameworkRegistry::getObject() should not be called statically, assuming $this from incompatible context in C:\www\ecom\registry\objects\template.class.php on line 111

Strict Standards: Non-static method PHPEcommerceFrameworkRegistry::getObject() should not be called statically, assuming $this from incompatible context in C:\www\ecom\registry\objects\template.class.php on line 111

Notice: Undefined offset: 0 in C:\www\ecom\registry\objects\template.class.php on line 78

Notice: Undefined offset: 0 in C:\www\ecom\registry\objects\template.class.php on line 83

Strict Standards: Non-static method PHPEcommerceFrameworkRegistry::getObject() should not be called statically, assuming $this from incompatible context in C:\www\ecom\registry\objects\template.class.php on line 139

Strict Standards: Non-static method PHPEcommerceFrameworkRegistry::getObject() should not be called statically, assuming $this from incompatible context in C:\www\ecom\registry\objects\template.class.php on line 139



Varianta 1:

/**
     * Vrátí nastavení z registru
     * @param String $key klíč použitý pro uložení nastavení
     * @return String nastavení
     */
    public function getSetting( $key )
    {
        return self::$settings[ $key ];
    }


Varianta 2:

Třída registry má singleton
    /**
     * metoda singleton pro přístup k objektu
     * @access public
     * @return 
     */
    public static function singleton()
    {
        if( !isset( self::$instance ) )
        {
            $obj = __CLASS__;
            self::$instance = new $obj;
        }
        
        return self::$instance;
    }


Hodím ti sem celou třídu registry.class.php



<?php
/**
 * The PCARegistry object
 * Implements the Registry and Singleton design patterns
 * Building a PHP Ecommerce Framework
 *
 * @version 1.0
 * @author Michael Peacock
 */
 
class PHPEcommerceFrameworkRegistry {
    
    /**
     * pole objektů uložených v registru
     * @access private
     */
    private static $objects = array();
    
    /**
     * pole nastavení uložených v registru
     * @access private
     */
    private static $settings = array();
    
    
    /**
     * instance registru
     * @access private
     */
    private static $instance;
    
    private static $urlPath;
    private static $urlBits = array();
    
    /**
     * Soukromý konstrutkor zabrání přímému vytvoření
     * @access private
     */
    private function __construct()
    {
    
    }
        
    /**
     * metoda singleton pro přístup k objektu
     * @access public
     * @return 
     */
    public static function singleton()
    {
        if( !isset( self::$instance ) )
        {
            $obj = __CLASS__;
            self::$instance = new $obj;
        }
        
        return self::$instance;
    }
    
    /**
     * zabrání kolonování objektu: vyvolá chybu E_USER_ERROR
     */
    public function __clone()
    {
        trigger_error( 'Klonování registru není povoleno', E_USER_ERROR );
    }
    
    /**
     * Uloží objekt do registru
     * @param String $object název objektu
     * @param String $key klíč do pole
     * @return void
     */
    public function storeObject( $object, $key )
    {
        if( strpos( $object, 'database' ) !== false )
        {
            $object_a = str_replace( '.database', 'database', $object);
            $object = str_replace( '.database', '', $object);
            require_once('databaseobjects/' . $object . '.database.class.php');
            $object = $object_a;
        }
        else
        {
            require_once('objects/' . $object . '.class.php');
        }
        
        self::$objects[ $key ] = new $object( self::$instance );
    }
    
    /**
     * Vrátí objekt z registru
     * @param String $key klíč do pole použitý při uložení objektu
     * @return object - objekt
     */
    public function getObject( $key )
    {
        if( is_object ( self::$objects[ $key ] ) )
        {
            return self::$objects[ $key ];
        }
    }
    
    /**
     * Uloží nastavení do registru
     * @param String $data the setting we wish to store
     * @param String $key klíč pro přístup k nastavení
     * @return void
     */
    public function storeSetting( $data, $key )
    {
        self::$settings[ $key ] = $data;
    }
    
    /**
     * Vrátí nastavení z registru
     * @param String $key klíč použitý pro uložení nastavení
     * @return String nastavení
     */
    public function getSetting( $key )
    {
        return self::$settings[ $key ];
    }
    
    
    /**
     * Vrátí data z aktuální adresy URL
     * @return void
     */
    public function getURLData()
    {
        $urldata = (isset($_GET['page'])) ? $_GET['page'] : '' ;
        self::$urlPath = $urldata;
        if( $urldata == '' )
        {
            self::$urlBits[] = 'home';
            self::$urlPath = 'home';
        }
        else
        {
            $data = explode( '/', $urldata );
            while ( !empty( $data ) && strlen( reset( $data ) ) === 0 ) 
            {
                array_shift( $data );
            }
            while ( !empty( $data ) && strlen( end( $data ) ) === 0) 
            {
                array_pop($data);
            }
            self::$urlBits = $this->array_trim( $data );
        }
    }
    
    public function redirectUser( $urlPath, $header, $message, $admin = false)
    {
        self::getObject('template')->buildFromTemplates('redirect.tpl.php');
        self::getObject('template')->getPage()->addTag( 'header', $header );
        self::getObject('template')->getPage()->addTag( 'message', $message );
        if( $admin != true )
        {
            self::getObject('template')->getPage()->addTag('url', $urlPath );
        }
        else
        {
            //
        }
    }
    
    public function getURLBits()
    {
        return self::$urlBits;
    }
    
    public function getURLBit( $whichBit )
    {
        return self::$urlBits[ $whichBit ];
    }
    
    public function getURLPath()
    {
        return self::$urlPath;
    }
    
    private function array_trim( $array ) 
    {
        while ( ! empty( $array ) && strlen( reset( $array ) ) === 0) 
        {
            array_shift( $array );
        }
        
        while ( !empty( $array ) && strlen( end( $array ) ) === 0) 
        {
            array_pop( $array );
        }
        
        return $array;
    }
    
}

?>
Tori
Profil
Buď můžete všechna volání PHPEcommerceFrameworkRegistry::getNěco() a PHPEcommerceFrameworkRegistry::storeNěco()
přepsat na PHPEcommerceFrameworkRegistry::singleton()->getNěco(), anebo metody getSettings, storeSettings, getObject a storeObject změnit na statické. První možnost je bez problémů použitelná hned. U té druhé by bylo potřeba nejdřív ověřit v celém kódu eshopu, jestli se ty metody někde nevolají i na instanci (např. nechat vyhledat řetězec "->getSettings").

Je to docela hloupé, že ke knížce jsou zdrojáky, které generují chyby. E_STRICT bych ještě přežila, to může být i rokem napsání anglické verze knihy, ale E_NOTICE by tam už být nemělo.
pozn. ve [#3] jsem se ptala kvůli těmto dvěma možnostem, jen v opačném pořadí.
scorapka
Profil
Tori:
tak jsem ve tříde template.class.php přpsal ty volání (přidal singleton()->) chyby to už nepíše. Super. Takže díky moc za pomoc.

Ale ještě to hlásí tyhle chyby:
Notice: Undefined variable: weightFound in C:\www\ecom\models\basket\model.php on line 127

Notice: Undefined offset: 0 in C:\www\ecom\models\basket\model.php on line 129

Notice: Undefined offset: 0 in C:\www\ecom\models\basket\model.php on line 132

Notice: Undefined offset: 0 in C:\www\ecom\registry\objects\page.class.php on line 130

Notice: Undefined offset: 0 in C:\www\ecom\registry\objects\template.class.php on line 78

Notice: Undefined offset: 0 in C:\www\ecom\registry\objects\template.class.php on line 83

Notice: Undefined variable: filterSQL in C:\www\ecom\controllers\products\controller.php on line 222

Notice: Uninitialized string offset: 36 in C:\www\ecom\models\basket\model.php on line 163



Co tam jsou zase za chyby?
Tori
Profil
Koukla jsem na to zběžně, bez phpdoc to teda není úplně intuitivní. V models\basket\model.php se na ř.90+100 provádí zřejmě tentýž SQL dotaz dvakrát, ale chybu to nezpůsobí.

- models\basket\model.php:127 - Jelikož se musí sčítat váha všech produktů, tak by asi na ř.126 mělo být $weightFound = false;.
- models\basket\model.php:129+132 - Tohle vypadá, že metoda getShippingWeightCosts vrací prázdné pole. Asi si musíte nejdřív někde v backoffice nastavit alespoň jeden typ poplatků podle váhy zásilky (např. minimálně 0 kg, poplatek 0 Kč.)
- registry\objects\page.class.php:130 - Zkontrolujte si, odkud se to volá, jaká šablona a jaký blok je z ní požadován, jestli není někde v šabloně překlep. Asi by to šlo vyřešit výchozí hodnotou, pokud tag není nalezen:
        if (preg_match ('#<!-- START '. $tag . ' -->(.+?)<!-- END '. $tag . ' -->#si', $this->content, $tor) {
            $tor = str_replace ('<!-- START '. $tag . ' -->', "", $tor[0]);
            $tor = str_replace ('<!-- END '  . $tag . ' -->', "", $tor);
            return $tor;
        } else {
            return '';
        }
A vlastně by na to stačil jeden řádek:
return preg_match('#<!-- START '.$tag.' -->(.+?)<!-- END '.$tag.' -->#si', $this->content, $tor) ? $tor[1] : '';

- registry\objects\template.class.php:78+83 - najděte si volání metod addTag a/nebo addPPTag (asi to bude zapsané jako PHPEcommerceFrameworkRegistry::singleton()->getObject('page')->addTag) a zkontrolujte, co se tam posílá za data. Jako druhý parametr by mělo jít nějaké pole, zřejmě není v očekávaném tvaru, chybné klíče jednotlivých prvků apod. Případně pokud je klíč $data[0] nepovinný, tak změňte podmínku na ř.75 na: if (is_array($data) && isset($data[0])) {
- controllers\products\controller.php:222 - to má být zřejmě $this->filterSQL. V kódech k angl.originálu je to taky blbě.
- models\basket\model.php:163 - změňte ten řádek na $string .= $characters[mt_rand(0, strlen($characters)-1 )]; - Autor zapomněl, že ofset posledního bajtu v řetězci je o 1 menší, než délka řetězce.

No, přeju hodně štěstí při dohledávání a opravách dalších chybek. Většina z toho jsou jen maličkosti (spoléhání na existenci indexu v poli apod.), ale některé jsou docela hloupé chyby. To je ale IMHO vina nakladatele, resp. odborného redaktora, který by ten kód měl nejen projít a zkontrolovat syntax+překlad, ale i spustit a vyzkoušet.
scorapka
Profil
Tori:
Tak jsem to začal ladit.
Ale přesně nechápu jak myslíš tohle:
- models\basket\model.php:129+132 - Tohle vypadá, že metoda getShippingWeightCosts vrací prázdné pole. Asi si musíte nejdřív někde v backoffice nastavit alespoň jeden typ poplatků podle váhy zásilky (např. minimálně 0 kg, poplatek 0 Kč.)

Jsem začátečník a neumím si představit jak se nastavuje v backofficu ty poplatky. Máš na mysli v phpmyadminu, a nastavit v databazi ecom?

a toto:
- controllers\products\controller.php:222 - to má být zřejmě $this->filterSQL. V kódech k angl.originálu je to taky blbě.
máš na mysli nahradit if( $filterSQL == '' ) tímhle tím if( $this->filterSQL )

Jinak ti chci poděkovat za tvoji laskavost, že si mi pomohla opravit ty chybné kody.
Tori
Profil
Ad $filterSQL: ano, přesně tak, if ($this->filterSQL == ''). Když si projdete tu třídu, tak někde se tam do proměnné $this->filterSQL nastavuje nějaké omezení, předpokládala jsem teda, že se to týká i této metody.
K příplatkům za váhu zásilky - mělo by se to nastavit někde v tom eshopu. Ale můžete i přímo přidat 1 řádek do databáze. Zkuste spustit v phpmyadmin tohle, snad by to mělo být správně.
INSERT INTO `shipping_costs_weight` (`ID`, `shipping_id`, `lower_weight`, `cost`) VALUES
(1, 1, 0.0, 0.0);
A není zač. :)
scorapka
Profil
Tori:
Tak už se mi podařilo:) jak nahrát do databáze poplatky, tak i přidat if ($this->filterSQL == '') děkuji ti!

Jenže ta ukázka e-shopu má nekonečně mnoho chyb. Ještě to vypisuje tohle:

Notice: Undefined variable: currentWeight in C:\www\ecom\models\basket\model.php on line 129

Notice: Undefined index: in C:\www\ecom\models\basket\model.php on line 129

Notice: Undefined variable: currentWeight in C:\www\ecom\models\basket\model.php on line 132

Notice: Undefined index: in C:\www\ecom\models\basket\model.php on line 132

Notice: Array to string conversion in C:\www\ecom\registry\objects\template.class.php on line 92
Tori
Profil
Ty první dvě chyby (models\basket\model.php:129+132) by to vypisovat rozhodně nemělo. Nepřepsal jste si ten řádek, kde je definovaná výchozí hodnota 0? Měly by tam (po předchozí změně) být dva řádky:
$currentWeight = 0;
$weightFound = false;
a potom následuje ten cyklus: while( $weightFound == false ) ...

Tu druhou chybu jsem asi způsobila svou radou, nekoukla jsem se na druhou část podmínky. Asi teda bude lepší tohle:
            if( is_array( $data ) )
            {
              
                if( isset($data[0]) && $data[0] == 'SQL' )
                {
                    // jedná se o výsledek dotazu uložený v mezipaměti, značky se nahradí tímto výsledkem
                    $this->replaceDBTags( $tag, $data[1] );
                }
                elseif( isset($data[0]) && $data[0] == 'DATA' )
                {
                     // jedná se o data uložená v mezipaměti, značky se nahradí daty z mezipaměti 
                    $this->replaceDataTags( $tag, $data[1] );
                }
            }
scorapka
Profil
Tori:
tak to se omlouvám, zapomněl jsem tam přidat $currentWeight = 0;, to byla zase moje chyba:)

nicméně ještě jsou tam chyby:

Warning: Illegal string offset 'weight' in C:\www\ecom\models\basket\model.php on line 130

Warning: Illegal string offset 'cost' in C:\www\ecom\models\basket\model.php on line 133
Tori
Profil
Tohle zvládnete opravit. ;)
Illegal string offset 'weight'“ znamená, že se někdo pokouší použít klíč "weight" u proměnné, která není pole, ale řetězec. Takže se kouknete, že proměnná $shippingCosts je naplněná pomocí metody getShippingWeightCosts. V téhle metodě, která má vracet různé typy doplatků podle váhy zboží, se vytváří pole v jiném tvaru, než jaký je očekáván na ř.130. Máte teda dvě nesourodé varianty toho pole a musíte to sjednotit na jednu z nich. Dejte si vyhledat v celém eshopu, kde všude se volá metoda getShippingWeightCosts, koukněte se, jak se s tou návratovou hodnotou pracuje (tj. kterou z těch dvou možností, dvou způsobů uspořádání pole, očekává). Podle toho se pak rozhodněte:

A - metoda getShippingWeightCosts se buď jinde nepoužívá, anebo se tam taky počítá se stejnou strukturou pole, jako v místě, kde vám to hlásilo chyby. --> přepíšte metodu getShippingWeightCosts tak, aby vracela pole v jiném tvaru

B1 - na ostatních místech, kde se volá metoda getShippingWeightCosts, se pracuje s tou strukturou pole, kterou ona skutečně vrací. --> přepíšete tuhle část metody checkBasket, aby pracovala s jiným tvarem pole.
Ale tohle řešení by bylo dost obtížné, takže je možnost B2: --> přidáte další metodu, která použije stejný SQL dotaz jako getShippingWeightCosts, ale bude vracet pole v jiném tvaru.
scorapka
Profil
Tori:
No já jsem fakt úplný začátečník,
takže jsem hledal metodu getShippingWeightCosts v celém eshopu a nikde jinde není, jen v C:\www\ecom\models\basket\model.php na řádku 358
Nevím jak hledáte efektivněji ale já musel otevírat v PSPpadu každý soubor zvlášt a prohledávat zda tam není.

Chci si zvolit způsob A přepsat metodu getShippingWeightCosts , tak aby vracela pole ve správném tvaru. ale fakt netuším jak to udělat:(


že by to nemělo vracet Pole array()?


Notice: Undefined property: Basket::$isChecked in C:\www\ecom\controllers\basket\controller.php on line 62
scorapka
Profil
Tori:
Tak jsem na to ještě nepřišel...jinak ti děkuji, že si mi pomáhala Tori.
Tori
Profil
V PSPadu nevím, používám NetBeans a tam se dá hledat ve vybraných adresářích.

K tomu poli: (všechno se týká jen \models\basket\model.php, a předpokládám, že v tabulce shipping_costs_weight jsou data:

ID | shipping_id | lower_weight | cost |
1  | 1           | 0.0          | 0.0  |
2  | 1           | 15.0         | 20.0 |
, tj. u zboží nad 15 kg se připočítává k poštovnému 20 Kč).
Podle toho, jak se na ř.129 pracuje s polem $weightCosts, by mělo mít strukturu

array(
    0 => array(
        'weight' => 15.0,
        'cost'   => 20.0,
    ),
    1 => array(
        'weight' => 0.0,
        'cost'   => 0.0,
    ),
)
, kdežto metoda getShippingWeightCosts vrací pole ve tvaru:
array(
    15.0 => 20.0,
    0.0 => 0.0,
)
Takže můžete buď změnit metodu getShippingWeightCosts takto:

        $shipping_weights_sql = "SELECT cost, lower_weight FROM shipping_costs_weight WHERE shipping_id={$this->shippingMethodID} ORDER BY lower_weight DESC";
        $this->registry->getObject('db')->executeQuery( $shipping_weights_sql );
        $weights = array();
        while( $data = $this->registry->getObject('db')->getRows() )
        {
            $weights[] = array('weight' => $data['lower_weight'], 'cost' => $data['cost']);
        }
        return $weights;
anebo přepsat ten cyklus okolo řádku 130 takto:

                // dopravné: dle váhy
                // $currentWeight = 0; -- tohle není potřeba, smazat
                // $weightFound = false; -- tohle taky
                
                foreach ($weightCosts as $weight => $cost)
                {
                    if( $contents['product_weight'] >= $weight )
                    {
                        $this->shippingCost = $this->shippingCost + ( $cost * $contents['product_quantity'] );
                        break; 
                    }
                }
Nakonec je to jednodušší úprava, než jsem myslela, ten původní cyklus vypadá strašně složitě.
scorapka
Profil
Tori:
ahaaaaa, už to chápu
Super, už to funguje, děkuji:)

ale ted se snažím odstranit poslední chybu, se kterou si opět nevím rady:(
chyba se vypíše při přidání produktu do košíku, a jak je vidět, košík nefunguje jak má...

Notice: Undefined property: Basket::$isChecked in C:\www\ecom\controllers\basket\controller.php on line 62
Tori
Profil
Koukněte do toho modelu, ona se totiž ta proměnná jmenuje trochu jinak.
↓A jo, díky za opravu, ona je to vlastně soukromá vlastnost.
Rfilip
Profil
62, 130 a 156 řádek souboru C:\www\ecom\controllers\basket\controller.php má být:
if( ! $this->basket->isChecked() == true ) { $this->basket->checkBasket(); }
isChecked není vlastnost ale metoda.
scorapka
Profil
Tak Vám oběma děkuji:) chyba ischecked je vyresena...
ale stejně nejde přidat více jak jedna položka do košíku...což je divné...
teď se snad bude s tím kodem pomocí knihy lépe pracovat, když to ted "zatím" nehlásí zadné chyby.

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: