I created a function like e.g. getAllCitiesOfLocations(). This functions delivers me an aggregation of cities. I want to have this function reusable like e.g. for the index function of the ServiceController. Inside the index function, I want to call the function getAllCitiesOfLocations() to fetch the information and later on deliver it to the view.
However, I red, that it is not proper style to call a function from another controller. Furthermore, I red, that I should create a helper class. Unfortunately, when I search for information how to create a helper class, I only find information about creating helper classes for the views. Can you tell me
1.) Where I should put the function, that should be called by different controllers if needed, and
2.) How I can call the function later on when it is not inside the same controller?
public function getAllCitiesOfLocations(){
$cities = DB::table('locations')
->select('city')
->groupBy('city')
->get();
return $cities;
}
You can use helper class like this
namespace App\Services;
class Helper {
public static function getAllCitiesOfLocations(){
// Code goes here
}
}
I usually store it inside app/services folder, but you can have it anywhere you like. Then in your controllers, you can access them like this:
App\Services\Helper::getAllCitiesOfLocations();
You can also let laravel autoload this class for you by adding it to your aliases array found in config/app.php
'Helper' => App\Services\Helper::class
Then when calling methods from your Helper class, you simply
Helper::getAllCitiesOfLocations();
This kind of function would belong in a model, not a controller. Generally if its dealing with the database, you put things in models.
What you want to do is have a Model. You can then use that Model in any controller you want to.
Please read https://requiremind.github.io/a-most-simple-php-mvc-beginners-tutorial/ to start working in MVC model.
Related
In my current implementation of the MVC design pattern (demonstrated using PHP and CodeIgniter):
Let's say I have a "page" located at "www.mysite.com/blue/page" that is ultimately generated by the following (greatly simplified) files:
/libraries
session_lib.php
/controllers
/red
/white
/blue
page.php
/models
/red
/white
/blue
funky_class.php
page_model.php
/views
/red
/white
/blue
page.php
And here's an easy to understand controller:
// FILE: /controllers/blue/page.php
// Get some paramaters from URL
$params = $this->input->get();
// Use a library to do some stuff with these params with a session
$this->load->library('session_lib');
$this->session_lib->store_in_session($params);
// Use a very page specific class to do some funky stuff with the params
$this->load->model('blue/funky_class');
$funkified_params = $this->funky_class->funkify($params);
// Pass params to a model
$this->load->model('blue/page_model');
$data['output_from_db'] = $this->page_model->get_some_output_from_db($funkified_params);
// Send to view
$this->load->view('blue/page', $data);
And now the question...
What is the best procedure for these "funky" little page specific classes that don't interact with the database? In this example I store the little class with the models, and in some cases might just add additional methods inside the model class to do the funky stuff. Is this good practice? Or should the library and funky class both go inside the model so the controller is even skinnier (however the model might be used in other places without the need for sessions and funkiness)?
I would use a helper.
When a helper is loaded, that function will be available in the global scope so you can call it anywhere.
They're great for small, stand-alone functions that do only one thing that is not necessarily related to code in a model or library
Helpers especially excel for me when converting things between one format or another (slugify, convert_timezone, change_query_string) or doing little tasks that you don't want to think about (force_ssl, is_image, uri_string)
funkify() seems like an appropriate helper function that may prevent a lot of repeated code.
Here's the codeigniter documentation page on them: http://ellislab.com/codeigniter/user-guide/general/helpers.html
If you're in a situation where the helper function is so specific it will be only used in one place, you can still use a helper. Name the helper after your controller, page_helper.php for example.
page_helper.php
function funkify($params) {
// do funky stuff
return $funky_params;
}
then in your controller:
class Page extends CI_Controller {
public function __construct() {
parent::__construct();
$this->load->helper('page');
}
public function page() {
// do stuff
$funky_params = funkify($params);
// do more stuff
$this->load->view('blue/page', $data);
}
I have no excuse for it, but sometimes if I am in a situation where I need a razor specific function that will only be used on one location (say, a controller) ever, I will put it right in the controller's file. You can paste a function outside of the class definition and it will act like a helper and be available globally (as long as that controller is loaded). You can also define functions inside of a view. Yucky, but possible. I don't like to do it often because it's unusual and not expected (by myself or other developers)
I want to verify if file/folder exists on my CI system (not system folder), can i do it from controller or I need create a method on my model to do it?
It's basically a matter of choice. You can define your function in both your model and controller. But if you want to use it over and over from different controllers, then better define a new model and put that function in it. I'd define model which is to be used by many controllers that is having some common-general methods. Just to keep things apart and maintaining them later. Helpers are also a way to keep things separate.
You have got many way for this :
You can create an helper and put your function like verify()
You can create a private function into your controller like
private function _verify() { }
enjoy !
Best to add this function in a codeigniter helper or in a library class(if you are fan of OOP). Load this automatically with autoload.php and call from wherever you need it.
This might be a bit hard to comprehend so I apologize in advance if this is not clear enough.
I'm writing my own MVC framework and am once again stuck.
I am in the process of writing the controller classes for the framework. Basically this is how it works:
Instantiate class coreController which extends abstract class
coreController sets controller to be loaded by interpreting query string
query string values stored in variables
other variables assigned values
new controller is loaded
new controller checks if an action object needs to be instantiated.
new actioncontroller is loaded
action controller checks if it is the final object required.
action controller is returned as an object to be referenced during the rest of the script.
generic $controller->method() can be called and references final controller loaded.
Another overview:
coreController
pageController
pageControllerActionAdd
return as object to start
$controller->something(); //References pageControllerActionAdd
Esentially what I want to be able to do is be able enter a url like:
http://www.mywebsite.com/page/modify/
and have the script pull up the PageModifyController as a variable so I can execute it's methods.
If you can tell me a better method for what I am doing please go ahead. You don't have to write any code, just the idea would be great. It is just that the way I am currently doing is very confusing and hard to debug. I will end up with multiple nested objects and I don't like the concept of that.
I've been reading a lot of other source code and found that it too can be quite sophisticated.
I actually created a framework that works along the lines you are trying to implement. I think what you are missing is a RoutingHandler class. Routing is the physical manipulation of the URL, which tells your application which Controller to load, and which Action to run.
In my world I also have Modules, so the basic routing scheme is
Module -> Controller -> Action
These three items map to my URI scheme in that fashion. Variables can be appended also like so...
http://www.domain.com/module/controller/action/var1/val1/var2/val2
So, what happens after the URI is parsed, and control is passed over to the appropriate controller and action? Let's make some code up to demonstrate a simple example...
<?php
class indexController extends Controller {
protected function Initialize() {
$this->objHomeModel = new HomeModel;
$this->objHeader = new Header();
$this->objFooter = new Footer();
$this->objHeader
->SetPageId('home');
}
public function indexAction() {
$this->objHeader->SetPageTitle('This is my page title.');
}
// other actions and/or helper methods...
}
?>
In the Initialize method, I'm setting some controller-wide stuff, and grabbing an instance of my Model to use later. The real meat is in the indexAction method. This is where you would set up stuff to use in your View. For example...
public function randomAction() {
$this->_CONTROL->Append($intSomeVar, 42);
}
_CONTROL is an array of values that I manipulate and pass onto the View. The Controller class knows how to find the right template for the View because it is named after the Action (and in a sibling directory).
The Controller parent class takes the name of the action method and parses it like so...
indexAction -> index.tpl.php
You can also do some other fun stuff here, for example...
Application::SetNoRender();
...would tell the Controller not to render inside a template, but just complete the method. This is useful for those situations where you don't actually want to output anything.
Lastly, all of the controllers, models, and views live inside their own Module directory like so...
my_module
controllers
indexController.class.php
someotherController.class.php
:
:
models
HomeModel.class.php
:
:
templates
index.tpl.php
someother.tpl.php
:
:
I can have as many Modules as I need, which means I can separate functionality out by Module and/or Controller.
I could go on, but I'm writing this from memory, and there are some wrinkles here and there, but hopefully this gives you food for thought.
can anyone tell me how do i access model from view in codeigniter?
Load a model on the controller
$this->load->model('yourmodel');
Assign this model to a var like this
$data['model_obj'] = $this->yourmodel;
and assign this data array to your view template
Use $model_obj object on the view template for calling model methods
$model_obj->some_method()
Hope this helps ...
See the thread:
View Calling a Model
By the way why do you need to access the model from the view, you can send the model data to the view from the controller too which is the usual and better approach.
As a good note, keep your processing logic out of the view, you should use controller instead.
CodeIgniter's $this->load->model() returns absolutely nothing. Look at it: system/libraries/Loader.php.
This will output absolutely nothing:
$model = $this->load->model('table');
print_r($model);
And this next example will give you the fatal error Call to a member function some_func() on a non-object:
$model = $this->load->model('table');
$model->some_func();
It doesn't matter whether that function even exists, $model is not an object.
The thing to do is have a method in your model that returns data, then call that function and pass the results to your view file:
$this->load->model('table');
$data = $this->table->some_func();
$this->load->view('view', $data);
PS: How is the only answer you've accepted the absolute wrong thing to do?
You can use following code:
$ci = &get_instance();
$ci->load->model('your_model');
$ci->your_model->your_function();
Note: You have to call your model in your controller. Its working fine
In cases when you want to access a model function from within a shared view , you don't have to load the needed model in every controller that will call that view. you can load the model inside the view itself by using the following code :
$ci =&get_instance();
$ci->load->model(model_name);
$ci->model_name->function_name();
in older versions of codeigniter the following code used to work :
$this->load->model('model_name');
model_name::function();
but when tested on CI 3.1.9 it throw the following error
Message: Undefined property: CI_Loader::$model_name_model
Note: I use this technique in template views (sidebar, menus ...etc) which is not used everywhere in my application , if you want to access a model from anywhere in your application considre loading this model globally by adding it to the autoload array in application/config/autoload.php
Since $model is not an object, you can make a call to the model "table" using "::" scope resolution operator, which can call the function of the class itself without any object instance.
$this->load->model('table');
table::some_funct();
Note: you also need to make the function "some_funct" static inside your model "table".
Hey. You can access from view to models the same mode as you access on its controller. Remember that the view access to models that import its controller.
in the original UML I've seem for MVC architecture, view calls methods in model..
http://www.as3dp.com/wp-content/uploads/2010/02/mvc_pope_krasner.png
..but in practice with PHP apps, because there is no persistence to track state changes in objects between requests (or at least not efficiently), I find it better to keep all model method calls in controller and pass the result to view if possible.
you can add your model's name to config -> autoload model
$autoload['model'] = array('model_name');
this success for me
You can access basicly a method from view in codeingiter.
public function index()
{
$this->load->model('persons');
$data['mydata'] = $this->persons->getAllSessionData();
$this->load->view('test_page', $data);
}
in view
print_r ($mydata);
my function returned an array.
Here is a quick overview of the controllers functionality in most of the application:
controller loads a specific model, gets data from it, formats the data and passes the formatted data to the view.
Now there is a search page, which needs to do a search query over entire database (all models). It needs to show each type of data in its particular formatted output on a single page as a list.
The problem:
The search controller can do the search, dynamically load model for each record type, and get the data from model. Problem comes when the data needs to be formatted. I am trying to load the specific controller from the search controller, which is causing problems.
What to do?
PS: I tried using the 'Wick' library, but it fails when the controller's format function tries to use its own model and session object, giving errors about call to a member on a non-object.
After much refactoring and trial/error, It appears that the best way to achieve the above is this way:
Keep the format function in the base controller from which all other controllers are derived. The format options are passed to the function along with the data object as arguments.
Make a static function in each derived controller, which returns the formatting options of the data.
Inside the search controller (which is itself derived from the base controller), for each data object, call the static function of its particular controller which returns the data formatting options, then use that to format the object for the view.
I guess I can say I will stick to using the model only for interaction with the database, and let everything else be done by controller. If anyone has a better solution still, I am all ears.
It sounds like you want to use the Factory design pattern
Make this a library:
class MyModelFactory {
static public function Factory($data) {
$type = key($data);
return new $type($data);
}
}
now, in your controller, you can do something like this:
$model = MyModelFactory::Factory(array($_REQUEST['model'] => $_REQUEST));
and now you have an object of whatever model was specified in $_REQUEST['model']. Be sure to take any security precautions you may need for your application to assure the user has permissions to use the model that they request
Now, since you want to be using common methods and stuff, your models should probably be based off an abstract class / interface.. so instead of
class MyModelOne extends Model {
// stuff
}
You probably want something like this, to ensure your required methods will always be available:
abstract class MyAbstractModel extends Model {
protected $search_params;
public function __construct($data = array()) {
$search_params = $data['search_params'];
}
protected function GetSearchParameters() {
return $this->search_params;
}
abstract public function GetData();
abstract public function GetColumns();
abstract public function DefineViewOptions();
}
class MyModelOne extends MyAbstractModel {
public function GetData() {
$params = array();
$params[] = $this->db->escape_str($this->GetSearchParameters());
// return whatever data you want, given the search parameter(s)
}
public function GetColumns() {
// return some columns
}
public function DefineViewOptions() {
// return some configuration options
}
}
In general you can't load another controller from within a controller in CodeIgniter (although there are mods that allow you to do something like this).
I would try creating a class for formatting your data and add it to the application/library folder. Then load, use and re-use this class throughout your various controllers.
Here is a page from the CodeIgniter documentation Creating Your Own Libraries that explains the details and conventions.
Also, if a class is overkill, creating helper functions is an even lighter approach.
The difference between libraries and helpers in CodeIgniter is that libraries are classes, helpers are just a group of php functions.
Once you have formatted your data, you can load any view from any controller, so you should still have all the re-usability you need so you DRY (don't repeat yourself)
There are a few simple approaches based on the principle of what's simpler (versus what's perfectly DRY). Here's one alternative approach I use with CodeIgniter:
Instead of trying to load multiple controllers, reuse the view fragments from your search controller (or search route, depending which you're using). This requires using the same naming conventions for your data elements so the views are interchangeable, but you should be doing this anyway.
Instead of using multiple models for search, add a single Search model that knows about the things that can be searched on. If you want to prevent duplicate SQL, reuse the SQL between models (this can be done using constants, or loading SQL from disk).
Controllers are not great candidates for reuse from your own PHP code: they route actions and requests for resources to the things themselves. They are intended to be called via HTTP, using the URI interface you've come up with. Calling them from code is a coupling you want to avoid. That said, reusing controllers from JavaScript (or via cURL) is a great, decoupled way to reuse things in any web framework.