Jak na výpis z databáze a vložení dat? (počítadlo návštěvnosti)
- Zuben45
- Člen | 268
Dobrý den, potřeboval bych pomoct, tvořím si vlastní návštěvnost a nemůžu přijít na to jak to udělat v nette, normálně to není problém, ale tady fakt netuším :(
mám tabulku pocitadlo s kolonkamy ip,datum,cas
A teď nastává problém, z návodů jsem vůbec nepochopil jak bych to mohl použít.
V app/model jsem si vytvořil soubor Navstevnost.php
<?php
namespace Pocitadlo;
use Nette;
use Nette\Database\Connection;
class Pocitadlo extends Table
{
$database = new Connection($dsn,$user,$password);
$ip = $_SERVER['REMOTE_ADDR'];
public function getOnline()
{
$database->query("SELECT * FROM pocitadlo WHERE datum=NOW() and ip='$ip'");
}
}
a zařadil ho také jako službu
services:
database: @Nette\Database\Connection
authenticator: Authenticator
navstevnost: Navstevnost( 'pocitadlo' )
prosím pomohl by mi někdo ? Díky moc
Jinak normálně to mám nějak takhle:
function pocitadlo()
{
$ip = $_SERVER["REMOTE_ADDR"];
$dotaz = mysql_query("SELECT * FROM pocitadlo WHERE datum=NOW() AND ip='$ip'");
if (mysql_num_rows($dotaz))
{
$dotaz2 = mysql_query("UPDATE pocitadlo SET cas='".time()."' WHERE datum=NOW() AND ip='$ip'");
}
else
{
$dotaz2 = mysql_query("INSERT INTO pocitadlo (ip, datum, cas) VALUES('$ip',NOW(),'".time()."');");
}
}
function navstevy()
{
$navstevnici = array();
$dotaz = mysql_query("SELECT count(*) FROM pocitadlo");
list($navstevnici['celkem'])=mysql_fetch_array($dotaz);
$dotaz = mysql_query("SELECT count(*) FROM pocitadlo WHERE datum=NOW()");
list($navstevnici['dnes'])=mysql_fetch_array($dotaz);
$dotaz = mysql_query("SELECT count(*) FROM pocitadlo WHERE datum=NOW() AND cas>='".(time()-180)."'");
list($navstevnici['online'])=mysql_fetch_array($dotaz);
# vratime pole
# $navstevnici['celkem'] = pocet navstev celkem
# $navstevnici['dnes'] = pocet navstev za dnesni den
# $navstevnici['online'] = pocet navstev, ktere nejsou starsi jak 3 minuty
return $navstevnici;
}
pocitadlo();
$navstevnici = navstevy();
echo "ONLINE: $navstevnici[online]<br>
DNES: $navstevnici[dnes]<br>
CELKEM: $navstevnici[celkem]<br>";
EDIT: Kdyby mi někdo vysvětlil základní tvorbu výpisu a vkládání dat z/do db (pro NF, normálně to umím ;) ), tak bych byl moc rád
Editoval Zuben45 (17. 8. 2013 13:18)
- Oli
- Člen | 1215
Řekl bych, že to nepoužíváš dobře. Já bych na to šel zhruba takhle:
neon:
services:
database: @Nette\Database\Connection
authenticator: Authenticator
pocitadlo: Pocitadlo\Pocitadlo(@httpRequest) // Předá třídě počitadlo objekt httpRequest
navstevnost: Navstevnost( @pocitadlo ) // Předá třídě Návštěvnost objekt pocitadlo
Presenter:
protected $pocitadlo;
protected $navstevnost;
function __construct(\Pocitadlo\Pocitadlo $pocitadlo, Navstevnost $navstevnost)
{
$this->pocitadlo = $pocitadlo;
$this->navstevnost = $navstevnost;
public function actionDefault()
{
$online = $this->pocitadlo->getOnline();
$pocet = $online->count(); // Pocet záznamů v tabulce pro zadaný výraz
}
}
pocitadlo:
namespace Pocitadlo;
class Pocitadlo extends \Nette\Object
{
private $_db;
private $httpRequest;
function __construct($httpRequest, \Nette\Database\Connection $db)
{
$this->_db = $db;
$this->httpRequest = $httpRequest;
}
public function getOnline()
{
return $this->_db->table('pocitadlo')->where(
'datum = ? && ip = ?',
new \Nette\DateTime(), $this->httpRequest->getRemoteAddress()
);
}
public function delete($id)
{
$this->_db->table('pocitadlo')->wherePrimary($id)->delete();
}
public function editOrAdd($id, Array $arr)
{
if($id == null)
{
$lastInsert = $this->_db->table($this->table)->insert($arr);
return $lastInsert;
} else
{
$lastUpdate = $this->_db->table($this->table)->where("id = ?", $id)->update($arr);
return $lastUpdate;
}
}
}
Psal jsem to z fleku, nemusí to být přesně. Nevím jestli to je úplně nejlepší postup, ale řekl bych, že je správnější než tvůj :-)
víc by ti mohlo mopomoct: Databáze & ORM, Getting started (Getting started je i časky, ale neaktualizuje se)
//Edit: Vkládání, editace, mazání v db
Editoval Oli (17. 8. 2013 13:38)
- Zuben45
- Člen | 268
Supr, už to trochu začínám chápat, a když pak chci vypsat $pocet, tak to udělám pls jak ?
jinak, vypisuje mi to chybu
Class Navstevnost used in service 'navstevnost' has not been found or is not instantiable
Třída Návštevnost použita ve službě ‚navstevnost‘ nebyla nalezena nebo není …, nevím jak to vyřešit :(
Editoval Zuben45 (17. 8. 2013 15:02)
- ViPEr*CZ*
- Člen | 818
Jen doplním pár lepších (jednodušších) zápisů. Prvně bych _db klidně pojmenoval jen db.
->where('datum = ? && ip = ?',
new \Nette\DateTime(), $this->httpRequest->getRemoteAddress()
toto je přehlednější podle mě do dvou where
->where('datum', new \Nette\DateTime())
->where('ip', $this->httpRequest->getRemoteAddress());
Toto
$this->_db->table('pocitadlo')->wherePrimary($id)->delete();
lze takto
$this->_db->table('pocitadlo')->get($id)->delete();
->where(„id = ?“, $id) je totéž jako ->where(„id“, $id)
na porovnání $id == null bych raději použil $id === null
- Zuben45
- Člen | 268
Teď jsem zkoušel to použít s pomocí Repository jak jsou v návodu, počet online a celkem jde, jen mi nejde vkládat data, kod mam tento:
NavstevnostRepository.php
<?php
namespace Todo;
use Nette;
/**
* Tabulka navstevnost
*/
class NavstevnostRepository extends Repository
{
private $httpRequest;
function __construct($httpRequest)
{
$this->httpRequest = $httpRequest;
}
public function CelkemNavstevnost()
{
$CelkemNav = $this->findAll();
return $CelkemNav->count();
}
public function getOnlineNavstevnost()
{
return $this->findBy(array('datum' =>"Now()"))->count();
}
public function createNavstevnost()
{
$ip = $this->httpRequest->getRemoteAddress();
if($ip === null)
{
return $this->getTable()->insert(array(
'ip' => $ip,
'datum' => new \DateTime()
));
}
}
}
<?php
/**
* Homepage presenter.
*/
class HomepagePresenter extends BasePresenter
{
private $taskRepository;
private $navstevnostRepository;
protected function startup()
{
parent::startup();
$this->taskRepository = $this->context->taskRepository;
$this->navstevnostRepository = $this->context->navstevnostRepository;
}
public function renderDefault()
{
$this->template->tasks = $this->taskRepository->findIncomplete();
$pocet = $this->taskRepository->findIncomplete();
$this->template->pocet = $pocet->count();
$ncelkem = $this->navstevnostRepository->CelkemNavstevnost();
$this->template->navstevnostcelkem = $ncelkem;
$nonline = $this->navstevnostRepository->getOnlineNavstevnost();
$this->template->navstevnostonline = $nonline;
}
}
ale teď mi to hází chybu
Call to a member function table() on a non-object
Editoval Zuben45 (17. 8. 2013 19:17)
- Oli
- Člen | 1215
actionDefault totiž nemá v repository co dělat, pokud teda to není nějaká tvoje metoda. ActionDefault a renderDefault jsou metody Presenteru: MVC aplikace & presentery.
presenter:
protected $navstevnost;
function __contruct(Todo\NavstevnostRepository $navstevnost)
{
$this->navstevnost = $navstevnost;
}
// ip zjistíš pres httpRequest, nenní potřeba ho předávat parametrem.
public function actionDefault()
{
$>ip = $this->httpRequest->getRemoteAddress();
if($this->ip == null)
{
$Insert = $this->navstevnost->insert(array('ip' => $ip,'datum' => 'NOW()');
}
}
}
model:
public function insert(Array $arr)
{
$lastInsertId = $this->db->table('nazev_tabulky')->insert($arr);
return $lastInsertId;
}
Lepší než přes context je předávat si databazi přes konstruktor. V mém prvním příspěvku jsem ti to psal i s nastavením v configu, jak by to mělo fungovat
- Zuben45
- Člen | 268
no teď mi ale zase hází chybu s db
Argument 1 passed to Todo\Repository::__construct() must be an instance of Nette\Database\Connection, instance of Nette\Http\Request given, called in C:\xampp\htdocs\nette framework 2\sandbox\temp\cache\_Nette.Configurator\_-967fb136ca1226356bf18e9532238eb7.php on line 178 and defined
13: public function __construct(Nette\Database\Connection $db)
<?php
/**
* Homepage presenter.
*/
class HomepagePresenter extends BasePresenter
{
private $taskRepository;
private $httpRequest;
protected $navstevnost;
function __construct(Todo\NavstevnostRepository $navstevnost)
{
$this->navstevnost = $navstevnost;
$this->httpRequest = $httpRequest;
}
protected function startup()
{
parent::startup();
$this->taskRepository = $this->context->taskRepository;
}
public function renderDefault()
{
$this->template->tasks = $this->taskRepository->findIncomplete();
$pocet = $this->taskRepository->findIncomplete();
$this->template->pocet = $pocet->count();
$ncelkem = $this->navstevnost->CelkemNavstevnost();
$this->template->navstevnostcelkem = $ncelkem;
$nonline = $this->navstevnost->getOnlineNavstevnost();
$this->template->navstevnostonline = $nonline;
}
public function actionDefault()
{
$ip = $this->httpRequest->getRemoteAddress();
if($ip == null)
{
$Insert = $this->navstevnost->insert(array('ip' => $ip,'datum' => 'NOW()'));
}
}
}
<?php
namespace Todo;
use Nette;
/**
* Tabulka navstevnost
*/
class NavstevnostRepository extends Repository
{
public function CelkemNavstevnost()
{
$CelkemNav = $this->findAll();
return $CelkemNav->count();
}
public function getOnlineNavstevnost()
{
return $this->findBy(array('datum' =>"Now()"))->count();
}
public function insert(Array $arr)
{
$lastInsertId = $this->getTable->insert($arr);
return $lastInsertId;
}
}
Editoval Zuben45 (17. 8. 2013 19:34)
- Oli
- Člen | 1215
Myslím, že jsi použil ten config co jsem ti psal na začátku. Tahle
hláška by tomu odpovídala. Jde o to, že v tom configu říkáš,
třídě Todo\Repository předej objekt httpRequest
. Jestli to
chápu dobře, tak databáze se tam vloží automaticky. A konstruktor by teda
měl vypadat takhle:
__construct(Nette\Http\Request $httpRequest, Nette\Database\Connection $db)
- Zuben45
- Člen | 268
Oli napsal(a):
Myslím, že jsi použil ten config co jsem ti psal na začátku. Tahle hláška by tomu odpovídala. Jde o to, že v tom configu říkáš,
třídě Todo\Repository předej objekt httpRequest
. Jestli to chápu dobře, tak databáze se tam vloží automaticky. A konstruktor by teda měl vypadat takhle:__construct(Nette\Http\Request $httpRequest, Nette\Database\Connection $db)
ty jo, tak já už tomu frameworku snad už neporozumím :/ , ten konstruktor patří do presentu že ? U mě v HomepagePresenter.php
neměl by spíš vypadat takhle ?
function __construct(Todo\NavstevnostRepository $navstevnost, Nette\Http\Request $httpRequest, Nette\Database\Connection $db)
a v tom configu mám to na tu návštěvnost
navstevnostRepository: Todo\NavstevnostRepository(@httpRequest)
ale i tak mi to hází stejnou chybu
Editoval Zuben45 (17. 8. 2013 22:25)
- Oli
- Člen | 1215
Ne. V configu rikas: navstevnostRepository dostane zavislost httpRequest.
Connection dostane jako bonus automaticky.
V presenteru reknes, pro tenhle presenter chci tridu NavstevnostRepository,
kterou si ulozis do napr $this->navstevnost. Tahle promenna ted obsahuje
objekt NavstevnostRepository. V cofigu jsi mu predal do konsttruktoru ten
httpRequest a connection. Ted si to musis v te tride NavstevnostRepository jen
vyzvednout.
Je to takhle trochu pochopitelny? :)
- Zuben45
- Člen | 268
Oli napsal(a):
Ne. V configu rikas: navstevnostRepository dostane zavislost httpRequest. Connection dostane jako bonus automaticky.
V presenteru reknes, pro tenhle presenter chci tridu NavstevnostRepository, kterou si ulozis do napr $this->navstevnost. Tahle promenna ted obsahuje objekt NavstevnostRepository. V cofigu jsi mu predal do konsttruktoru ten httpRequest a connection. Ted si to musis v te tride NavstevnostRepository jen vyzvednout.Je to takhle trochu pochopitelny? :)
takže, v NavstevnostRepository musím mít
private $httpRequest;
$this->httpRequest = $httpRequest;
a
$ip = $this->httpRequest->getRemoteAddress();
?
EDIT: nejlepší to je ukázat na příkladu, mohl bys prosímtě ? děkuji
Editoval Zuben45 (17. 8. 2013 22:59)
- Oli
- Člen | 1215
To zalezi na tobe, kde tu IP ziskas. Pokud mas ale v configu
navstevnostRepository: NavstevnostRepository(@httpRequest)
Tak musi byt v konstruktoru prvne $httpRequest a az potom $db.
Priklad, snad dobre, je muj prvni prispevek. Presne takhle by meli vypadat konstruktory presenteru a NavstecnostRepository…
Editoval Oli (17. 8. 2013 23:11)
- Zuben45
- Člen | 268
Oli napsal(a):
To zalezi na tobe, kde tu IP ziskas. Pokud mas ale v configu
navstevnostRepository: NavstevnostRepository(@httpRequest)
Tak musi byt v presenteru prvne $httpRequest a az potom $db.
Priklad, snad dobre, je muj prvni prispevek. Presne takhle by meli vypadat konstruktory presenteru a NavstecnostRepository…
$db musím taky, když to dělám přes Repository.php ?
- Oli
- Člen | 1215
Jsem se upsal, editoval, ale ty jsi byl rychlejsi :)
V presenteru ma konstruktor jen NavstevnostRepository nebo PocetRepository, zalezi na tom, co chces. A az pocet\NavstevnostRepository ma db pripadne httpRequest,jestli jsi mu ho v configu nastavil.
V tom prvnim mem prispevku to je nazorne ;)
- Zuben45
- Člen | 268
Už mi všechno jde
<?php
namespace Pocitadlo;
class Pocitadlo extends \Nette\Object
{
private $_db;
private $httpRequest;
function __construct($httpRequest, \Nette\Database\Connection $db)
{
$this->_db = $db;
$this->httpRequest = $httpRequest;
}
public function getOnline()
{
return $this->_db->table('navstevnost')->where(
'datum = ? && ip = ?',
new \Nette\DateTime(), $this->httpRequest->getRemoteAddress()
);
}
public function getCelkem()
{
return $this->_db->table('navstevnost')->count();
}
public function addNavstevnik()
{
$ip = $this->httpRequest->getRemoteAddress();
$existIp = $this->_db->table('navstevnost')->where('ip = ?',$ip)->count();
if($existIp == 0)
{
$lastInsert = $this->_db->table('navstevnost')->insert(array('ip' => $ip,'datum' => new \DateTime()));
return $lastInsert;
}
}
}
<?php
/**
* Homepage presenter.
*/
class HomepagePresenter extends BasePresenter
{
private $taskRepository;
protected $pocitadlo;
function __construct(\Pocitadlo\Pocitadlo $pocitadlo)
{
$this->pocitadlo = $pocitadlo;
}
public function actionDefault()
{
$online = $this->pocitadlo->getOnline();
$onlinepocet = $online->count(); // Pocet záznamů v tabulce pro zadaný výraz
$this->pocitadlo->addNavstevnik();
}
public function renderDefault()
{
$online = $this->pocitadlo->getOnline();
$onlinepocet = $online->count(); // Pocet záznamů v tabulce pro zadaný výraz
$this->template->navstevnostonline = $onlinepocet;
$this->template->navstevnostcelkem = $this->pocitadlo->getCelkem();
}
}
jen teď nevím jak se dá přičítat nebo odečítat od DateTime (chtěl bych příčíst 60min, kvůli hodnotě online, protože teď jak to mám, to započítává jen když je někdo přesně v tu sekundu minutu… na stránce)
Mám tento příkaz:
$cas = $this->_db->table('navstevnost')->where('ip = ? && cas >= ?',$ip,time()-180)->count();
elseif($cas == 1)
{
$lastUpdate = $this->_db->table('navstevnost')->where("ip = ?", $ip)->update(array('datum' => Date("Y-m-d"),'cas' => Date("H:i:s")));
return $lastUpdate;
}
ale po uplynutí 3 minut se nic neděje :(
Editoval Zuben45 (18. 8. 2013 16:06)