Podstrčení jiného obrázku pokud dotazovaný neexistuje

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

Zdravím,
velice jednoduchá věc. Jelikož jsem si tu toho dost přečetl, tak jsem zjistil, že bych neměl do .htaccess vůbec lést. Takže bych chtěl poprosit o pomoc s nastavením routeru. A to tak. Pokud napr. uploads/photos/teachers/1.jpg nebo uploads/photos/students/3.jpg neexistuji, tak se nahradí prohlížeči podstrčí images/incognito.jpg. O to jaký http kód odešlě mi nejde může klidně poslat 302(myslím že by to bylo i lepší).

Zkoušel jsem hodně kombinací a zkončil u téhle.

<?php
	public function createRouter()
	{
		$router = new RouteList();
		$router[] = new Route('<presenter>[-<page>]/<action>[/<id>]', 'Homepage:default');
                $router[] = new Route('uploads/photos/teachers/<photo>', array(
		    'presenter' => 'Homepage',
		    'action'	=> 'default',
                    'photo'     => 'incognito.jpg'
                ));
		return $router;
	}
?>

Problém je v tom, když si otevřu samotný obrázek co existuje např. http://neco.cz/…achers/1.jpg tak URl zůstane stejná a obrázek se zobrazí. Ale když dám např. http://neco.cz/…achers/2.jpg, (tento obrázek neexistuje) tak se mi zobrazí hlavní stránka a a URL se změní na http://neco.cz/?… a já chci http://neco.cz/…ncognito.jpg

MartinitCZ
Člen | 580
+
0
-

Tohle nemá v routě co dělat.
Přesun logiku do akce:

function actionDefault($photo)
{
....
	if (file_exists($file = SLOZKA_FOTEK . '/' . $photo)) {

		return $file;

	} else {
		return SLOZKA_FOTEK . '/incognito.jpg';
	}
....
}
holantomas
Člen | 55
+
0
-

Tak to se omlouvám, ale to je podle mě blbost. Proč kopírovat stejný kód 20× když můžu v .htaccess napsat jeden řádek ? Tomuhle přesně jsem se chtěl vyhnout.

enumag
Člen | 2118
+
0
-

Moje představa je přibližně následující:

  • všechny obrázky budou v jedné složce (nebo několika málo složkách), např. /upload
  • pokud obrázek existuje tak se prostě zobrazí, Nette se vůbec nedostane ke slovu (nelze použít v případech kdy je vyžadována autorizace pro zobrazení obrázku)
  • pokud obrázek neexistuje, odchytne to přibližně takováhle routa:
$router[] = new Route('uploads/<photo .+>', array(
	'presenter' => 'Images',
	'action'    => 'default'
));

Presenter pak dle parametru photo rozezná jaké rozměry má obrázek mít (to by se dalo řešit už v route a presenter by dostal $dimensions či $width a $height) a vrátí výchozí obrázek v potřebných rozměrech, případně na něj přesměruje pomocí redirectUrl (sám nevím která možnost je lepší – zda vrátit rovnou nebo přesměrovat).

Editoval enumag (30. 9. 2013 17:33)

holantomas
Člen | 55
+
0
-

Nad tím vytvořit čistý presenter pro zobrazení obrázku jsem taky přemýšlel … a zatím se to jeví jako nejlepší nápad

frosty22
Člen | 373
+
0
-

Akorát tedy do .htaccess sáhnout budeš muset, jelikož tento řádek by ti neposlal request například s příponou .jpg na index.php, ale stačí jen odstranit ty příslušné přípony:

RewriteRule !\.(pdf|js|ico|gif|jpg|png|css|rar|zip|tar\.gz)$ index.php [L]
frosty22
Člen | 373
+
0
-

Jo a jenom alternative – né vždy to jde, záleží oč se přímo snažíš, ale občas je hezčí toto řešit přes JS/CSS. Minimálně je to méně náročné na server, pokud se jedná o zatíženější web, či pokud se jedná o vyšší množství obrázků, které nemusí existovat.

