Dvojité přidávání presenterů

kajinek32
Člen | 35
+
0
-

Ahoj, u nette 3.1 mám problém s načítáním presenterů

Cannot declare class FrontendModule\HomepagePresenter, because the name is already in use

Což zní celkem jasně, že bych tam měl presenter vícekrát. Nicméně hledání v souborech žádný další (ve stejném namespace) nenachází.
Navíc, když tento presenter přejmenuju např. na Homepage2Presenter, chyba se vypíše taky, jen s názvem Homepage2Presenter.

Napadá mě, že se „někde“ dvakrát volá načítání presenterů, nicméně Bootstrap.php mám původní ze sandboxu, stejně tak www/index.php.

HomepagePresenter.php mám v app/FrontendModule/Presenters/ v tomto tvaru:

declare(strict_types=1);
namespace FrontendModule;

/**
 * Description of HomepagePresenter
 *
 */
final class HomepagePresenter extends FrontendPresenter
{
	public function renderDefault()
	{

	}
}

dědí od FrontendPresenteru ve stejné složce

declare(strict_types=1);
namespace FrontendModule;

/**
 * Description of FrontendPresenter
 *
 */
class FrontendPresenter extends \BasePresenter
{
	protected function error403()
	{
		throw new \Nette\Application\ForbiddenRequestException;
	}

	protected function error404()
	{
		throw new \Nette\Application\BadRequestException;
	}
}

a ten dědí od BasePresenteru z app/Presenters/

declare(strict_types=1);

/**
 * Base presenter for all application presenters.
 */
class BasePresenter extends \Nette\Application\UI\Presenter
{
	protected function startup()
	{
		parent::startup();
	}

	protected function beforeRender()
	{
	}
}

v configu mám mapping:

application:
	errorPresenter: Error
	mapping:
		*: App\*Module\Presenters\*Presenter

a v routeru

$router->addRoute('front/<presenter>[/<action=default>]', array(
			'module' => 'Frontend',
			'presenter' => array(
				Route::VALUE => 'Homepage',
				Route::FILTER_TABLE => $presenterTable
			),
			'action' => 'default'
		));

Napadá vás, kde by mohla být chyba? Presentery jsem si zkopíroval z projektu, který byl na nette 2.4, ale porovnával jsem je se sandboxem, a rozdíl jsem nenašel.
Díky

Ondřej Kubíček
Člen | 494
+
0
-

jak vypadá index, boostrap a composer.json ?

kajinek32
Člen | 35
+
0
-

Index.php:

declare(strict_types=1);

require __DIR__ . '/../vendor/autoload.php';

App\Bootstrap::boot()
	->createContainer()
	->getByType(Nette\Application\Application::class)
	->run();

Bootstrap.php

declare(strict_types=1);

namespace App;

use Nette\Bootstrap\Configurator;


class Bootstrap
{
	public static function boot(): Configurator
	{
		$configurator = new Configurator;
		$appDir = dirname(__DIR__);

		//$configurator->setDebugMode('secret@23.75.345.200'); // enable for your remote IP
		$configurator->enableTracy($appDir . '/log');
		error_reporting(~E_USER_DEPRECATED); // note ~ before E_USER_DEPRECATED


		$configurator->setTimeZone('Europe/Prague');
		$configurator->setTempDirectory($appDir . '/temp');

		$configurator->createRobotLoader()
			->addDirectory(__DIR__)
			->register();

		$configurator->addConfig($appDir . '/config/common.neon');
		$configurator->addConfig($appDir . '/config/local.neon');
		$configurator->addConfig($appDir . '/config/settings.neon');

		return $configurator;
	}
}

a composer.json

