I have a set of functions that are called from 2 different models [ and maybe more in the future ]
What's the best approach to deal with this :
1 - Duplicated in each model
2 - Creating a helper for those functions and loading that helper from each model
Do you suggest any other approach
You can create a base model that your individual models extend, giving them all a shared ancestor of sorts.
Create the file application/core/MY_Model.php
class MY_Model extends CI_Model {
public function common_method($param)
{
// Stuff goes here
}
}
Then, any model that you wish to use the common method(s) in should simply extend MY_Model instead of CI_Model.
Note that the MY_ prefix is the default for CI, but you can change it in the application/config/config.php file.
Its my approach i don't know its a proper one or not.
If you are using this function throughout the site, You can create the class with those functions and add it in a library.
If you like you can do autoload also if require. Based on your usage.
Related
how to use another controller function without extends in our controller
$this->load->library('../controllers/controllername');
already used
it is giving error =
Unable to locate the specified class: Session.php
Well you are not supposed to do that. If your controller uses repeatable logic, you should make class (Service for example), put the re-usable logic into it and call it in your controllers.
You can't use another controller function inside the controller. You can archive this in these two ways.
Create a Helper class
Create a generic model.
To develop a project where I am creating some methods which are common in all the controllers.
Before this I have used codeigniter and there I wrote MY_Controller class in core directory and then I extended the controller in all the controllers in controller directory.
Same I want to do inside Laravel. But I am confused that where should I write the common methods like send_email, validate_captcha, ajax_file_upload and other common methods which remains same across whole application.
So please suggest me a good way to define such a class or middleware.. What should one do to create that?
OK. Let me suggest some stuffs
Need to write methods which is apply to all Controllers. You
can/should modify App\Http\Controllers\Controller.php. Because all
Controllers in Laravel extend it
Need to write class that available across whole application. It is
never easier
Step 1: Write any class you want in app folder. And follow psr-4 convention
Step 2: Register to Laravel application
In App\Providers\AppServiceProvider. In register() method. Add
$this->app->bind('bindname', function ($app) {
return new \App\YourClass;
// If you want to inject other class to YourClass contructor
// return new \App\YourClass($app->make('otherbindname'));
});
Step 3: Use it. There are several ways to access YourClass in your whole application:
app()->make('bindname');
app('bindname');
app()['bindname'];
\App::make('bindname');
//etc
Im new to Laravel and namespaces, but a colleague told me i have to use the namespaces and place all my models in a folder in the app directory, named after the project.
As far as i know this means that in every single controller that uses one or more models, have have to set "use" for every model my controller needs. Example:
<?php
use Foo\Entities\Entity;
use Foo\Entities\Inheritance;
use Foo\Entities\Type;
class EntitiesController extends BaseController {
public function index()
{
$inheritances = Inheritance::all();
$entities = Entity::all();
return View::make('settings/entities')
->with('entities', $entities)
->with('inheritances', $inheritances);
}
}
If we asume that the associated models above will be used everywhere, would it be completely crazy to put the models in the /app/model/ folder and if a controller need a model which overwrite the standard system, then use namespaces?
First things first: namespaces are NOT a Laravel thing, but a PHP feature created to better organize our code.
So, if you want your code organized, you should use namespaces for everything and, yes, you'll have to add 'use' clauses in the top of most of your PHP files. But in Laravel you also can be free to not use namespaces at all, you just have to add your autoload classes directories to your composer.json file:
"autoload": {
"classmap": [
"models"
],
},
Execute
composer dumpautoload
So Composer read all files in your models folder, to create a class map of them, and then you can just drop all uses clauses:
class EntitiesController extends BaseController {
public function index()
{
$inheritances = Inheritance::all();
$entities = Entity::all();
return View::make('settings/entities')
->with('entities', $entities)
->with('inheritances', $inheritances);
}
}
To not use namespaces in your PHP application, these days, may be considered a code smell. The only 'part' of Laravel where people doesn't usually use namespaces is Controllers, but this is also changing in Laravel 5, where controllers will be namespaced by default, but still, you will have the option to not use them, because this is a Composer/PHP thing, not Laravel.
Taylor Otwell has 3 big things always in mind when creating features and evolving Laravel: Best practices, fast coding and beautiful code.
EDIT
Answering your comment, if all your controllers needs to have access to some service or even model, why not add it to your BaseController?
But you may have to take a read at the repository pattern, because your controllers should not really be aware of your models. Developers are now creating a new layer (repository) between controllers and models, and perform the operations in those layers. You can, also, make use of Laravel Dependency Injection to help you with those use clauses you don't like.
It would be something like this:
Create a repository interface:
interface EntityRepositoryInterface {
}
Create the repository:
use Foo\Entities\Entity;
class EntityRepository {
public function find($id)
{
return Entity::find($id);
}
public function all()
{
return Entity::all();
}
}
Create your controllers using your repository:
class EntitiesController extends BaseController {
public function __construct(EntityRepositoryInterface $entityRepository)
{
$this->entityRepository = $entityRepository;
}
public function index()
{
$entities = $this->entityRepository->all();
return View::make('settings/entities')
->with('entities', $entities);
}
}
And you have to tell Laravel Dependency Injection what to instantiate when it needs a EntityRepositoryInterface:
App::bind('EntityRepositoryInterface', 'Foo\Entities\EntityRepository');
There's nothing wrong with putting your models anywhere you like. In fact, I put all my models that extend directly from Eloquent in app/models. You are free to follow this, or not follow it, in your own project.
However, this does come with a caveat. Very few of my classes actually directly interact with these models (Repositories are pretty much it). Those I do put in separate namespaces which are then injected into my controllers. Consequently, I must either use each repository that a controller needs at the top of each file or specify the fully qualified class name every time I reference it.
I am currently developing a Lithium application and have come across a function that I have written that I would like to use across multiple Controllers.
I obviously don't want to have the function in each controller. What is the standard way of creating a re-usable component in Lithium?
The lack of search facility on their documentation is making it difficult to find any specifics.
You could try extending controller. Extending controllers is not that bad according to core devs. If that is not and option you could extract your code into a plugin, still some code in controller though.
All you have to do is create a extensions/action/Controller.php and have your controllers extend that.
In your extensions/action/Controller.php
<?php
namespace app\extensions\action;
class Controller extends \lithium\action\Controller {
protected function _init() {
parent::_init();
//add your functionality here
}
}
?>
And then, your controller has to extend the above mentioned base controller: class MyController extends \app\extensions\action\Controller {
I think this is not a Lithium-specific thing. You could either inherit from the Controller and make your own base controller, but you can also create arbitrary classes that hold your functionality. Don't let a framework inhibit you =)
Regarding the documentation: I usually google in the sense of "<keywords> site:lithify.me"
I have a list of constants (I'm using them as an enum), some are define statements, and some are just global variables.
Where am I suppose to put them in the MVC framework so I can use them for both my model and my controller that needs to reference it?
I'd rather not stick it into config/constants.php since they shouldn't be called except for by this model and the controllers that use it.
Edit 1: Clarification
To be more specific, I have my message_model model and it has a bunch of constants that I need that are stored in message_model_constants.php. Where should I put message_model_constants.php and is there a way to have it automatically included by the controller that loads message_model when message_model is not (and I don't want it to be) auto-loaded.
Edit 2:
I really don't want to have the constants auto-loaded except for when I use the model
Go to application/config/constants.php and define your constant their and you can use your constants on Model-View-Controller of CI not include "Helper" and "Library"
But in your case I prefer you to create a php file that has your constants and rename it to something like my_constants_helper.php.
In your model or controller __construct just
$this->load->helper('my_constants');
And hooray you can access them =)
You can choose to load a particular config file when you load a particular model in the controller. For instance in your file:
application/controllers/messages.php
You would use a line like this:
$this->config->load('messages');
If you include it at the top of your controller like this
function __construct() {
$this->config->load('messages');
$this->load->model('message_model');
}
Then all of those constants will be available to all the functions and methods in the given controller. You then call each config constant like:
$this->config->item('item name')
And you can name protected $variables; in the construct as well for shorter syntax.
If you are using these config constants and the message model in multiple different controllers you may want make a "Library" file that then loads both the config and the model and declares all variables there.
extending Brennan Novak answer, you can simplify your code by loading your config file in the model constructor. That way, you only have to load the model in your controllers and everything else is done automatically.
Model
class Message_model extends Model {
function __construct()
{
parent::Model();
$this->load->config('message_model_constants');
}
...
}
Controller
class Some_controller extends Controller {
function __construct()
{
parent::Controller();
$this->load->model('message_model');
}
...
}
As already stated, your config files should be application/config/message_model_constants.php
For global configs, add to the config/config.php or create a config/application.php and then load the config, then the item.
$this->config->load('application'); // or autoload this - $autoload['config'] = array('application');
$this->config->item('item name');
Have you considered just adding your constants to your Message_Model Class? You'll then reference them by self::ConstantName inside the Class and Message_Model::ConstantName outside the class. This would also prevent name space collision.