Kdyby/AOP nefunguje, jak má

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Azathoth
Člen | 495
+
0
-

Zdravím,

mám problém s Kdyby/AOP. Vytvořil jsem si ExampleAspect, který něco napíše vždy před metodou a po metodě a potom HelloGenerator, který volám Presenterem a metody ExampleAspectu se spouští před jeho metodami a po jeho metodách. Vše vypadá následovně.
ExampleAspect:

<?php
class ExampleAspect extends Nette\Object{

    function __construct() {

    }

    /**
     * @Aop\Before("method(\App\Model\HelloGenerator->[hello|goodDay])")
     */
    public function sayBeforeHello(Aop\JoinPoint\BeforeMethod $before) {
        echo("This is before method ".$before->getTargetReflection()->getName().".</br>");
    }

    /**
     * @Aop\After("method(\App\Model\HelloGenerator->[hello|goodDay])")
     */
    public function sayAfter(Aop\JoinPoint\AfterMethod $after) {
        echo("This is after method ".$after->getTargetReflection()->getName().".</br>");
    }

}
?>

HelloGenerator:

<?php
class HelloGenerator extends Nette\Object{

    function __construct() {

    }

    public function hello() {
        echo("hello.</br>");
    }

    public function goodDay() {
        echo("good day.</br>");
    }
}
?>

HomepagePresenter:

<?php
class HomepagePresenter extends BasePresenter {

    /**
     * @var \App\Model\HelloGenerator
     * @inject
     */
    public $helloGenerator;

    public function renderDefault() {
        echo("start testing AOP</br>");
        $this->helloGenerator->hello();
        $this->helloGenerator->goodDay();
        echo("end testing AOP</br>");
    }
?>

Když mám v ExampleAspectu v anotaci @Aop\After("method(\App\Model\HelloGenerator->hello())") vše běží normálně a vypíše se

start testing AOP
This is before method hello.
hello.
This is after method hello.
This is before method goodDay.
good day.
This is after method goodDay.
end testing AOP

Ovšem pokud chci, aby se metoda v ExampleAspectu spustila po každé metodě helloGeneratoru, napíšu @Aop\After("method(\App\Model\HelloGenerator->*())") a vyskočí na mne:
User Notice

Possible problem: you are sending a HTTP header while already having some data in output buffer. Try OutputDebugger or start session earlier.

 ...\www\index.php:8	source  Nette\Application\Application-> run ()

1: <?php 2: 3: // Uncomment this line if you must temporarily take down your site for maintenance. 4: // require '.maintenance.php'; 5: 6: $container = require __DIR__ . '/../app/bootstrap.php'; 7: 8: $container->getService('application')->run(); 9:

Další problém mám s pověšením metody na nějakou metodu presenteru.
Když přidám do ExampleAspectu metodu

<?php
    /**
     * @Aop\After("method(\App\Presenters\HomepagePresenter->renderDefault)")
     */
    public function sayAfterPresenter(Aop\JoinPoint\AfterMethod $after) {
        echo("This is after method renderDefault.</br>");
    }
?>

tak na mne vyskočí Nette\Application\BadRequestException #404

Page not found. Missing template '…\wamp\www\klubduch\temp\cache\templates\Homepage\default.latte'.
 ...\www\index.php:8	source  Nette\Application\Application-> run ()

1: <?php 2: 3: // Uncomment this line if you must temporarily take down your site for maintenance. 4: // require '.maintenance.php'; 5: 6: $container = require __DIR__ . '/../app/bootstrap.php'; 7: 8: $container->getService('application')->run(); 9:

Zkoušel jsem promazat cache a nic.

Upřímně nevím, co dělám špatně a jak si s tím poradit. Jsem vděčný za všechny rady.

Editoval Azathoth (11. 8. 2014 23:34)

David Matějka
Moderator | 6445
+
0
-
  1. nesouvisi primo s tim aop, zkus zapnout session autoStart na true a uvidis :)
  2. jo, tohle je problem. nevim, jestli ma @FilipProcházka nejaky jednoduchy reseni. Ono nette defaultne hleda sablony relativne k presenteru. A kdyby/aop zdedi ten presenter a prida tam potrebny kod. Ten vygenerovany presenter ulozi do cache, takze cesta je jina. Slo by to asi vyresit prekrytim formatTemplateFiles a formatLayoutTemplateFiles v presenteru, konkretne tak, ze ctrl+c, ctrl+v a $this->getReflection()->getFileName() nahradit za $this->getReflection()->getParentClass()->getFileName()
