I sometimes see the function parentNode() in cakePHP models. What is the purpose of that function and when should I use it? If I don't use it, what problems am I going to encounter.
On this website, they say that you need it so that your model can have ACL behaviors, but what if I just run the build_acl command after creating my Model, isn't that the same thing? Can someone shed some light on this please?
Thank you
build_acl() is useful as a one-time execution to populate your acl tables with the current controllers+actions. This is useful as a base to get you started.
parentNode() is called by the model behaviour in afterSave() to maintain the hiearchy during the life of your application. So when you manually (or dynamically) add AROs / ACOs later on (e.g. 5 months from now) everything will still work. Especially true if you add ACOs with custom aliases.
BTW, best ACL tutorial I've found:
http://net.tutsplus.com/tutorials/php/how-to-use-cakephps-access-control-lists/
Related
I'm learning Laravel and I'm watching many tutorials, but I dont really get it, what's the difference between the controller and model, because you can put in both a function.
Controllers in Laravel are used to determine how to handle http requests.
When you have anything to do with the DB, its better to place those function in the model, and call them from the controller.
In clear terms:
Model performs all operations on data from DB.
Controller call necessary model methods and ready the data.
View take care of displaying the data.
I hope this is clear enough.
You will be familiar with all of this soon.
model methods is for relationships mainly , or to make some thing for every object of this model (database table) every column in db is an object and every table is a model.
but in controller you set your app functionality that you want , and its an intermediator between model and view .
i hop this makes you good in this point.
good luck
You can write functions anywhere, you are perfectly right.
But is not an efficient way to do things.
The answers for those questions can be easily find out. Search about MVC pattern. In few words, remember brief:
MODEL => working with relational databases / storing the data
CONTROLLER => working with the logic(taking inputs, calculus etc) / general functionalities
Combining them is more efficient than working with those together, that is the reason why using a pattern is more great than writing code in a old style mode reinventing the wheel again.
I am currently looking to redesign a feature on my web application.
The web application utilizes Yii (version 1) for the back-end.
In this instance I have a model and controller. The model is used to store all the userTracking data and is appropriately a userTracking model however the actual logic for the model is in a controller called UserController. I have a function called actionTrackUser($id) which is used to implement various tracking logic for a particular user and create a model for that user.
I however now need to extrapolate this functionality from the UserController to a seperate trackingController which will implement tracking for various models.
I need to be able to utilize this functionality however in the new controller and old controller. I was wondering as to the best approach for this in Yii 1 that implements MVC correctly. I thought about making a trackingModel and having the userTracking model extend that but then I would have a lot of business logic in a model in order to use it in two places.
I am fairly new to MVC and Yii so I was wondering as to the best approach to take here?
I have purposely left code out of this question as it is more a theoretical question regarding the implementation of such functionality in Yii.
Any help is appreciated.
Thanks!
I am not sure that there may be a 'best' approach. However, you need to choose an approach that works best for you. Be guided by what will work for your situation, and what will make manageable code for you and others in the future.
There is nothing wrong with your current userTracking model and controller. You state that the "actual logic for the model is in a controller." You may want to relook at that to move appropriate data management, constraints and validation rules to the model at least.
You can move functions to a separate trackingController and still use the userTracking model. There is no rules that says you have to have a matching model and controller set, and it is quite possible for a controller to manage more that one model at a time.
I generally start with activeRecord models, which map against data stores (database tables in most cases). I use corresponding Form models to reflect forms that are markedly different from activeRecord models, and I use domain models to reflect complex business objects that are feature rich, and reflect lots of runtime attributes (like calculated fields) and state data (like publish state, which are calculated from other fields - for example a user could have validation status, paid status, active status, account level and so on that all work together to indicate what activity is possible for the user).
I have 3 tables that contain user information, one for students, one for teachers and one for administrators.
They are not related in any way. I wan't to create a dashboard for the Administrators, where a list of students and teachers shows up.
The only way I found to achieve this was using the $uses variable in the Administrators controller. However, I have read in many places that this is bad practice.
Any solutions?
Another, perhaps better practice is the use of ClassRegistry::init('MyModel')->myMethod() (more reading # Cake API)
This only loads the object when it's used, as opposed to loadModel or uses, with ClassRegistry the models are treated as singletons.
--
that you are doing something wrong: you need access to a model that has nothing to do with your current controller.
There are plenty of conditions where you would need to access all of your models data, from one controller, but never a definitive answer on how to do it without breaking convention!
You can always use another Model which is not related by using
$this->loadModel('NewModelName');
Then you can access new loaded model by:
$this->NewModelName->add(); // whatever method model has defined
Why prefer loadModel() over uses?
To gain performance. How? uses calls the loadModel function itself to load all the models you specify in uses array. But the problem is if only one of your action needs a particular model, whats the good thing to include it in every action. e.g. only add() action requires an unrelated model, but if you have specified it in uses array, no matter what action gets called a completely unrelated model is going to load. To put simply it will be inefficient. Its like you have declared variables in a C programme but never used them. In case of C compiler will warn you that you are not using your variables, but unfortunately cake couldn't tell you.
Its alright to use uses if all your actions needs to load that model, use loadModel() otherwise.
You probably didn't read my answer in your other question :))
I have 3 tables that contain user information, one for students, one for teachers and one for administrators. They are not related in any way. I wan't to create a dashboard for the Administrators, where a list of students and teachers shows up.
The problem is you are separating similar data into 3 different tables, in this case, user information. So when you try to manage this data, you hit a brick wall: because you leave out the relationships when you separate them in 3 tables.
The only way I found to achieve this was using the $uses variable in the Administrators controller.
You got the wrong idea about the controller. Each controller manage the data flow of a particular model (and related models). It doesn't mean that you have to stay in Admin controller to do administrative things. What model you want to manipulate decides what controller you need to be in.
However, I have read in many places that this is bad practice.
Now for the main question: using $uses is a red flag that you are doing something wrong: you need access to a model that has nothing to do with your current controller. Now, there're always exceptions in programming, sometimes we need to have access to that model. That's where loadModel comes in. Because it should be rare. If you need the model a lot, then you'll need to call loadModel a lot, which is cumbersome, which is what $uses is for, but then that means something's wrong with your app design :))
So, you can say using $uses is a sign of bad decision (in DB design or application structure); and so is using loadModel a lot.
Edit: Any solutions?
I gave one solution in your other question. But if you want to have them all in one place, you can have 1 users table with user information. Each User can hasOne Student, Teacher, Administrator and a 'group' field to decide what group the User is. The third solution is using $uses. Its performance impact won't be a problem really. But it will be pretty convoluted when you develop your app further. That's what you need to worry about. For example, I can say that, if you use Auth, you'll need to tweak it a fair bit to get it working with 3 models. If you use the users table, it will be a lot easier.
i am developing a groupon-like system, and i came into this project when the system is already around 70% built, and it was built using cakePHP, to be honest, i know nothing about cakePHP. and i came across this:
a member bought a deal
if(has_enough_account_balance){
if((parameters validated)){
insert into 'deal_user' table
log transaction
update 'deal' table by:
user_count = current user_count + bought deal //to determine whether this deal is tipped or not
if(this deal is tipped){
issue coupon
}
}
}else{
this_user_owed
}
the admin confirmed that a particular user has paid his/her owed deal payment
confirm has_paid
update into 'deal_user' table
log transaction
update 'deal' table by:
user_count = current user_count + bought deal //to determine whether this deal is tipped or not
if(this deal is tipped){
issue coupon
}
now seeing that the two of those has something in common, i am trying to do this:
a member bought a deal
if(has_enough_account_balance){
if((parameters validated)){
process_deal(parameters)
}
}else{
this_user_owed
}
on admin confirmation:
confirm has_paid
process_deal(parameters)
and process_deal would be:
function process_deal(parameters){
if(isset(deal_id)){
update into 'deal_user' table
}else{
insert into 'deal_user' table
}
log transaction
update 'deal' table by:
user_count = current user_count + bought deal //to determine whether this deal is tipped or not
if(this deal is tipped){
issue coupon
}
}
is it possible to do things like this ? and where is the best place should i put this process_deal method, i have tried to put this inside the app_controller class, but it seems that it wont update the table, i am not sure why can't it update (i am using the updateAll method), thank you very much
Looks like you can have this function implemented into /models/deal_user.php or /models/deal.php as model classes, so you can share the process_deal across needy controllers.
When a controller need it, simply include the ModelClass. Fatter Models.
and furthermore, you should not include this function into your app_controller as it might not make sense sharing this method across all other controllers, or instantiating the DealUser and Deal models across all controllers, and some might not need it at all.
If you tried debug($this) inside a controller, you know how horrible the array is. The more Model you include, the messier it will be.
Update
(Base on personal experience), put your code into following files when..
/app/bootstrap.php
Is when you have shared codes among everywhere in your application, like debug, json_encode (when PHP version < 5.2) etc
/app/controllers/components/*.php
Is when you have shared code/logic among controllers, with very minimal DB interaction.
/app/models/*.php
(Fat Models) Is when you have shared functionalities among a few controllers, that manipulate the data before saving into the DB, example such as your question above.
/app/libs/*.php
Is when you have shared external codes that doesn't fit into MVC, like TwitterOauth, or other generic classes/packages, which does not make sense converting it into Components, or too complex to do so. Import them into cake by using App::import('Lib', <name>) is pretty sufficient and neat.
/app/views/helpers/*.php
Is when you have shared html codes to render, that required some logic before converting it from data into html codes.
/app/app_controller.php
Is only when you need to do some hack on beforeFilter, beforeRender etc, that need to have common functionalities among controllers. The reason is because, your *_controller is extending app_controller, and if you are tempted and then add shared components, uses, helpers in the app_controller with the hope of having them in all controllers, it turns out that you have heavy controllers in every requests. Make it a habit try make your app_controller as slim as possible. Write more codes in each controllers.
/app/app_model.php
Same idea goes for app_controller
/app/plugins/*/
Is when you include external cake-like framework/features, or you can wrap certain framework into a plugin if you want.
/app/webroot/*/
And never never put your code under webroot! It's not neat, break Cake's structure, and it's not recommended! It's evil. Considering moving your code out of Cake if they couldn't be fit into Cake.
I think that is all? Again, they are my personal experience base on coding experience. Do comment/edit if you think they are not correct.
I'd go with Lionel Chan's answer above.
Also, it would probably help you to read over the CakePHP documentation. What you're trying to do looks like it shouldn't be difficult, but you'll have much more luck if you learn the framework and work within it rather than trying to work around it just using what you already know.
Any code that deals with a certain model's database table should go in that particular model class (the fat models referred to by Lionel).
So you could put the process_deal method in the Deal model.
The DealsController can then access the method like this:
$this->Deal->process_deal().
Then, if there's a relationship between two models, for example: DealUser hasMany Deal, you can access the method from within an action in the DealUsersController like this:
$this->DealUser->Deal->process_deal();
If there isn't a relationship between the models, you could still call the process_deal() method from within an action in the DealUsersController like this:
$this->loadModel('Deal');
$this->Deal->process_deal();
I hope this helps point you in the right direction, but I'd still recommend spending an hour or two perusing the CakePHP documentation linked to above because you're likely to find the answers to most of your questions there...
P.S. Kudos for going for the modular approach. It's always refreshing to see...
What I have is the following db structure(tables):
lists[name,id]
list_items[title,list_id,content]
I've created the needed files and code(the MVC) needed to manage the first table(lists).
I also added the hasMany to the model class. At that point I am stuck.
What I need is a solution for managing each item (basic CRUD, I assume that complex management is just an advanced CRUD that I will find out how to do by myself).
I will be specific: since it's a content that have no place (but the admin) that it will be used by itself, should I -
create a full mvc structure for it? (can or should I implement it somehow[how?] in the lists package?
if not, how can I attach the tables? (since the use is about to be dropped in version 2)
would an element(cake concept/context) will be the appropriate way to create a view for such situation?
ANY insight will be appreciated.
If I undertant correctly, you want to create a CRUD part of this tables by yourself, without bake.
You need to write all the MVC estrucure and be carefull with the naming combention of cakephp http://cakebaker.42dh.com/2006/02/18/cakephp-conventions/
You need the model into app/models and also a a controller into app/controllers (remember naming combentions) and for each model you need a folder into /app/views.
Alfo, every, every function in your controller needs a view, even if this action doesn´t write anything to screen
I hope this was usefull.
Have you tried using Cake's bake feature? Your CRUD will be automatically created in about 2 seconds. I would also recommend you do the Blog tutorial to get a feel for scaffolding.
CakePHP is all about convention over configuration. Eg naming conventions for tables, controllers, models etc.. So much can be done automagically.