Normally I load model inside classes like this:
public $uses = array('Table1', 'Table2', 'Table3');
But some of my models are only used by 2-3 actions. So I don't want to load that model for other actions. So I need to declare "table1" controller wide. And load "table2" and "table3" when I need them inside controller. Is it possible? I couldn't find inside cookbook.
Something like this:
class myController extends Controller {
public $uses = array('Table1');
public function myaction() {
$uses = array('Table2','Table3');
....
}
}
CakePHP uses lazy loading since v2.x, i.e. if you specify a model in the $uses array it is only loaded when it is really used, so it's fine to use your first snippet.
But if necessary you can also use the loadModel() method to load a model in a single action:
public function myaction() {
$this->loadModel('ModelName');
$this->ModelName->doSomething();
...
}
In any controller method you can import models when required:
App::Import('Model', 'YourModel');
$foo = new YourModel();
Now you can call methods by referencing from the model Variable e.g.
$foo->myMethod()
Instead of:
$this->Model->myMethod();
Related
I have a Node Model with variable translateFields (using CakePhp):
class Node extends AppModel {
public $translateFields = array('title');
.....
}
For any case (not all), I want change to:
public $translateFields = array('title','field_image');
How I do this? Change in Controller or where?
See all Models inherit AppModel ,correct? So define the variable in AppModel. Therefore it will be accessed as will be defined in parent. Also you can override like you used different array indexes.Hope it makes sense.
In a Controller or another Model which uses the Node model:
$this->Node->translateFields = array('title','field_image');
In a method of Node:
$this->translateFields = array('title','field_image');
I have Content controller with REST methods (index..create..store..) and i want to run some code before any of those methods run.
what i am trying to do is to set var for my layout with some data that is relevant to all my methods within Content controller:
$this->layout->myvar = 'some-data';
I tried to do something like that:
class ContentController extends BaseController {
function __construct() {
$this->layout->myvar= 'some-data';
}
..
but it doesn't seems to work.
i get "Attempt to assign property of non-object" error.
Laravel 5.1+
This has been deprecated in favour of Middleware.
Laravel 4
You could set the beforeFilter like this:
class ContentController extends BaseController {
function __construct() {
// this function will run before every action in the controller
$this->beforeFilter(function()
{
// this will make the variable $myvar available in your view
$this->layout->with('myvar', 'some-data');
});
}
}
try share in app/routes.php
View::share('variable_name', 'value');
ex:
View::share('name', 'Steve');
will share variable with its value across all views
I am creating an API and I want to include both regular resources and nested resources
For example, I will say I have a Post resource and Comment resource. I have setup the appropriate routes and controllers like the following
Routes
Route::resource('posts', 'PostsControllers'); // /posts/{id}
Route::resource('comments', 'CommentsControllers'); /comments/{id}
But I also want to have comments as a nested resource of posts, like this
Nested resource route
Route::resource('posts.comments', 'PostCommentsControllers'); /posts/{id}/comments/{id}
Because I have already written my CommentsController, I would like to know of the best method to re-use the CommentsController for my PostsController
Thanks
Using inheritance is the best way:
class BaseController extends Controller {
public function index() {
}
public function create() {
}
public function store() {
}
public function update() {
}
}
class PostsController extends BaseController {
}
class CommentsController extends BaseController {
}
You can just extend your Blog/Comment/*Controller on a generic FooBarController which holds all the logic.
You will have to supply the model and other model-related data, I do this via the constructor, and my models holding data about the columns, etc.
Heres what im trying to do
Ive got table that holds many different types of data for items. the model name for this is 'Object'
for example :
row 1 : item_type = event
row 2 : item_type = news
row 3 : item_type = booking
i want to write a controller 'event_controller' and use the 'Object' model with it and only deal with item_types of event. and another controller for news (news_controller) and use the same model.
how do i do this on cakephp.
Im coming into cake from codeigniter and in CI we can load any model we want into any controller can i do something similar with cake?
It's considered poor form to use var $uses in CakePHP 1.3+. It's been replaced by App::import (see below)
Given you have a Users controller with User model, and a Comments controller with Comment model. The accepted patterns are:
Using Associations
This is your best bet if the models can be logically associated.
// models/user.php
Class User extends AppModel {
public $hasMany = array('Comment');
}
// controllers/users_controller.php
Class UsersController extends AppController {
function allComments() {
$this->User->Comment->find('all'); // You can use this across multiple models (e.g. $this->User->Comment->NestedComment->find('all');
}
}
Instantiating the model object
This will load your model file, add the instance to CakePHP's object map, and returns the instance.
// models/user.php
Class User extends AppModel {}
// models/comment.php
Class Comment extends AppModel {}
// controllers/users_controller.php
Class UsersController extends AppController {
function allComments() {
$Comments =& ClassRegistry::init('Comment');
$Comments->find('all');
}
}
Using $this->loadModel
Internally this uses ClassRegistry::init, then also adds the model as a property of the controller.
// models/user.php
Class User extends AppModel {}
// models/comment.php
Class Comment extends AppModel {}
// controllers/users_controller.php
Class UsersController extends AppController {
function allComments() {
$this->loadModel('Comment');
$this->Comment->find('all'); // using load model allows you to access it via $this->Model
}
}
App::import
This is really just the CakePHP way of requiring a file. You'll still need to instantiate the object.
// models/user.php
Class User extends AppModel {}
// models/comment.php
Class Comment extends AppModel {}
// controllers/users_controller.php
App::import('Model', 'Comment');
Class UsersController extends AppController {
function allComments() {
$Comment = new Comment();
$Comment->find('all');
}
}
I hope this helps.
Edit: If you want to use the model object globally within the controller, you can use any of these patterns I specified within your beforeFilter().
I would like to suggest you to not to $uses statement. Instead of that you can use relations of the models like $this->Model->M0del1->....->someFunc(); if the relation exists.
If the relation between the models dos't exist then simply use $this->loadModel('ModelName'); in the specific function where-ever you need it.
If you use var $uses = array('Object'); it becomes global to the controller and it will load that model for all the actions of the controller despite of whether you require it or not. This will affect your performance.
If you use $this-LoadModel('ModelName'); in a particular function it will only load in that function not in all the actions.
You declare your controller and declare the $uses variable on it like this:
var $uses = array('Object');
Hopefully a simple question: I've a plugin which uses a set of tables (kb_items, kb_item_tags, etc). and I'd like to be able to access these models from another controller (say, my Pages controller), thus:
class PagesController extends AppController{
function knowledgebase(){
$items = $this->KbItem->findAll(...);
}
}
I am admittedly breaking the rules a little (by not placing this controller inside the knowledge base plugin), but this in this case its a custom page that doesn't need to be part of the knowledge base plugin code base.
Please let me know if you need more details. Thanks in advance for any help!
I just had to do this myself, and putting the model name in the 'Uses' array does work. If you don't need to access the model in multiple controller actions, you can also use loadModel() to access it in just the actions you need. For example, let's say you only need to access this model in the view() action of a given controller:
function view() {
// load the model, making sure to add the plug-in name before the model name
// I'm presuming here that the model name is just 'Item', and your plug-in is called 'Kb'
$this->loadModel('Kb.Item');
// now we can use the model like we normally would, just calling it 'Item'
$results = $this->Item->find('all');
}
Hope that helps.
Not sure if it works like this in 1.1 but in 1.2+ you prefix the model name with the plugin name and a period in the controller's uses array:
class PagesController extends AppController
{
var $uses = array('Page','Kb.KbItem');
function knowledgebase()
{
// This now works
$items = $this->KbItem->findAll();
}
}
Just add the models to your controllers' $uses property:
class PagesController extends AppController
{
var $uses = array('Page','KbItem');
function knowledgebase()
{
// This now works
$items = $this->KbItem->findAll();
}
}