Implementace Nette do starého informačního systému

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

Hezký den,
jsem nadšený z Nette a moc rád bych v něm programoval náš stávající informační systém. Je to moloch – odhaduji kolem 100 000 řádků v php programovaný víc než deset let. Ale dost špatně, částečně neobjektově, žádné html šablony, samý require, žádný MVC model… Nechci ho přeprogramovávat, ale pokračovat ve vývoji smysluplnějším způsobem. Staré funkce nechat umřít, nové programovat v Nette.

Jaký je nejlepší způsob implementace Nette do staré aplikace s vlastní adresářovou strukturou? Tak, abych od teď mohl již programovat pořádně, ale současně používat starý systém, aniž by se uživatelé museli přihlašovat na některé funkce do nového portálu?

Díky za odpověď!
Štěpán

Jan Suchánek
Člen | 404
+
0
-

@stepos to budeš muset hodně oddělit, a nebo budeš muset používat jen časti nette, tzn zapomenout na Presentery i další fičury, nebo jak části Nette používáte na bastl to by mě taky zajímalo.

Spíš si myslím že k bastlu je takovej odpor že se píše vše znova.

Editoval jenicek (27. 4. 2015 20:16)

David Kudera
Člen | 455
+
0
-

Osobně s tím nemám žádnou zkušenost, ale co mě tak napadá:

Záleží to na tom, jestli používáš mod rewite nebo ne. Pokud ne, tak by to mohlo být celkem snadný, jinak nějak složitěji vyřešit bod 3.

  1. Kompletně celý systém přesunout někam do složky www v novém systému.
  2. Přenastavit server apache/nginx, aby koukal do složky www
  3. Tady nějak vymyslet, jak přesměrovat neexistující stránky v novým na ten starý. Někdo nějaký lehký nápad? :-) Jinak by jsi musel chodit třeba přes domena.cz/old/ nebo prostě přes složku, do které by jsi to nahrál
  4. Nachystat si přihlášení v nette (nemyslím formulář, viz bod 5)
  5. Ve starém systému requirnout bootstrap.php, který vrací container, z něj vytáhnout user a pracovat ve starým systému s nette userem
  6. Postupně vše přepsat do nette a starého se co nejdřív zbavit ;-)

No a teoreticky by to mohlo fungovat

stepos
Člen | 36
+
0
-

Díky,
tak nad tím stále přemýšlím. Nakonec to vypadá, že asi pojede starý systém paralelně vedle nového. Je možné si mezi systémy (oddělené složky na stejném serveru) nějak předávat informace, že uživatel je přihlášen?

winner21
Člen | 5
+
0
-

Asi nejlepší budeš mít implementovat si rozhraní IUserStorage https://api.nette.org/…Storage.html tak, aby ti fungovalo se starým systémem.

Filip Procházka
Moderator | 4668
+
+7
-

Viděl jsem tuhle pěknej návod jak převést legacy applikaci pod Symfony. Udělal bych to velice podobně.

  • Založil bych si novej projekt, udělal bych si jeden presenter, kterej bude předávat requesty na starou aplikaci a začal přepisovat.
  • Napsal bych si router který bude zpracovávat url aby kopírovaly schéma adres starého systému, abych si mohl generovat adresy z Nette a přijímat je jako requesty a tunelovat přes ten „legacy“ presenter do starého systému
  • Nový věci rovnou s novýma modelama pod Nette.
  • Pokud to půjde, tak používat DI Container aspoň jako Service Locator ve staré aplikaci.
  • Postupně přepisovat všechno do Nette a mazat starý kód.
  • Profit

:)

kejlicz
Člen | 201
+
0
-

Pro Filip Procházka : Můžeš prosím upřesnit, jak by jsi řešil to " tunelovat přes ten „legacy“ presenter do starého systému".

O něco takového se pokouším, ale nějak mi není jasné, jak by jsi to z toho presenteru přesměrovával na starou URL, protože by to přesměrování opět zachytil htaccess z Nette a poslal by to do Nette. Asi mi něco uniká.

Filip Procházka
Moderator | 4668
+
+1
-

@kejlicz nemáš přesměrovávat, máš tam například includnout scripty ze staré aplikaci, nebo zavolat nějaký starý controller, zkrátka to co by se volalo na té staré url.