{
	"name": "nette/web-project",
	"description": "Nette: Standard Web Project",
	"keywords": ["nette"],
	"type": "project",
	"license": ["MIT", "BSD-3-Clause", "GPL-2.0", "GPL-3.0"],
	"require": {
		"php": ">= 7.2",
		"nette/application": "^3.1",
		"nette/bootstrap": "^3.1",
		"nette/caching": "^3.1",
		"nette/database": "^3.1",
		"nette/di": "^3.0",
		"nette/finder": "^2.5",
		"nette/forms": "^3.1",
		"nette/http": "^3.1",
		"nette/mail": "^3.1",
		"nette/robot-loader": "^3.3",
		"nette/security": "^3.1",
		"nette/utils": "^3.2",
		"latte/latte": "^2.9",
		"tracy/tracy": "^2.8",
		"dg/ftp-deployment": "^3.3",
		"ublaboo/datagrid": "^6.6"

	},
	"require-dev": {
		"nette/tester": "^2.3",
		"symfony/thanks": "^1"
	},
	"autoload": {
		"psr-4": {
			"App\\": "app"
		}
	},
	"minimum-stability": "stable"
}
Ondřej Kubíček
Člen | 494
+
0
-

takhle to všechno vypadá oukej. Cache si mazal nebo máš prázdnou že?

Kamil Valenta
Člen | 815
+
0
-

kajinek32 napsal(a):

Nicméně hledání v souborech žádný další (ve stejném namespace) nenachází.

Hledáš v IDE nebo přímo na disku?

kajinek32
Člen | 35
+
0
-

Ondřej Kubíček napsal(a):

takhle to všechno vypadá oukej. Cache si mazal nebo máš prázdnou že?

jj, cache jsem mazal.

Hledal jsem v IDE (VS CODE), ale jak jsem psal, i když ten presenter přejmenuju, chyba se objevuje stále (tj. nejde nejspíš o to, že bych měl dvakrát HomepagePresenter, ale spíš, že se nějak načítá dvakrát…

Šaman
Člen | 2658
+
0
-

Ještě mě napadá, jestli nemáš nějaké načítání presenterů jako služeb v configu. Jinak podobný problém byl se starým RobotLoaderem na PHP8, ale ta hláška zněla jinak a ty máš podle composeru nový. Takže předpokládám, že tímhle to není.

Editoval Šaman (10. 2. 2021 10:36)

Kamil Valenta
Člen | 815
+
0
-

Zkus hledat i přímo na disku, aby se vyloučily nějaké „on save“ rutiny, které mohou v IDE být nastaveny.
Také se podívej do všech 3 neonů, neregistruješ např. presentery ručně?

kajinek32
Člen | 35
+
0
-

Šaman napsal(a):

Ještě mě napadá, jestli nemáš nějaké načítání presenterů jako služeb v configu. Jinak podobný problém byl se starým RobotLoaderem na PHP8, ale ta hláška zněla jinak a ty máš podle composeru nový. Takže předpokládám, že tímhle to není.

No něco takového (načítání i jako služba) bych právě čekal, že to je, nicméně common.neon mám téměř kompletně zakomentovaný.

Zkusil jsem to i na kompletně čistém nette web-project, kam jsem jen vložil FrontendModule/Presenters/HomepagePresenter.php a upravil router.

říkám si, jestli nějak složku app nenačítá composer

"autoload": {
		"psr-4": {
			"App\\": "app"
		}
	},

a zároveň Bootstrap

$configurator->createRobotLoader()
			->addDirectory(__DIR__)
			->register();

ale ani jedno, když vypustím, problém neřeší…

Šaman
Člen | 2658
+
0
-

A co je v routeru v té $presenterTable? Když píšeš, žes to zkoušel na čistém WebProjectu, vložil jsi Presenter a upravil router, tak bych se asi soutředil na ten router (bo ten presenter vypadá nevinně).

Případně tenhle pokus dej někam na Github, ať si ho můžeme proklikat.

kajinek32
Člen | 35
+
0
-

Šaman napsal(a):

A co je v routeru v té $presenterTable? Když píšeš, žes to zkoušel na čistém WebProjectu, vložil jsi Presenter a upravil router, tak bych se asi soutředil na ten router (bo ten presenter vypadá nevinně).

v $presenterTable bylo původně

$presenterTable = [
			'uzivatele' => 'Users',
		];

nicméně, zkusil jsem router ještě zjednodušit podle dokumentace a ani tak to nejde

	$router->addRoute('front/<presenter=Homepage>[/<action=default>]', array(
			'module' => 'Front',
		));

Případně tenhle pokus dej někam na Github, ať si ho můžeme proklikat.

Díky moc, zjednodušenou verzi jsem umístil zde (je bez složek log, temp a vendor, snad se to takhle dělá)

běžná routa /www/ s defaultním textem se spustí v pohodě, problém nastane, když zavolám /www/front/, nebo když do toho app/Presenters/templates/default.latte dám

<a n:href=":Front:Homepage:default">odkaz</a>

Editoval kajinek32 (10. 2. 2021 14:29)

Ondřej Kubíček
Člen | 494
+
+1
-

ten namespace v souboru FrontModule/Presenter/HomepagePresenter.php musí být namespace App\FrontModule\Presenters; ne jenom FrontModule

Editoval Ondřej Kubíček (10. 2. 2021 14:52)

kajinek32
Člen | 35
+
0
-

Ondřej Kubíček napsal(a):

ten namespace v souboru FrontModule/Presenter/HomepagePresenter.php musí být namespace App\FrontModule\Presenters; ne jenom FrontModule

Wow, moc díky! A proč to tak je? Ve všech starých projektech (Nette 2.4) mi to takhle fungovalo…

Ondřej Kubíček
Člen | 494
+
+1
-

ve starých projektech to nebylo autoloadované přes composer psr-4

Šaman
Člen | 2658
+
+1
-

Aha, že nepoužíváš namespace App jsem si všiml, ale nevšiml jsem si, že nemáš tomu přizpůsobené mapování, viz. v úvodním postu v configu mám mapping:

Šaman
Člen | 2658
+
0
-

Ondřej Kubíček napsal(a):

ve starých projektech to nebylo autoloadované přes composer psr-4

To je tím? Předpokládal jsem, že /app si stále načítá RobotLoader a že PSR4 je jen záležitost vendoru?

Ondřej Kubíček
Člen | 494
+
0
-

možná není :D dobře at nekecám, jen jsem si tak tipnul, když mu to na starém projektu šlo

@kajinek32 a na starým projektu jsi měl mapping v konfigu nastavený jak, když ti to fungovalo?

kajinek32
Člen | 35
+
0
-

Ondřej Kubíček napsal(a):

možná není :D dobře at nekecám, jen jsem si tak tipnul, když mu to na starém projektu šlo

@kajinek32 a na starým projektu jsi měl mapping v konfigu nastavený jak, když ti to fungovalo?

překvapivě

*: *Module\*Presenter

jen jsem si toho tady nevšimnul… :)

