I would like to extend Query class in order to create function customContain() available in every Table model. How should I do it?
I want to use that BleMethod() in all table models in cakephp. Where I have to add code of that function? Where I have to implements BleMethod?
Unlike Cake2 Cake3 does not feature an application level class like AppModel from where all other classes inherit from. So you have two options:
Trait
Behavior
The behavior can be loaded globally to all models by using the Model.initialize event. And then loading the behavior inside the events callback. Read these pages:
Creating a behavior
Event system
Model / Table callbacks
But that's not what you want
customContain() indicates for me that you want to setup some contains very often. Well, use finders.
Finders can be combined:
$this->Table->find('foo')->find('myContains')->all();
Each custom find will add something to the query object. You can add your custom contains this way.
Read Custom Finder Methods.
I have read a book about MVC last week and a general one about design patterns, but I'm still confused as to where SQL queries belong in my code: the model or in the controller?
Let's take a very simple example, where you have a /popular page that will print the 5 most popular stories on a website.
In your model, you would have a class for prepared staments, and a class for assisting in the creation of the SELECT query. In your view, you'd have the HTML elements that display the /popular page.
Where does the query "SELECT most popular stories LIMIT 5" belong to? Is that something a controller class should ask, taking query methods from the model and passing to the view, or should the query be declared instead on a model class related to the /popular page?
Is the distinction even relevant? Would placing that query on the controller or the model be both considered professional ways to build a MVC?
Thank you. It seems most people get stuck understanding what to place on controllers
Edit: thanks for help everyone. Unfortunately as a new account I can't upvote any helpful posts yet
Usually (based on my experiences with MVC frameworks) the model layer takes care of database-related stuff in MVC.
Consider following approach:
Create abstract class which covers all the DB operations (selects, updates, etc). Each table would be a PHP class extending such class. You can then define DB table name in for instance private field, constructor or depending on model name.
Each controller (or the single controller) would load desired model, and use its methods to fetch data as associative arrays or objects, delete the data, change it.
After all DB operations have been done, controller returns view and passes data as its parameters.
Note that models are great place to put all the validation rules, and some helper methods due to the fact that they can be easily tested in PHPUnit.
Ok, I couldn't insert the overview image, but I'm required to create a PHP app for my studies, it must allow student to register, and the administrator to edit course and student info.
We are not required to code it in an OOP style, but since its the best programming practice to code in OOP, why not learn OOP from the beginning.
I'm a beginner but I know the basics about OOP, classes, inheritance, setters and getters and all that cool lingo, but I'm struggling to decide which parts of this app should be objects, should I make course and student classes or add, edit and delete classes? Any advice on how to approach and visualize such a problem would be appreciated.
Very roughly: This is how I would do it:
Store your data in SQL or XML. You will need two SQL tables, one for Students and one for Courses. You can use one XML file containing all the data, or you can use two files (which I recommend).
Create a class called, for example, dataItem with a property like '$arr_fields' corresponding to a single data record (a single row in a SQL table, or an XML record).
The dataItem class should have the following methods (all public):
loadFromSQL() (or loadFromXML())
saveToSQL() (or saveToXML())
add(), edit() and delete()
a view() method using HTML
These methods are obviously used to read and write data between the SQL/XML data and $arr_fields of the class, and to display the data in $arr_fields. The keys of $arr_fields are the SQL column names (or XML tag or attribute names) for the specific SQL table.
Try not to call loadFromSQL() or saveToSQL() in your constructor or in any of the other methods which are used to modify only the class data. Keep these actions separate. EDIT: This is a personal preference which helps me to keep track of the state of my objects.
Create Student and Course classes that extends the dataItem class.
You can override methods, for instance the view() method, inside your extended classes if you need to.
Then you can call the methods in Students and Courses from an Admin object (like rcdmk suggested) or maybe from StudentFolder and CourseFolder classes whose view() method contains buttons for the actions that need to be performed. (Let StudentFolder and CourseFolder extend a Folder class that you create).
UPDATE:
For example: If your primary key in a SQL table is id, then dataItem's loadFromSQL($id, $tablename) should set $arr_fields so that its keys are the column names and it's values are the values from the row whose primary value is equal to $id.
In Students, you can then override loadFromSQL() as follows:
class Students extends dataItem {
// other attributes
public function loadFromSQL($id) {
parent::loadFromSQL($id, "Students");
}
}
EDIT: On reconsideration, it might be better to set $arr_fields["id"] = $id and also set $tablename with the constructor for dataItem - then you never have to override loadFromSQL() or specify parameters for it. loadFromSQL() should then load the record if it exists. saveToSQL() should save $arr_fields in SQL if $arr_fields["id"] is set and create a new record if it is not set. Anyway, you must find a consistent way of interacting with the data which works for you, these are just possibilities.
However, if you are not experienced with OOP and SQL or XML, you might be opening a can of worms for yourself and it might be better to just do your assignment using functions only and php arrays for your data. Unless you have some time to learn...
From a simple perspective:
Abstract the main objects as classes and use methods for actions of this objects:
Student (object) are deleted (action) by the Admin (object), so
Admin class will have a deleteStudent method, because Admin deletes Students.
Another aprouch is to concentrate all Student related actions in the Student class:
Student class will have a public delete method that Admin can use.
Anyone that think this in better ways of explanation can edit this wiki.
Think about which aspects of your system are actually objects, you know, something you can do something with. The methods are what you do to the objects. So, you're on the right track with course and student classes, and add, edit, and delete would be methods of those classes.
But don't get too bogged down with it. If it's not your core assignment objective, you could quickly get in over your head by trying to do everything exactly the right way. If you can formulate a clear way to get to where you need to go, then go for it, if it seems confusing, back off it a little and learn some more.
You say that you know the basis of OOP, however you ask whether you should create Course, Student classes OR Add, Delete, Edit classes. Well maybe there are other practices, but I guess the most popular one and the only I am aware of is to use nouns as classes and verbs as their methods. Hence, intuitively there is something wrong with class "Add" or "Edit". What I would have done if I were were, is to think of all "entities" that might be considered an object - like Student, Course, Lecturer, Class (Room) and depending on how advanced your model should be you can add more like Building etc. Then try to implement basic things like creating new student, registering for a course, associating teacher with a course etc. Once you have it in place and IT IS WORKING you might want to add advanced things, like inheritance. For example you might want to say, that both Teacher and Student are a Person so you might want to create such abstract class and use inheritance.
i use a simple PHP framework (like Codeigniter) without ORM.
I have a database with product data (prices, sells, page in catalog...).
And i want to calculate the conversion per page and the conversion per product.
The calculations with SQL are not a problem, but i don't really know where to put them in.
Should I create a "Page" and a "Products" model with methods like
"Page::getConversions($page_id)" or a "ConversionPerPage" and a "ConversionPerProduct" model, or sth. completely other.
I think that the best model classes are to have two classes for each table - one for object and plural for static classes.
For example: if you have Page table then you should have Page and Pages classes.
First one will allow you to have one object from table and you can do the regular methods on it like:
$page = new Page($page_id);
$conversions = $page->getConversions();
$page_number = $page->getNumberInBook(); etc
On the other hand in Pages class you can put the methods that will (usually) return the array of Page and those methods will usually be static:
$pages = Pages::getPagesByCatalog($catalog_id);
This way you will have real OOP and code complete with full model MVC implementation.
I hope that this model hierarchy will help you. We are using it in our office and it showed to be really good.
All the best!
Basically, you create models based on the database schema. So, first option is preferred. Moreover, it should be instance method instead of class method (the object is then identified from the $page_id).
Presumably you are going to have Page and Product models anyway so I would add the getConversions() function to those.
I've inherited a medium-size website written with a custom (small) php framework. I want to switch to the yii framework but first I need to find a solution for the following problem : the site is basically a series of courses and exercices that are available in multiple languages. In fact all the content is available in multiple languages.
The users can select their preferred language and the localized content is retrieved from the database.
Database organisation :
table exercises with id and language-free columns
table exercises_strings with exerciseId, sLanguage and sContent
How can this be easily integrated with the "Post::model()->findAll()" yii's way of retrieving data from the DB ?
Should I write my custom derived class of CModel that would retrieve language preference from the IUserIdentity class and adapt the query ?
Is there some code arround that I could look at ?
Should I write my custom derived class of CModel that would retrieve language preference from the IUserIdentity class and adapt the query ?
I don't think, you need to do that. There are different ways:
1.)
You can use the cdbcriteria to set the criteria (for example the where clause) after creation an instance of the object and before running findAll
http://www.yiiframework.com/doc/guide/1.1/en/database.ar (look at the end of the 2nd quarter of the page)
2.)
An other way is to overwrite the findAll inside your model:
public function findAll($condition='',$params=array())
{ $condition["criteria"]->compare ....
return parent::findAll($condition,$params);
}
3.)
You also can use the onBeforFind trigger http://www.yiiframework.com/doc/api/1.1/CActiveRecord#onBeforeFind-detail, which fires before (every) the findAll search
i would prefer that 1st or 2nd idea.