kejlicz
Člen | 201
+
0
-

@FilipProcházka Aha, tak to zkusím. Dík.

kejlicz
Člen | 201
+
0
-

Filip Procházka napsal(a):

@kejlicz nemáš přesměrovávat, máš tam například includnout scripty ze staré aplikaci, nebo zavolat nějaký starý controller, zkrátka to co by se volalo na té staré url.

Zasekl jsem se na jedný věci. Stará aplikace používá toto

ve spuštěném scriptu je v globálním prostoru vytvořen objekt pro práci s db

$database = new Database();

soubor s třídou, která používá databázi

class Trida()
{
	public function metoda()
	{
		global $database;
		$database->dotazPole("SELECT ...");
		.....
	}
}

Když spustím přímo script, tak to funguje. Když ale chci script includovat v metodě presenteru, tak class Trida hodí chybu, že $database neni objekt. Pokud to dobře chápu, $database se při přímém spuštění vytvoří v globálním prostoru a pak je přes příkaz global dostupná. Když se spouští přes presenter, již se vytváří jinde a tudíž se k ní přes global nedostanu.

Jak tohle vyřešil bez zásahu do starých scriptů?

Díky za pomoc.

Editoval kejlicz (27. 5. 2015 13:31)

Unlink
Člen | 298
+
+1
-

Ak pridáš global pred tú deklaráciu tak to nepôjde?

global $database = new Database();
kejlicz
Člen | 201
+
0
-

To hodí syntax error, tak jsem to zkusil napsat jinak a to projde a funguje to.

	global $database;
	$database = new Database();

Sice by to znamenalo úpravu původních scriptů, ale pokud to nepůjde jinak, nedá se nic dělat.

Unlink napsal(a):

Ak pridáš global pred tú deklaráciu tak to nepôjde?

global $database = new Database();

Editoval kejlicz (27. 5. 2015 22:17)

stepos
Člen | 36
+
0
-

kejlicz napsal(a):

@FilipProcházka Aha, tak to zkusím. Dík.

Ahoj, můžeš mi prosím tedy poradit, jak jsi to udělal?
Prosím zkus to polopatě, s nette začínám a dost to bolí;)

Mám prostě adresářovou strukturu v nette a pak mám někde jinde adresářovou strukturu původní rozsáhlé aplikace.
Jak a kam nakopírovat původní aplikaci? Do www/puvodni_aplikace?
Jak a kde includovat?
Jak v nové aplikaci tvořit odkazy na starou a naopak ve staré odkazy do nové aplikaci?

Díky, a omlouvám se za možná blbý dotazy, jsem fakt zmaten;)
Š+

stepos
Člen | 36
+
0
-

nebo někdo jiný, prosím, odpovíte na mé otázky?
díky moc
S+

kejlicz
Člen | 201
+
0
-

Měl jsem starou aplikaci v root adresáři. Tam jsem nahrál do podadresáře sandbox Nette. Pak jsem si v htaccess nasměroval požadavky na scripty do podadresáře Nette. V Nette jsem si vytvořil routy, které přesně popisovali staré URL adresy a ty nasměroval na LegacyPresenter. Tohle asi nejde nějak obecně popsat. Záleží jakou máš strukturu aplikace a URL.
Ukázka routy

		$router[] = new Route('volna-mista/<okres>[/index.php?page=<page>]', array(
		    'presenter' => 'Legacy',
		    'action'    => 'vm'
		));

takže jsem požadavky např. na domena.cz/volna-mista/jicin/ poslal na tuhle action v LegacyPresenteru

	public function actionVm($okres, $page = NULL)
	{
		include "../volna-mista/jicin/index.php";
		die;
	}

Odkazy jsem zatím nedělal, ale pokud budou dobře routy, budeš normálně v nette generovat URL klasicky a měly by odpovídat staré struktuře.

stepos
Člen | 36
+
0
-

Díky moc.
A jde to i opačně?

Mít adresářovou strukturu Nette, ve které psát novou aplikaci košér.

Do adresáře /vendor hodit celou původní složku se starým systémem s requiry atd.
Tzn. /vendor/old/index.php

V RouterFactory doplnit řádek se starým systémem

