Cakephp - Overriding model method from controller - cakephp

I need to override & add methods in a model invoked by a controller. I don't want to write anything inside Model class file because it's used by other controllers too. Methods are like pagination() and find(), can I do it from inside a controller?

CakePHP behaviors are mixins. They add methods to a model, which is what you are looking for.
It sounds like dynamically attaching a behavior to the model would get you the outcome you need.
Looking at Model::__construct(), I can see that it calls $this->Behaviors->init($this->alias, $this->actsAs);.
You may be able to call it again after the model has been instantiated to attach different behaviors (ie. $this->MyModel->Behaviors->init('MyModel', array('MyBehavior'));).
In fact, a closer look reveals that $this->MyModel->Behaviors is an instance of BehaviorCollection. As such, you can use the attach() method.

Related

Me, AngularJS, and its 3 different ways to specify a controller

I'm confused by these three different ways to specify a controller.
1- I can have an include in the app/index.html file:
<script src="scripts/controller/nav.js"></script>
2- I can have an attribute in a route:
.when('/link/list/', {
templateUrl: 'view/list.html',
controller: 'navController'
})
3- I can have an attribute in a view:
ng-controller="navController"
It's quite a few. I wonder which way to go and when.
Kind Regards,
Stephane Eybert
Your (1) has nothing to do with (2) and (3).
And there are other places where you can bind controllers (e.g. a directive's controller property).
Each way is serves a different purpose, so go with the one that suits your situation.
If you have a directive and want to give it a specific controller, use the Directive Definition Object's controller property.
If you use ngView and want to give each view a specific controller (as is usually the case) use the $routeProviders controller.
If you want to assign a controller to some part of your view (in the main file or in a view or partial) use ngController.
All the above are methods for "binding" a controller to some part of the view (be it a single element or the whole HTML page or anything in between).
Im quite new too but Ill try to explain in a more layman way.
1 For each .js file you have (which may contain one or more controller defined), you need a corresponding entry into the script for #1 there. Its not the controller itself, more like to allow script to recognise that this .js file is part of the set of files to run.
2 is more like specify a state or route, which may or may not use a controller. Its much like saying how one event should lead to another. The controller may be involved in the transitions of the states/routes (ie. responsible from one state, to another) or within a view itself.
3 is for using a controller's functions within a view itself.
I've added comments to one of the answers, but aside from syntax this may is more of a design question. Here is my opinion
Firstly, (1) is irrelevant to the conversation.
(2) is the preferred approach when specifying the controller for the view as it decouples the controller from the view itself. This can be useful when you want to re-use the same view by providing a different controller.
If you find yourself using (3),consider making that area into a directive, since by specifying a controller you are indicating that it requires its own logic.

Angular docs: how can one share stateless/stateful code between controllers?

Been reading the Angular.js' Controller docs and stumbled across:
Sharing stateless or stateful code across Controllers — Use angular
services instead.
But this leaves me uncertain. How do one can share a stateless/stateful code between controllers? Or what does the "code" mean here? A model? Besides, controllers do not refer to each other, as far as I understood. Can anyone clear things out for me(others) please? Thanks.
I think what they are referring to might be one of the methods to "persist" data, sharing it between controllers or between route-changes. One way to do that is to put it in your rootScope, another is to use a service. If you define a service like this:
.factory("MyDataObject", function() {
return {};
})
Then MyDataObject will be the same object anywhere you call it, allowing you to save things into it in order to share data, functions and states between controllers (or directives, or other services, etc).
You never know with the Angular documentation, but I would guess that is what they are talking about :)
See for example this answer: Angularjs, passing scope between routes
Here is my view on subject. As angular guys have always tried to explain, scope is not your model. Angular "services" are way to do it, but word service is such and overloaded term. Coming from DDD background, I cannot reconcile word service with a state or statefulness, it just does not make sense to me. What makes more sense is ViewModel or whatever you want to call it. Since I've worked with Silverlight using MVVM pattern, I call them ViewModel. As it is a job of a "Controller" to provide Scope for a View, my controllers have been so far very lean. Bulk of logic is in a ViewModels that get associated with a View through a $scope that controller creates. Does that make sense? So my controller might take a dependency of let's say mySearchViewModel, bulk of the logic is in there and can be shared between controllers, and to associate it with a view you would do something like $scope.vm = mySearchViewModel in mySearchController.

AngularJS - ngView scope?

