update to Nette 2.3 – change in DB access

Notice: This thread is very old.
jik
Member | 144
+
0
-

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.

David Matějka
Moderator | 6354
+
0
-

You should use dependency injection

jik
Member | 144
+
0
-

I have problem with this concept.

  1. 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.
  2. 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 | 6354
+
+1
-

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

jik
Member | 144
+
0
-

I do not test it now, only teoretically: It means, that models remain without changes and in presenter I must create constructor for each used tables?

David Matějka
Moderator | 6354
+
0
-

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 | 144
+
0
-

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
+
+1
-

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 | 144
+
0
-

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 | 6354
+
+2
-

You are not calling parent constructor.

It is better to use inject methods or inject properties in a BasePresenter.

pata.kusik111
Member | 78
+
-1
-

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 | 144
+
0
-

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.

jik
Member | 144
+
0
-

huh… injection is terrible magic, but works well! Thank you!