public static function createRouter()
	{
		$router = new RouteList();
		//stary systém
		$router[] = new Route('old', 'Legacy:old');
		$router[] = new Route('<presenter>/<action>[/<id>]', 'Homepage:default');
		Route::$defaultFlags = Route::SECURED;
		return $router;
	}

a presenter:

<?php

namespace App\Presenters;

use Nette,
	App\Model;


/**
 * Legacy presenter. - do starého systemu
 */
class LegacyPresenter extends BasePresenter
{

	public function renderDefault()
	{
//		$this->template->anyVariable = 'any value';
	}

	public function actionOld()
	{
			include "../vendor/old/index.php";
			die;
	}
}

Problém, že to tak nefunguje.
Teda, když zadám odkaz localhost/newapp/old
Routing debugger praví, že byl použit správný router, nicméně se nic nevykreslí, prázdná obrazovka (ani echo „ahoj“ nefunguje…).
Začínám, tak se omlouvám, ale tápu, tápu, tápu.
Děkuji

Editoval stepos (4. 6. 2015 13:21)

stepos
Člen | 36
+
0
-

Prosím, nevíte, někdo jiný, kde by mohla být chyba?
Díky

stepos
Člen | 36
+
0
-

Tak asi problém je v tom adresáři, kam jsem nasypal původní systém. Vendor/old nefunguje. když je to /www/old, tak ano.
Škoda, že to laděnka, nehlásí jako chyba. Zobrazuje se prázdná obrazovka.

stepos
Člen | 36
+
0
-

Ahoj, tak jsem se po několika měsících konečně dopracoval k implementaci Nette do starého rozsáhlého informačního systému. Zvolil jsem nakonec adresářovou strukturu Nette, ve které píšu nové funkce, do starého systému přistupuju přes router a presenter, který mi includuje staré soubory /viz výše/.
Mám ten starý systém v adresářové struktuře Nette ve složce www/old/index.php…

Právě počítám s tím, že uživatelé se budou přihlašovat přes formuláře tvořené v Nette. Pokud bude potřeba vstoupit do starého systému, rád bych mu předal informaci, že uživatel je přihlášený, aby se nemuselo zadávat znovu heslo do starého systému, ale současně, aby se dalo přihlašovat do starého po staru

Chtěl bych zkusit do starého systému načíst informace o přihlášení z Nette, nevíte, kudy nejlépe?
Napadlo mě načíst si identitu $user, ale mám problémy se jmennými prostory, ať chci cokoliv použít z Nette, píše mi to Class Nette\Object nenalezena.
Pokud použiju namespace Nette, nefungují mi zase staré třídy, které to nemají.
Existuje nějaký způsob, jak toto vyřešit? Abych nemusel ve všech souborech starých tříd definovat namespace, protože teď žádný nemají.

Pak leda přistupovat k identitě přes sessions, ve starém systému se nějak dostat do sessions, kde je uložena identita – to by snad mohlo jít, protože je vnořený v nette, čili ve stejné doméně na stejném počítači ve stejném prohlížeči… Ty sessions by pak sloužily i k dalšímu předávání informací a signálů mezi systémy. Děkuji za případné postrčení.

romiix.org
Člen | 343
+
0
-

Ako máš nainštalované Nette? Akú verziu PHP používaš?

stepos
Člen | 36
+
0
-

php 5.6.17, nette přes composer

rozhodl jsem se jít cestou přes to sessions, nette při autentizaci uloží do session informaci o tom, že už je ověřený, a starý systém si informaci načte a už hesla neřeší.

Problém mám trochu s DI, zase v tom plavu,a to jsem myslel, že to už chápu. Mám vlastní autenticator:

Authenticator.php

namespace Model;
use Nette\Security as NS;

class Authenticator extends \Model\BaseRepository implements NS\IAuthenticator
{
	const
		TABLE_NAME = 'i_users'...
		...


	 /** @var Nette\Http\Session */
    private $session;

    /** @var Nette\Http\SessionSection */
    private $sessionSection;

