I am building a db intensive application in yii . So performance and security are naturally a concern . Apart from that form validation is also a major criteria . For security I plan to use parameter binding for all Sql Queries . For validation I want to use validators provided by Yii instead of rolling out my own . I am aware that performance takes a hit with CActiveRecord . So I plan to make Cmodel classes for all my tables , define validation rules in these respective models and also define functions to perform the sql queries for retrieval and insertion of data . All my data collection on the website is primarily through forms (about 95%) , should I use Cformmodel , I dont really understand the distinction between Cmodel and Cformmodel , is there any performance hit in using either .
Also to prevent XSS attack I want to use HTML purify wrapper as a validation rule , since I read almost everywhere that performance is bad for this wrapper , is it going to be bad even if I use it as a validation rule ? And should I be displaying my output text using Chtml::Encode even though I am purifying the input ?
My rough plan to deal with the data is :
$users= new Users() ; //Users is extending CModel , contains validation rules
$users=getdata(Yii->app->userid()) ;
if(isset('update'))
{
if($users->validate())
{$users->updatedata() ; }
}
$this->render('users','data'=>$users)
CFormModel inherits from CModel, CModel is just a generic Model class, there are not performance differences in using CFormModel, which is what would suit more for your application if you don't plan to use CActiveRecord.
For 'functions to perform sql queries' hopefully you mean stored procedures, other wise there is not that big performace gain, even then, writing your own SQL queries only for insertion and retrieval of single models doesn't help much. My advice is that you care about performance latter on. once you really have something to improve upon.
Purifying the input its different from encoding, with HTML purify you eliminate harmfull html to prevent XSS or other tags you dont want to allow. but a string could still contain ( ' ) for example. what CHtml::encode does, its just generating the HTML equivalent, so that you get html entities instead.
I have posted a link to yii forum where you can find best answer.
Yii Forum Link
CModel Model class is base for both CFormModel & CActiveRecord.
CActiveRecord is used when we perform CRUD operation with a table of a database & needs variable definition according to them.
CFormModel is used when we don't need CRUD operation but a logical operation like Login Form. Here we don't use any table for the model.
This is called Premature Optimization Syndrome as you are blocking your development with early and unnecessary optimization.
Develop your application first with the best model/schema as you can, only after look for the bottlenecks and ways to increase performance, load time etc.
Yii implements two kinds of models:
form model
active record.
Both extend from the same base class CModel. A form model is an instance of CFormModel. Form model is used to keep data collected from user inputs. Such data are often collected, used and then discarded. For example, on a login page, we can use a form model to represent the username and password information that are provided by an end user. For more details, please refer to Working with Form
Active Record (AR) is a design pattern used to abstract database access in an object-oriented fashion. Each AR object is an instance of CActiveRecord or its child class, representing a single row in a database table. The fields in the row are represented as properties of the AR object. Details about AR can be found in Active Record.
Source
Related
I have been trying to learn about MVC pattern (without frameworks), however no matter material I read on the Internet, it just seems to be contradicting itself all the time.
My project right now consists of a form that can be submitted in order to add an element to the database. Another page just lists all the elements that are on the database.
So as I understand, my model should connect to the database (or just take the connection as a parameter, something else that was not very clear to me) and have functions like "saveItem" (which takes the $_POST variable as an input and parses it) and "listItems" (which just returns all entries to the page).
However, where does the controller come in? Now I parse my data in the model. But, if that should be rather done in the controller, what does the model actually do? I came across this page. Here, the model only has methods like "select" whose input is just a sql query. But this seems essentially just a PDO wrapper. (Contradicting information in this page about PDO already being a kind-of wrapper and there isn't really any need to do it.)
I guess it kind of makes sense, if the model was written as just a wrapper, it wouldn't actually have anything to do with the specifics of my website. (My understanding now is that each part of mvc is highly specific for each project.)
But then, it seems that either the model or the controller is just unnecessary. Either model parses the data leaving nothing for the controller to do or vice-versa.
I would be deeply grateful for any clarification.
I'd take this question rather as a genuine inquiry than a request to review some SEO spam article from Internet. So it goes:
What you need to understand in the first place is that the term "model" is ambiguous. It can represent either the whole application's business logic, or just what you meant - some piece of code that interacts with the database. To avoid this ambiguity, let's stick with the former. It will help you to settle with the Controller. Whereas we will call a "lesser model" a storage. A cover term for a code which actually interacts with the database.
I have a very concise writeup, MVC in simpler terms or the structure of a modern web-application. It will help you to wrap your head around MVC at whole.
Now closer to your question.
A database wrapper cannot be considered a model, in either meaning. A database wrapper is a service used by the storage class. So, you can have at least 3 layers in your application:
a controller. Just an interface to convey an HTTP client's request to the business model
a service or a helper. the code which is usually (and wrongly) written in the controller. For example, if you need to register a user, in the controller you are calling a method from a user service, providing the data came from the client.
a storage class. The actual code to interact with a database. For example it could be a User class that contain methods such as register and such. This class would use PDO (or some more advanced wrapper, or an ORM instance) as a class variable.
Where the latter two should actually encapsulate your whole application's business logic.
The most tricky part here is the instantiation of the Storage class. Given the connection must be done only once, there should be means to instantiate the UserStorage object providing it with the database connection. That is slightly different issue which is solved by means of the Dependency Injection Container
To illustrate the above with a bit of code
class UserController extends Controller
{
public function create($request)
{
$userService = $this->serviceContainer->get('user_service');
$userService->create(
$request->email;
$request->password;
);
}
}
class UserService
{
public function create($username, $password)
{
// here, userStorage instance was already injected
// in the UserService in the controller by DI container
$this->userStorage->create(
$request->email;
$request->password;
);
}
}
class UserStorage
{
public function create($username, $password)
{
$sql = "INSERT INTO user VALUES (null, ?, ?)";
// here, db instance was already injected
// in the UserStorage in the controller by DI container
$this->db->prepare($sql)->execute([$username, $password]);
}
}
It could be considered unnecessarily verbose, with all these seeming repetitions, but there are reasons for that:
in the real code there are other parts in the each stage, For example,
Controller would validate the form submitted (like whether the form was actually submitted, whether passwords are equal, etc.) and call View to render the form.
UserService could perform additional validations, like whether such email already exists
Different calling points
UserService could be called from many differnt places: from the above controller or a command line utility, or a REST controller.
UserStorage could be called from even more places. For example there is a TaskService that lists tasks belong to users, and it will naturally make a good use of the UserStorage class. And so on.
So it makes a perfect sense to separate your layers this way.
Of course it's just an oversimplified draft model, it doesn't implement an ORM which is usually here, and many other things. But the simpler the sketch is, the less details it have, the simpler to get the main idea.
I came across this page. Here, the model only has methods like "select" whose input is just a sql query. But this seems essentially just a PDO wrapper.
You're correct. In fact, this example is very poorly structured, and does not conform to any sensible conception of MVC design. I would recommend that you disregard it entirely and look for a better example.
The DB class (allegedly a "model") in this example is a database helper class. While this is a useful thing to have, it is not a MVC model in any sense, and this one is not particularly well written, either.
The Users class (allegedly a "controller") is not a controller. It is actually more akin to a model, as it attempts (awkwardly) to represent a business object as a class.
(As an aside, extending a database helper class is a design "smell" which should be avoided -- it means that every object instantiated will create its own separate connection to the database.)
The list.php file (allegedly a "view") is not much of a view, either. While it provides some presentation functionality, it also takes on the role of a controller by operating on the model. In most MVC applications, views are implemented as pure template files -- often not even executable code -- which are passed data by a controller.
Now that we've properly torn apart this terrible tutorial:
A common architecture in MVC applications is the active record pattern, in which each table in your database (other than purely relational tables) is represented by a class, each row from those tables which has been loaded by your application is represented by an instance of that class, and each of those instances has methods which can be used to manipulate the contents of that row.
Implementing such an architecture usually requires some form of database mapper or ORM framework.
I'm building an application in CakePHP 3. It uses a number of legacy databases which are not built in the Cake conventions.
I do not want to use any of the ORM features Cake provides, as it's more tedious to set up all the relations than just write "Raw SQL". We are also not going to make any changes to the database structures, so the ORM is a non-starter. So I'm going to write raw SQL queries for everything.
However, I'm not sure where this code would be put. I've read https://book.cakephp.org/3.0/en/orm/database-basics.html#running-select-statements but it doesn't say where you actually put that code.
I don't want to put my queries in a controller ideally since that defeats the purpose of MVC.
All I really need is one Model where I can put all my queries in different functions and reference them in my Controller(s).
In Cake 2.x it was easy to just create a model under app/Model/ then load it (loadModel) where needed in controller(s). But with the new Cake 3.x Table and Entity spaces, I'm not sure how this fits in?
I've also read up on Modelless Forms but don't think they're right either. For example the initial page of the application shows a list of chemicals which is just a SELECT statement - it doesn't involve forms or user input at all at this stage.
Obviously there will also be situations where I need to pass data from a Controller to the Model, e.g. queries based on user input.
As mentioned in the comments, I would suggest to not ditch the ORM, it has so many benefits, you'll most probably regret it in the long run.
Setting up the tables shouldn't be a big deal, you could bake everything, and do the refactoring with for example an IDE that does the dirty work of renaming references and filenames, and then set up the rules and associations manually, which might be a little tedious, but overally pretty simple, as there shouldn't really be much more to configure with respect to the database schema, than the foreign keys, and possibly the association property names (which might require updating possible entities #property annotations too) - maybe here and there also conditions and stuff, but oh well.
That being said, for the sake of completeness, you can always create any logic you want, anywhere you want. CakePHP is just PHP, so you could simply create a class somewhere in say the Model namespace (which is a natural fit for model related logic), and use it like any other class wherever needed.
// src/Model/SomeModelRelatedClass.php
namespace App\Model;
class SomeModelRelatedClass
{
public function queryTheDatabase()
{
// ...
}
}
$inst = new \App\Model\SomeModelRelatedClass();
$results = $inst->queryTheDatabase();
See also
Cookbook > Database Access & ORM > Associations - Linking Tables Together > BelongsTo Associations
I have a couple quick conceptual questions about saving models in PHP's Yii framework. I've run into this code a couple of times $model->save() (for example if($model->save())....
but I've never quite understood what it means.
Also, I read in the MVC Tips/Handbook that we should try to save our models in the model and not the controller - could someone explain why that is? I have a friend who has told me that it doesn't matter - but, I'd like to understand the rule behind it.
Thank you for you help!
What does $model->save() do?
Just check the source, it's on github. Apply logic, and the answer is pretty predictable.
As the docs clearly state: the BaseActiveRecord represents a data object. It could be a row returned from a MySQL query, or a processed form being sent by a client, or a MongoDB document, or whatever.
Calling save on that object either inserts the data into the DB you chose, or attempts to update that record. Depending on the insert/update call being successful, it returns a boolean (true if save succeeded, false if it failed).
It's pretty intuitive, really. If you want to learn more about the tools/frameworks you are using, common sense dictates you check out their online documentation. Yii's docs seem to me to be pretty comprehensive and easy to navigate: check them here.
Why save models in the Model?
Well that's easy, but it requires some disambiguation. The term "model" is often used to refer to the data containers. The objects on which you call save in this case. They are data models, true enough, and they are used to carry data back and forth throughout your application. In Yii, what some call models are called "ActiveRecords".
In the acronym MVC (as you know Model View Controller), the Model part actually covers a lot more than mere data containers. That "Model" (with a capital M) refers to the Model layer, also known as the logic or business layer. It's the part of your application that actually will contain the bulk of the code. It's there where the more complex computation is handled, it's the layer where you'll connect and query the DB. And it's this layer that has methods that the controller will call. These methods will then return data models (lower-case m) containing the data or the result of the computation that the controller will then pass on to the view.
If you want to know what logic/jobs/classes make up the Model layer, simply ask yourself this simple question: "What doesn't this bit of do?" If it doesn't handle the raw request, and it doesn't present the data to the user (those are the jobs of the controller and the view respectively), it's part of the Model layer, with the exception of a router component, dispatcher and all that that ties an MVC framework together, of course.
Controller actions (the methods in a controller, obviously) should, therefore be quite small. All they really do, 9/10 times, is pour the request data (form submissions and the like) into a model, and call one or more methods on a service (which is part of the Model layer). These methods will receive the models created in the controller as arguments, and set to work with them.
The controller can perform some basic validation, but the Model layer will dot the i's and cross the t's.
Once the Model layer has done its job, it's back to the controller which has only two things left to do: Did the Model layer return data that it expects or not? If so, pass it on to the view. If not (an exception was thrown or nothing was returned) -> handle the error/exception and, if required, redirect the user.
So in short: The Model layer is the bulk of your code, and it communicates with the controller (and internally) through data models. The Model layer never communicates with the view directly, nor does it redirect the user or handles raw input like $_POST data.
Here's a couple of links to posts of mine where I explain this even further, complete with graphs and what not. They are code-review answers, so ignore the bits that deal with the code itself, but the background information may be relevant to you:
CodeReview: How to put XML results in the MVC pattern?
CodeReview: PHP MVC: how to do $_POST the right way
As I understand in your case $model variable it's instance of BaseActiveRecord class.
So when you call:
$model->save();
Yii run mechanism to insert/update data in data storage.
The save() method return true or false, which does mean model saved or not.
So when you write:
if ($model->save()) {
//some code will be here
}
you check saved model or not.
This tutorial describe how Yii implements MVC practices.
It will insert a new row into the table that the model represents.
i.e. If I have a model called $user that represents a table called users, then calling $user->save(); will insert a new row into the users table.
if($model->save())
Would be the same as:
//Attempt to insert row
$inserted = $model->save();
//If insert is successful.
if($inserted){
//Do this
}
Note that many frameworks will also allow you to update a table row via the save function. In those cases, a where condition is attached or the primary key of the row is passed in.
$model->save() are using for insert and update data in database.
The last few days, I have extensively read books and web pages about OOP and MVC in PHP, so that I can become a better programmer. I've come upon a little problem in my understanding of MVC:
Where do I put a mysql_query?
Should I put it in the controller and call a method on a model that returns data based on the provided query? Or should I put it in the model itself? Are both of the options I'm providing total garbage?
Materials on the subject of MVC
You could have listed the books you were reading, because most (if not all) php books, which touch on MVC, are wrong.
If you want to become a better developer, i would recommend for you to start with article by Marting Fowler - GUI Architectures. Followed by book from same author - "Patterns of Enterprise Application Architecture". Then the next step would be for you to research SOLID principles and understand how to write code which follows Law of Demeter. This should cover the basics =]
Can I use MVC with PHP ?
Not really. At least not the classical MVC as it was defined for Smalltalk.
Instead in PHP you have 4 other patterns which aim for the same goal: MVC Model2, MVP, MVVM and HMVC. Again, I am too lazy to write about differences one more time, so I'll just link to an old comment of mine.
What is Model ?
First thing you must understand is that Model in MVC is not a class or an object. It is a layer which contains multitude of classes. Basically model layer is all of the layers combined (though, the second layer there should be called "Domain Object Layer", because it contains "Domain Model Objects"). If you care to read quick summary on what is contained in each part of Model layer, you can try reading this old comment (skip to "side note" section).
The image is taken from Service Layer article on Fowler's site.
What does the Controllers do ?
Controller has one major responsibilities in MVC (I'm gonna talk about Model2 implementation here):
Execute commands on structures from model layer (services or domain objects), which change the state of said structures.
It usually have a secondary responsibility: to bind (or otherwise pass) structures from Model layer to the View, but it becomes a questionable practice, if you follow SRP
Where do I put SQL related code ?
The storage and retrieval of information is handled at the Data Source Layer, and is usually implemented as DataMapper (do not confuse with ORMs, which abuse that name).
Here is how a simplified use of it would look like:
$mapper = $this->mapperFactory->build(Model\Mappers\User::class);
$user = $this->entityFactory->build(Model\Entities\User::class);
$user->setId(42);
$mapper->fetch($user);
if ($user->isBanned() && $user->hasBannExpired()){
$user->setStatus(Model\Mappers\User::STATUS_ACTIVE);
}
$mapper->store($user);
As you see, at no point the Domain Object is even aware, that the information from it was stored. And neither it cases about where you put the data. It could be stored in MySQL or PostgreSQL or some noSQL database. Or maybe pushed to remote REST API. Or maybe the mapper was a mock for testing. All you would need to do, to replace the mapper, is provide this method with different factory.
Also, please see these related posts:
understanding MVC Views in PHP
testable Controllers with dependencies
how should services communicate between each other?
MVC for advanced PHP developers
Model and Entity Classes represents the data and the logic of an application, what many calls business logic. Usually, it’s responsible for:
Storing, deleting, updating the application data. Generally it includes the database operations, but implementing the same operations invoking external web services or APIs is not an unusual at all.
encapsulating the application logic. This is the layer that
should implement all the logic of the application
Here is the MVC Sequence Diagram which shows the flow during a http request:
In this case Model is the best place to implement the code realted to access database.
The model contains the domain objects or data structures that represent the application's state. [wikipedia]. So the model would be the place to make the database call.
In the 'classic' (lack of a better word atm) MVC pattern the view would get the current state from the model.
Don't make the mistake by saying that the model is for accessing the database. It's more than just accessing the database.
For one, don't use mysql_query() and family; they're being deprecated, so consider also learning about PDO and/or mysqli.
The model takes care of data handling; it provides an interface to the controller by which it retrieves and/or stores information. So this would be a primary place where database actions take place.
Update
To answer a question asked by the OP in the comments: "one generic model for the whole db or a model for each table/action?"
Models are meant to abstract away individual tables (although there are models that exclusively handle a single table); for instance, instead of asking for all articles and then query the usernames for the authors you would have one function like this:
function getArticles()
{
// query article table and join with user table to get username
}
How many models you will create largely depends on how big the project is and how inter-related the data is. If you can identify independent groups of data, it's likely that you'd create a model for each group; but this is no hard & fast rule.
Data manipulation can be part of the same model, unless you want a clear separation between read-only and write-only models (I wouldn't know of a situation that warrants this, but who knows).
To go even further, your model should not contain the database access code. This belongs to another layer outside the Model/View/Controller: this is called the persistence layer, which can be implemented using an Object-Relational Mapper such as the popular Doctrine 2 for PHP.
This way, you never touch any (my)SQL code. The persistence layer takes care of this for you.
I really advise you to have a look at a Doctrine tutorial, this is a really professional way to create your applications.
Instead of working with raw data loaded from the database, you create objects that hold your data, and the behavior associated with it.
For example, you might have a User class, such as:
class User
{
protected $id;
protected $name;
protected $privileges;
public function setName($name) { ... }
public function getName() { ... }
public function addPrivilege(Privilege $privilege) { ... }
public function getPrivileges() { ... }
}
You controller will only interact with objects:
class UserController
{
public function testAction()
{
// ...
$user = $em->getRepository('User')->find(123); // load User with id 123
$user->setName('John'); // work with your objects,
echo $user->getName(); // and don't worry about the db!
$em->flush(); // persist your changes
}
}
Behind the scenes, the ORM takes care of all the low-level work of issuing a SELECT query, instantiating your object, detecting modifications to your object, and issuing the necessary UPDATE statement!
What do you have in your model classes. Generally if i use any framework or any library (Zend Framework) , my classes only have variable which is table name . I know that in complicated applications models have lots of thing to do , so i want to know what these jobs are.
Maybe instead of using library`s general select function ,you create special functions to get data from database ( getUserById() ) . To sum up , which parts of the process should go in to model layer.
For example thing about general user processes .So in registration process where should we check email is acceptable or not . This is example just explain what do you do in your model layer.
This question may seem as an abstract question because of my english , but it is not . If you can edit it please improve it . The purpose of this question is better understanding of mvc pattern
Well, in general, models should do the main work regarding your business layer. So, if you have a pretty complex query using (and combining) the accessor functions of the database layer (thus, your model), you should instead write an extra function for that query in your model class. Makes it much easier to change the implementation of your model (e.g. database-table-wise).
EDIT: To answer your other question: validating an e-mail should happen in the controller, usually using some kind of component, utility class or library...