Buď přes CSS nastavit background v tom bloku rovnou ten blank obrázek a když se načte obrázek, tak ho překryje, či případně přes JS navěsit událost onError na tagy IMG a když se nenačte obrázek nahradit za cestu k neexistujícímu.

holantomas
Člen | 55
+
0
-

Nápad s CSS se mi líbí děkuji za inspiraci. JS se mi nelíbí je to zavádějící, uživatel vypne JS a potom tam bude mít hnusné čtverečky.

petr.pavel
Člen | 535
+
0
-

CSS pozadí: Ty čtverečky tam v IE budeš mít taky, protože tvůj obrázek bude nad pozadím. Tudíž i ten [x] bude nad pozadím.

Jako další alternativu nabízím definovat přes .htaccess vlastní 404 dokument – adresu nějaké akce v Nette. Ta potom vrátí/přesměruje na ten incognito-123×456.jpg.

Tím mimo jiné také zajistíš, aby se vracela 404 a prohlížeče/vyhledávače tak pochopili, že obrázek opravdu neexistuje – ne, že byl přesunut (302).

holantomas
Člen | 55
+
0
-

petr.pavel napsal(a):
adresu nějaké akce v Nette. Ta potom vrátí/přesměruje na ten incognito-123×456.jpg.

Tím mimo jiné také zajistíš, aby se vracela 404 a prohlížeče/vyhledávače tak pochopili, že obrázek opravdu neexistuje – ne, že byl přesunut (302).

Ono je to ale stejné řešení jako uvádí enumag

holantomas
Člen | 55
+
0
-

enumag napsal(a):

Moje představa je přibližně následující:

  • všechny obrázky budou v jedné složce (nebo několika málo složkách), např. /upload
  • pokud obrázek existuje tak se prostě zobrazí, Nette se vůbec nedostane ke slovu (nelze použít v případech kdy je vyžadována autorizace pro zobrazení obrázku)
  • pokud obrázek neexistuje, odchytne to přibližně takováhle routa:
$router[] = new Route('uploads/<photo .+>', array(
	'presenter' => 'Images',
	'action'    => 'default'
));

Presenter pak dle parametru photo rozezná jaké rozměry má obrázek mít (to by se dalo řešit už v route a presenter by dostal $dimensions či $width a $height) a vrátí výchozí obrázek v potřebných rozměrech, případně na něj přesměruje pomocí redirectUrl (sám nevím která možnost je lepší – zda vrátit rovnou nebo přesměrovat).

Jak v tomto případě vyřešit view? Tedy mám udělaný presenter. Z adresy uploads/image.jpg?width=170&height=170 se mi to zroutuje na Noimage:default. Jak teď udělat to aby se mi vykreslil jen samotný nahrazující obrázek ? Aktuálně se mi vykresluje celý layout stránky.

enumag
Člen | 2118
+
0
-

Presenter::sendResponse(new FileResponse)

holantomas
Člen | 55
+
0
-

enumag napsal(a):

Presenter::sendResponse(new FileResponse)

Můj presenter

<?php
class NoimagePresenter extends BasePresenter {

    protected function startup() {
        parent::startup();
    }

    public function actionDefault() {

        $this->sendReponse(new \Nette\Application\Responses\FileResponse($this->context->params['wwwDir'] . '/images/incognito.jpg'));

    }
}
?>

A laděnka vyhazuje:
`Nette\MemberAccessException

Call to undefined method NoimagePresenter::sendReponse().`

Přižemž se zkoušel i $this->presenter->sendRes… Ale vždy to samé přitom netbeans mi nabízí v obou případech tuto funkci.

vvoody
Člen | 910
+
0
-

sendReSponse

holantomas
Člen | 55
+
0
-

vvoody napsal(a):

sendReSponse

OMG, tak to se omlouvám :D

Tak všem zúčastněným děkuji. Vše funguje tak jak má.