Is it possible to instantiate a Controller class within another controller class using the Yii Framework
For example I have controller Student and and method actionShow of class student I have the following
public function actionShow()
{
$student = $this->loadStudent();
$studentContact = new Student_ContactController;
//Checking if there was an ajax request
if(Yii::app()->request->isAjaxRequest){
$this->renderPartial('show',array(
'student'=>$student,
));
}else{
$this->render('show',array(
'student'=>$student,
));
}
}
Is it possible to include this action in the method $studentContact = new Student_ContactController;
Getting errors, :-(
I do not know the Yii framework, but as it is an MVC framework, then getting data should be part of the model, therefore $studentContact should be an instance of a model, not of a controller.
If you really want to instanciate an instance of a controller then call the constructor with brackets:
$studentContact = new Student_ContactController();
Related
I'm building a MVC PHP framework from scratch, and I have some problems regarding the model layer.
What I have right now is a relatively basic MVC implementation, here's my entry point ( index.php ):
//get the URI
$uri = isset($_SERVER['REQUEST_URI'])
? $_SERVER['REQUEST_URI']
: '/';
//Initializes the request abstraction from URI
$request = new request($uri);
//getting the view class from the request
$viewFactory = new viewFactory();
$view = $viewFactory->getView($request);
$view->setDefaultTemplateLocation(__DIR__ . '/templates');
//getting the data mapper from the connection string
$connectionString = "mysql:host=localhost;dbname=test;username=root;";
$dataMapperFactory = new dataMapperFactory($connectionString);
$dataMapper = $dataMapperFactory->getDataMapper();
$modelFactory = new modelFactory($dataMapper);
//getting controller and feeding it the view, the request and the modelFactory.
$controllerFactory = new controllerFactory();
$controller = $controllerFactory->getController($request,$view,$modelFactory);
//Execute the necessary command on the controller
$command = $request->getCommand();
$controller->{$command}($request);
//Produces the response
echo $view->render();
I think this is self explanatory, but if you don't get something, or if you think I did some horrible mistake, feel free to tell me.
Anyway, the modelFactory is in charge of returning whatever model the controller could require. I now need to implement the "model research" logic, and in my opinion there's two ways of doing it:
First way: Implementing a modelSearch class containing all research logic, then make my model inheriting it ( like in Yii2 ). I don't like this method because it would make me instantiate some model and have it returning other instance of itself. So I have the same model instantiated once to research and once ( or more ) with all datas, and no use of search methods.
so my controller would look like that:
class site extends controller{
public function __construct($view, $modelFactory){
parent::__construct($view, $modelFactory);
/* code here */
}
public function index()
{
$searchModel = $this->modelFactory->buildModel("exemple");
$model = $searchModel->get(["id"=>3])->one();
$this->render('index',['model' => $model]);
}
}
Second way: Implementing a modelSearch class containing all research logic, then in the entry point, instead of instantiating the modelFactory, I could istantiate the modelSearch, and feeding it the dataMapper. Then I give the modelSearch to the controller, and the controller would get any model he wants by asking the modelSearch ( which would use the modelFactory to instantiate models and return them ), like that:
class site extends controller{
public function __construct($view, $searchModel){
parent::__construct($view, $searchModel);
}
public function index()
{
$model = $this->searchModel->get("exemple",["id"=>3])->one();
$this->render('index',['model' => $model]);
}
}
This way seems more correct to me, but has the disadvantage of having to call the modelSearch class to return any model, even empty ones.
Thoughts?
TL;DR: modelSearch: Do I use it as independant tool to get models, or do I make models inherit from it?
Searching logic should be within the model itself as the MVC describes model,view & controller. Model should have only one responsibilities that is work with database itself. While as controller should be responsible for manipulating of data and passing the data.
First read any MVC pattern PHP framework as CI, CakePHP and YII, and then you will see the model (how it works with database). and you can create there self model searching logic and you can see YII framework for best searching logic in model and usability in controllers.
#1
Class controller {
$customer = Model\customer::find($id);
}
#2
Class controller {
$customer = new Model\customer;
$customer = $customer->data($id);
}
Class Model {
public function data($id) {
return self::find($id);
}
}
I'm new in larava, I got a question about MVC query.
I saw many people put query inside of controller like #1
I usually like to put query inside of model class.
any suggestion?
According to me MVC means - Model View Controller.
In a general language Model should contain the Database Query related stuffs whereas in View you should always use variables to populate view data and at last Controller is generally for catching the requests and send the response by doing some logical functionality on request.
<?php
namespace App\Models;
class ExampleModel
{
// All the database related methods like - all, paginate, find, where, etc would goes in the model...
}
In case of Views
<html>
...
YOUR_CONTENT_HERE
...
</html>
and in case of Controller,
<?php
namespace App\Controllers;
class ExampleController
{
public function index()
{
$request = request()->all();
... do some logical work here ...
return response($data);
}
}
Thats what MVC code structure would be like - in my opinion
Hope this helps!
It's ok to use the model's find() method directly to retrieve an entity.
If you are developing a larger application, you should, however, consider moving all the logic into your own classes. The controller should just collect the input from the http request, session etc. and call a method on a service to do the actual work. That way your code is not glued to a controller action or route.
I want to assign generic variables to the view renderer outside the controller action.
I'd prefer to handle this in the module class bootstrap.
My question is, how do I create a view model in the module class bootstrap that can be shared with the controller .
My end result is to have the ability to add variables to the view model before we create a new instance of one inside the controller action.
Here's something I started on, however i cannot add variables to the declared viewmodel and have it persist to the controller's new instance of a view model.
Is there a way to create a view model and have it set as the renderer before dispatch.
Here's something i started but if i can get it in the module class bootstrap instead id prefer that.
I dont think this works though.
class BaseController extends AbstractActionController
{
protected $viewModel;
public function onDispatch(MvcEvent $e)
{
$this->viewModel = new ViewModel([
'module' => 'modulename',
'controller' => 'controllername',
'action' => 'actionname'
]);
parent::onDispatch($e);
}
}
In the Module.php you have access to the event object.
In this event you can set some variables like this :
$event->getViewModel()->setVariable('isAdmin', $isAdmin);
$event->getViewModel()->setVariable('var', $var);
$event->getViewModel()->setVariable('form', $form);
$event->getViewModel()->setVariable('uri', $uri[0]);
If you want to test more you can also do :
$widgetTemplate = new ViewModel();
$widgetTemplate = $widgetTemplate->setTemplate('widget/container');
$event->getViewModel()->addChild($widgetTemplate, 'widget');
Those variables are available in your layout.phtml. I didn't test if it's the same viewModel available in your controller, give me a feedback if you test this solution.
For a variable defined in module.php, you can also use the Zend\Container\Session component to modify it in controllers
I Need some advice, as I'm still a bit new to Laravel and MVC in general. I'm coding a small web application that presents some data on the page, fetched from a remote API. However, the page already has a controller to it. The other controller I will be using I'm hoping I can also reuse it for other pages. I'm pretty stuck here.
So the two controllers
HomeController.php
ApiController.php
The HomeController is the original controller, which gets the view file (home.blade.php), with some other data that's being loaded from the controller.
With the ApiController, I want to fetch the api (json) results, do some changes and then load those changes to the HomeController as well. The changes would be like an array of methods and such that's being loaded to the view.
So How can I load both controllers inside of the same view?
First of all controllers doesn't get loaded inside view instead, you should load a view from a controller and to make the remote request for an API call you don't need to use another controller but you may use it if you have other use of API and need a separate controller. The flow is something like this:
class HomeController extends BaseController {
public function index()
{
// make the api call/remote request
// modify the returned data
// load the view
}
}
Let's rewrite it:
class HomeController extends BaseController {
protected $apiService = null;
public function __construct(ApiService $apiService)
{
$this->apiService = $apiService;
}
public function index()
{
// make the api call/remote request
$apiData = $this->apiService->makeRequest();
// modify the returned data.... then...
// load the view
return View::make(...)->with('apiData', $apiData);
}
}
So, it seems clear that, you should use the API related process in a separate class as a service, maybe a model or a simple repository class and inject it to your HomeController then use it from the controller.
Do all the API stuffs in ApiService and call methods of that class from the HomeController, in this case you may implement the ApiServiceRepository as a concrete class by implementing an interface, i.e. ApiService. So, finally it could be like this:
interface ApiService {
public function makeRequest();
}
// Implement the interface in concrete class
class ApiServiceRepository implements ApiService {
public function makeRequest()
{
// $data = make remote request
// return $data
}
}
Use the class HomeController with __construct as given above and add a IoC binding like:
App::bind('ApiService', 'ApiServiceRepository');
So, you don't have to worry about the dependency injection in the constructor of your HomeController.
BTW, to use a method from another controller, for example ApiController from HomeController you may use something like this:
$apiController = App::make('ApiController');
// Call any method of "ApiController" class/object
$apidata = $apiController->makeCallToMethod();
You may also check this article for understanding the use of repository pattern in Laravel.
I'm little bit confused. I want to build my own framework just to learn how everything works not that I will use it for big projects.
I have a FrontController class and this class has the route functionality inside.
Functions to set/get Parameters for Controller
Functions to set/get Actions (methods) from Controller
Functions to parse the requested URI and return proper controller if exists if not returns default controller which is IndexController.
Run() method that does the following:
public function run() {
$method = new \ReflectionMethod($this->controller, $this->action);
$numParams = $method->getNumberOfParameters();
//fill missing parameters with null values
if (count($this->params) != $numParams) {
$tempArray = array_fill(0, $numParams, null);
$this->setParams($this->params + $tempArray);
}
$controller = new $this->controller;
$userInstance = User::getInstance();
//just creates a model based on the controller name by default its
//Index.php (model)
$model = DB::createModel($this->getControllerName());
//run _before before any function
$controller->_before($model, $userInstance);
call_user_func_array(array($controller, $this->action), $this->params);
return;
}
now I've seen tutorials and they use BaseController and each Controller then extends from this basecontroller. My controllers do not extend from FrontController.
My question is Do i need a separate class for Routing? DO i need to split FrontController into
BaseController
Route.php
Model.php
Since run() function actually passes the model and user object to the controller.
One basic principle to keep in mind is the Single Responsibility Principle. A well designed class has exactly one responsibility.
So yes. You will need to separate the routing and all other responsibilities.
Also note that the model must be considered a layer and not a class or object. The model layer is a collection of classes (data access, services). In fact, your User class should be considered part of that layer.
Here's an article which can help you understand the MVC pattern a bit better.