	/**
	 * Performs an authentication.
	 * @return Nette\Security\Identity
	 * @throws Nette\Security\AuthenticationException
	 */
	public function authenticate(array $credentials)
	{
		list($username, $password) = $credentials;

		$row = $this->database->table(self::TABLE_NAME)->where(self::COLUMN_NAME, $username)->fetch();
		if (!$row) {
			throw new NS\AuthenticationException('Jméno nebo heslo není zadáno správně.', self::IDENTITY_NOT_FOUND);

		} elseif (!NS\Passwords::verify($password, $row[self::COLUMN_PASSWORD_HASH])) {
//			\Tracy\Debugger::dump(NS\Passwords::hash($password));
			throw new NS\AuthenticationException('Jméno nebo heslo není zadáno správně.', self::INVALID_CREDENTIAL);

		} elseif (NS\Passwords::needsRehash($row[self::COLUMN_PASSWORD_HASH])) {
			$row->update(array(
				self::COLUMN_PASSWORD_HASH => Passwords::hash($password),
			));
		}

		$roles_arr = $this->database->table(self::ROLES_NAMES_TABLE)->select(self::COLUMN_ROLE_NAME)->where(self::COLUMN_ROLE_ID,$this->database->table(self::USER_ROLES_TABLE)->select(self::COLUMN_ROLES_ROLE)->where(self::COLUMN_ROLES_USER, $row[self::COLUMN_ID]))->fetchPairs(NULL, self::COLUMN_ROLE_NAME);
//		\Tracy\Debugger::dump($roles_arr);
		$arr = $row->toArray();
		unset($arr[self::COLUMN_PASSWORD_HASH]);
		//nastavíme starému systému identitu

		$this->authenticateOldSystem($username);

		return new NS\Identity($row[self::COLUMN_ID], $roles_arr, $arr);
	}
/**
 *
 * @param \Model\Nette\Http\Session $session
 * získá přístup k sessions a uloží starému systému informaci o tom, že uživatel byl autentifikován v nette
 */


	private function authenticateOldSystem($identity_name, \Nette\Http\Session $session)
	{
        $this->session = $session;

        $this->sessionSection = $session->getSection(self::OLD_SYSTEM_SESSION_SECTION);
		$this->session->{self::OLD_SYSTEM_SESSION_VARIABLE}=$identity_name;

	}

BaseRepository.php

namespace Model;
use Nette;
abstract class BaseRepository extends Nette\Object {

/** @var Nette\Database\Context */
 protected $database;

public function __construct(Nette\Database\Context $database) {
    $this->database= $database;
 }
}

Hází mi to chybu:
Argument 2 passed to Model\Authenticator::authenticateOldSystem() must be an instance of Nette\Http\Session, none given, called in /home/www/ikona/app/model/Authenticator.php on line 55 and defined

Teď jsem se zamotal. Dělá se to tak, že Authenticator.php bude mít svůj konstruktor, kde si získá závislost na \Nette\Http\Session. Nebude se to tlouct se zděděným konstruktorem s BaseRepository, kde se získává závislost na databázi? Někde jsem tu četl, že se to moc dělat nemá, protože ty konstruktory se tlučou, ale nevím, přečetl jsem toho hodně.:) Přijde mi nesystémové získávat závislost už v baseRepository a dědit ji. BaseRepository ji nepotřebuje…

Díky. Š+

romiix.org
Člen | 343
+
-1
-

Nemá to nič s DI.

Voláš $this->authenticateOldSystem($username);, pri čom definíciu metódy máš

private function authenticateOldSystem($identity_name, \Nette\Http\Session $session)

Asi by si mal zmeniť kód na:

private function authenticateOldSystem($identity_name)
{
    $this->sessionSection = $this->session->getSection(self::OLD_SYSTEM_SESSION_SECTION);
    $this->sessionSection->{self::OLD_SYSTEM_SESSION_VARIABLE}=$identity_name;
}

Nejak detailne som to neskúmal.

stepos
Člen | 36
+
0
-

Díky, ale já právě potřebuji to Nette\Http\Session nějak dostat do toho autentikatoru a nevím jak? ;-)

romiix.org
Člen | 343
+
0
-

Cez konštruktor:

public function __construct(\Nette\Http\Session $session) {
    $this->session = $session;
}

V konfiguračnom config.neon stačí:

- Model\Authenticator

Následne to Autowiring zariadi.

Editoval romiix.org (3. 2. 2016 15:03)