update to Nette 2.3 – change in DB access
- jik
- Member | 149
Hello,
I get problem with update to Nette 2.3. I use (since Nette 2.0) this
mechanismus using methods defined in models (typically):
$select = $this->context->users->getUser($this->uid);
and in Nette 2.3 it does not work. Yes here is chance to set it in config.neon, but now I am going to do a lot of changes and it would be the best to rewrite access to DB. Please, write me a right new syntax of that operation. Thank you.
- jik
- Member | 149
I have problem with this concept.
- I feel, that this concept does not respect MVC model. In this concept I have access to data (model) in the same layer as presenter. But it is only problem of ‘ideology’, although it is very handy.
- My application consists from about 60 tables and presenters (total about 50) accesses to more tables. Concept with separated models is very handy, as access to table is only in one place.
By DI probably I shall write connection into every presenters for all tables used in that presenter – it means a lot of duplicate code, or write (simplicity) all connection into some parrent of presenters.
- David Matějka
- Moderator | 6445
No, you only change the way you are getting dependencies. Now you are using DIC as a service locator:
$this->context->users->getUser($this->uid);
instead, you require that service “users” (which is probably some class
of type App\Model\User
or something similar) using DI
class MyPresenter extends UI\Presenter
{
private $userModel;
public function __construct(\App\Model\User $user)
{
$this->userModel = $user;
}
public function actionDefault()
{
$this->userModel->getUser($this->uid);
}
}
Also, read this article explaining basic concept of DI
- David Matějka
- Moderator | 6445
It means, that models remain without changes and in presenter
that's right, there will probably be no change in your model
I must create constructor for each used tables?
Basically yes, but you can also use inject properties or inject methods (see the article mentioned in my first reply). But constructor is preferred (except BasePresenter where inject properties/methods are better – they prevent constructor hell)
- jik
- Member | 149
Thank you, it works well. But do not understand, how works with more tables. :
class HomepagePresenter extends BasePresenter {
private $okres, $kraj;
public function __construct(\App\Model\Kraj $array) {
$this->kraj = $array;
}
public function renderDefault() {
$kraj = $this->kraj->getRecord(19);
$kraje = $this->kraj->getAll();
}
}
- Barvoj
- Member | 60
Use more parameters in constructor:
class HomepagePresenter extends BasePresenter
{
private $okres, $kraj;
public function __construct(\App\Model\Okres $okres, \App\Model\Kraj $kraj)
{
$this->okres = $okres;
$this->kraj = $kraj;
}
public function renderDefault() {
$kraj = $this->kraj->getRecord(19);
$kraje = $this->kraj->getAll();
}
}
Last edited by Barvoj (2016-03-29 11:36)
- jik
- Member | 149
Thank you very much. And perhaps last question: I cannot access to database in parent presenter, I get response “Call to a member function … on null”. I think, that in parent presenter the constructor is not run:
namespace App\Presenters;
use Nette;
use App\Model;
abstract class BasePresenter extends Nette\Application\UI\Presenter {
private $describe;
public function __construct(\App\Model\Describe $describe) {
$this->describe = $describe;
}
protected function startup() {
parent::startup();
$describe = $this->describe->getRecord(1);
}
}
namespace App\Presenters;
use Nette;
use App\Model;
class HomepagePresenter extends BasePresenter {
private $okres, $kraj, $table, $u;
public function __construct(\App\Model\Kraj $kraj, \App\Model\Okres $okres) {
$this->kraj = $kraj;
$this->okres = $okres;
}
protected function startup() {
parent::startup();
}
public function renderDefault() {
$kraj = $this->kraj->getRecord(27);
$okresy = $this->okres->getKraj(27);
$this->template->nazev = $kraj->nazev;
$this->template->okresy = $okresy;
}
}
- David Matějka
- Moderator | 6445
You are not calling parent constructor.
It is better to use inject methods or inject properties in a BasePresenter.
- pata.kusik111
- Member | 78
jik wrote:
Thank you very much. And perhaps last question: I cannot access to database in parent presenter, I get response “Call to a member function … on null”. I think, that in parent presenter the constructor is not run:
namespace App\Presenters; use Nette; use App\Model; abstract class BasePresenter extends Nette\Application\UI\Presenter { private $describe; public function __construct(\App\Model\Describe $describe) { $this->describe = $describe; } protected function startup() { parent::startup(); $describe = $this->describe->getRecord(1); } } namespace App\Presenters; use Nette; use App\Model; class HomepagePresenter extends BasePresenter { private $okres, $kraj, $table, $u; public function __construct(\App\Model\Kraj $kraj, \App\Model\Okres $okres) { $this->kraj = $kraj; $this->okres = $okres; } protected function startup() { parent::startup(); } public function renderDefault() { $kraj = $this->kraj->getRecord(27); $okresy = $this->okres->getKraj(27); $this->template->nazev = $kraj->nazev; $this->template->okresy = $okresy; } }
Missing parent::__construct()
call in the child Presenter.
- jik
- Member | 149
It is OK when I write:
class HomepagePresenter extends BasePresenter {
private $okres, $kraj;
public function __construct(\App\Model\Describe $desc, \App\Model\Kraj $kraj, \App\Model\Okres $okres) {
parent::__construct($desc);
$this->kraj = $kraj;
$this->okres = $okres;
}
...
}
But in this case I must write into child presenters all tables from parent presenter and it is not very nice. I'll want to open another table in the parent presenter and it results in rewrite all child presenters.