Filip Procházka
Moderator | 4668
+
0
-

@matej21 dobrý nápad, dalo by se kontrolovat, jestli poděděná třída má Nette\Object a pokud ano, tak vždy překrýt metodu getReflection()

public static function getReflection()
{
	return new Reflection\ClassType('... doplnit jmeno tridy kterou dedim... ');
}

a pokud je to PresenterComponent

public static function getReflection()
{
	return new PresenterComponentReflection('... doplnit jmeno tridy kterou dedim... ');
}
Azathoth
Člen | 495
+
0
-

Tak jsme z 50% funkční!

  1. nastavil jsem

session:
autoStart: true
a bohužel to pořád nefunguje.

  1. v basePresenteru jsem overridnul metody jak jsi poradil a funguje to! Jenom se trochu paranoidně zeptám: nebude to dělat někdy v budoucnu bordel u presenterů, kde AOP nepoužívám? Nebo mám ten override dělat jenom u těch presenterů, na které budu věšet AOP metody?
Filip Procházka
Moderator | 4668
+
0
-

a bohužel to pořád nefunguje.

Hlásí to pořád to samé? nepadají do logu nějaké chyby? Použij ten output detector a najdi co se vypisuje.

Nebo mám ten override dělat jenom u těch presenterů, na které budu věšet AOP metody?

Přesně tak.

Azathoth
Člen | 495
+
0
-

Hlásí pořád to samé. Pokud se output detectorem myslí nějaký addon nebo externí program, tak vůbec netuším jaký a pokud se myslí to, co hlásí Tracy, tak jsem se pokoušel z toho něco vyčíst, ale bohužel jsem z toho nedokázal vydolovat nějaké kloudné informace.
A do logu nic nepadá.
Zde je výpis Tracy (bohužel je to trochu nevzhledné, ale nevím, jak zkopírovat tu stránku nějak přesně, aniž bych to dělal přes printscreeny).
http://justpaste.it/…dybyAOPError
Bohužel vše v Tracy vyskakuje někde uvnitř nette, ve stacktrace jsem neviděl jedinou svou třídu.

Budu vděčný za každou radu.

Azathoth
Člen | 495
+
0
-

Tak jsem konečně našel OutputDebugger, píše toto:

...\app\model\ExampleAspect.php:36
"This is after method __construct.</br>" (38)
...\vendor\tracy\tracy\src\Tracy\templates\bluescreen.phtml:31
"<!DOCTYPE html><!-- "' --></script></style></pre></xmp></table></a></abbr></address></article></aside></audio></b></bdi></bdo></blockquote></button></ ... " (949)
...\vendor\tracy\tracy\src\Tracy\templates\bluescreen.css:294
"/**
 * Debugger Bluescreen
 *
 * This file is part of the Tracy (https://tracy.nette.org)
 * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
 */ ... " (5788)
...\vendor\tracy\tracy\src\Tracy\templates\bluescreen.phtml:48
"	</style>
	<script>document.documentElement.className+=' js'</script>
</head>
<body>
<div id="tracyBluescreen">
	<a id="tracyBluescreenIcon" href="# ... " (366409)
...\vendor\tracy\tracy\src\Tracy\templates\bar.phtml:27
"
<!-- Tracy Debug Bar -->
<script>
(function(onloadOrig) {
	window.onload = function() {
		if (typeof onloadOrig === 'function') onloadOrig();
	 ... " (417119)

Pochopil jsem tedy z tohoto správně, že ExampleAspect se ozve po metodě __construct ještě dříve než zbytek nette a to hází error?

Azathoth
Člen | 495
+
0
-

Tak vyřešeno! Když u nějaké třídy nnapojuji aspekt na všechny metody pomocí ->*, tak pouze nesmím použít echo(), ale cokoli jiného funguje.

Filip Procházka
Moderator | 4668
+
+3
-

echo přece s nette nikdo nepoužívá, používá se barDump, který dumpuje do panelu a nerozbije ti http hlavičky :)

Azathoth
Člen | 495
+
0
-

Teprve s nette začínám a v https://doc.nette.org/cs/ se o nepoužívání echo nic nepsalo. Ale děkuji za tip, naučím se používat barDump.