I'm using ngView's to load content on demand.
What I don't quite get is when is the controller for each view created?
I have the same controller assigned to a few of my views, and they seem to share data between them. yet my impression is that the controller is recreated each time the specific view is shown.
So how does it work?
When you define a controller in your JavaScript using .controller(), you defining a class, not creating an instance of an object.
Colin Moock defines the difference this way: an Object is like an airplane, it can perform actions like fly() and has properties like maxPassengers. A Class is like the blueprint on how to build that airplane, from which you can make infinite airplanes. Amazing! You can watch Colin Moock's whole explanation right here if you want: http://tv.adobe.com/watch/colin-moocks-lost-actionscript-weekend/object-oriented-programming-overview/
Every time the view is loaded, a new Instance of your controller Class is created. Most Angular.js controllers have a capitalized name like Dashboard or Contacts because they describe a Class.
So the answer to your question is a new instance of your controller is created every time your view loads.
It turns out that when using a factory for your model and injecting the model into the controller, then you can keep state when you change views.
I used a factory for one of my controllers and "new FooModel()" inside another controller, thus two different behaviors on the views using the two controllers.

Define controllers in app.js Extjs

Here my app.js code :
Ext.Loader.setConfig({
enabled: true
});
Ext.application({
name: 'KP',
appFolder: 'scripts/app',
controllers: [
'login.Login'
],
views: [
'login.Login'
],
launch: function () {
var view = Ext.widget('login')
}
});
If I want to use some others views, controllers, models and stores in my application, should I define them in app.js? (like this : controllers[....all of my controllers.....])
Are there other way to get to work init function in my controllers? Thanks!
There are many ways...
Following some basics first:
All controllers that are listed within the controllers array of the application controller get instantiated at startup (application get initialized with the onReady event. Also the init() and onLaunch() methods of the listed controllers get called. See the linked API for details when this occurs). Now each instantiated controller initialize its stores,views and models (creates getter for all and over that creates instances of each store while overwriting the storeId and append them to the Ext.StoreMgr). Note that each controller will contains his own models, stores and views.
The simplest way to receive a controller that is not listed in the application controller is by using a reference of the application controller and calling getController(name)
It is Important to know that while using that way the receive a controller instance the getter method will not call the init() or onLaunch() method for the invoked controller, it will just try to get the controller or create it. You should also note the API for those methods in these controllers are no longer correct. You need to set an init bool to these controllers and check it on the reference that the getController(name) method hands back to you. If it is undefined/false you call the init() / onLaunch() by yourself and set it after that. I use these technique by myself to reduce intial load for bigger application. I guess you don't really need this for just a handful of controllers.
Update
Due to some changes in the 4.1.x release it is no longer required to init the controller
manually. This is now done for us by the getController method
You can define as many controllers as you want. To implement hierarchy you can define views and stores related to certain controller within it.
For example:
controller/
artists.js (inside: artistsView1.js, artistsView2.js, artistsStore.js)
paintings.js (inside: paintingsView1.js, paintingsStore.js)
All of your views and stores used in controllers would be loaded and initializadduring Applocation load.
The controllers you define in your application are loaded before the application launch() is called. As each controller is loaded its models, views and stores (MVS) are also loaded.
Although you can define the MVSs in your application, I'd recommend that each controller defines its related MVSs, as it is possible for the programmer to load controllers (and their related MVSs) upon request rather than by default. It is also a good practice from reusability point of view (so if you ever to reuse the controller, you know what MVSs come with it).
You may want to include some views in the application if, say, they are used without controllers, like some sort of a custom window you display if there was some error in the system.

Best way to control access to functions in CakePHP

Simple question: what is the best way to ensure that a function is only being called from inside my app? I just want to make sure that nobody could just type in the url and run it.
I've thought about using Auth, but I really don't need username/password protection. Then I thought about private/protected functions, but I've read that CakePHP doesn't handle with that very well. And if I use private, as an example, I wouldn't be able to call the protected function from another controller class.
I think there must be a simply solution to this, but I can't think of one.
Thank you all in advance. :)
if you have functions that are been used in different controllers, it would be better if you create a component.
But.... if you really need to.. if you really want to.. you could set the access by adding an underscore at the beginning of your method's name:
class ProductsController extends AppController {
// a browser can "access" this method
function iHaveAView(){
}
// this method is used only by controllers
function _cantTouchMe(){
}
Good Luck
EDITED: (finally found the doc about this)
You can also change the visibility of controller methods in CakePHP by
prefixing controller method names with underscores. If a controller
method has been prefixed with an underscore, the method will not be
accessible directly from the web but is available for internal use.
source: Controller Conventions
I think it's simple don't put the function as an action of a controller. Create a component and use that when you need it.
That would make your function unavailable to the public but available within your app.
What do you think?

Resources