Šaman
Člen | 2658
+
+2
-

Jinak to

"autoload": {
		"psr-4": {
			"App\\": "app"
		}
	},

je myslím jen pro načtení Bootstrapu. V novém index.php se už neincluduje bootstrap, ale vendor/autoload.php. Rozhodně není nutné držet psr-4 v adresáři app/.

Dodatek: Teď jsem to zkoušel a i se zakomentovaným Robotloaderem (v Bootstrapu) aplikace funguje, dokud drží PSR-4 strukturu. Ale bez ní pak zafunguje RobotLoader, který třídu najde kdekoliv v zadaných adresářích.

P.S. A tím, že ty jsi neměl presentery v namespace App, tak to šlo úplně mimo tebe. To PSR-4 tvoje presentery myslím ani nehledalo.

Editoval Šaman (10. 2. 2021 15:49)

Daewoo
Člen | 34
+
0
-

Jen chci dodat, že jsem právě na to narazil teď na jednom starém projektu a totožná chyba měla příčinu v tom, že jsem při definici dokumentačních templates tříd špatně dodržel jejich pořadí – extendující třída byla v kódu dříve, než byla ona sama definovaná. Čili toto je špatně:

class BannerPresenterEditTemplate extends BannerPresenterCreateTemplate
{
  /** @var string[] */
  public $post;

  /** @var string */
  public $bannerTitle;
}

class BannerPresenterCreateTemplate extends ProtectedPresenterTemplate
{
  /** @var string|null */
  public $bannerImageUrl;
}

A toto dobře:

class BannerPresenterCreateTemplate extends ProtectedPresenterTemplate
{
  /** @var string|null */
  public $bannerImageUrl;
}

class BannerPresenterEditTemplate extends BannerPresenterCreateTemplate
{
  /** @var string[] */
  public $post;

  /** @var string */
  public $bannerTitle;
}

Editoval Daewoo (7. 11. 20:52)