yii framework : how $dataProvider get data and how it works? - php

I am learning YII framework and I am at a beginners level.
I created a CRUD option and I found the following script my view file
<?php $this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_view',
)); ?>
But I don't understand How $dataprovider got the data from data base, I didn't see any related function on the Model class, also how can I update the data is $dataprovide, ( I have to replace one foreign key with correct data ie family_id with family_name)

Yii Data providers (there are many, the easiest way is to use CActiveDataProvider) are just data containers that can be used, for example, to populate a grid (CGridView widget, for example) or
The controller is the part of your application that feeds data into your views. You probably have a line or two of code in your controller where you create this data provider so you can send it to your view.
You can create a Data Provider by yourself (documentation of class CActiveDataProvider), just by instantiating it, but if you used gii or some simlitar device to generate models, then your model class should have a search() method. This is a helper method created for you so that you don't have to instantiate the data provider yourself. (when this method is called, a new CActiveDataProvider is returned)
As I said, a data provider is just a container of models. In your case, (as you are creating a CListView), it probably contains just one Model (the model whose details you are trying to display). Data providers can also be used for grids and in that case one data provider will hold not one but many models (in general, one per grid row).
p.s.: If you need to change things like foreign keys and/or attribute names, you need to do it in your Model class (that is, your ActiveRecord), not in the data provider. The data provider - and any widgets you use - are only used for displaying purposes.

Related

PHP MVC - One view class for all controllers vs a view class for each controller

I am creating an MVC inspired PHP framework, mainly for learning purposes.
I basically have the framework created and am building an app on it and improving the framework as i go along.
I am still confused/not sure about certain aspects of this sort of architecture, and at the moment i am questioning my implementation of the View part.
How i have set up my framework:
Its a very simple set up, for example: you go to the url /post/post_id, this will load index.php which will instantiate the router. The router will then check the url and instantiate the correct controller and method based on the url. In this case it would be PostController, and the method would be a default method that would use the post_id to get the posts data from the relevant model. Next the controller would set up a "data" variable that will hold the data to pass on to the View, and this is where i am confused - should it send to its own View object (a view class file dedicated to the PostController), or to a generally used View class that is used by all controllers to load an html file?
At the moment my controller is sending data to the View class, this data includes what template file should be included/shown, and the actual data for the page (what we got from the Model through the controller).
My question is this:
Should this type of system have one View object that renders all of the views (html files) based on what data is given to the "render" method, or, should each controller that eventually sends data to the View have its own View object/class?
Meaning, should PostController send a request to the general view class, the same one that is used by all controllers to renders pages, or should the PostController send to a dedicated View Class (call it PostView if it makes it clearer), and this class will then render the specific html file?
Basically if it should be one View class for all controllers that will render what ever html file the controller tells it to, or if there should be many View classes, one for each page load.
NOTE:
I know a lot of questions have already been asked about MVC in PHP, but i could not find an answer to my question in any of the answers.
A bit about MVC:
In the original MVC pattern (presented by Trygve Reenskaug in 1979), the controller updates the model, the model notifies the view about the changes, and the view pulls its data from it. Though the pattern was thought for desktop applications - each M-V-C "triad" beeing related to a single control in a window (a button, a textbox, a checkbox, etc). So, each control on the screen had an MVC "attached" to it.
Since, in web applications, the model-to-view notification step is not (or can not be) present, the original pattern can not be applied as is to them.
But a most similar approach can still be relatively easily implemented: the controller updates the model, the view pulls data from it (irrespective of the controller). I think it's called "Web MVC Model 2".
There is a multitude of web MVC variations. You are using one in which the controller takes the role of an intermediary between the model and the view.
So the controller is the only one component communicating with the model.
The view's responsibility:
The responsibility of the view component is the presentation logic - which should not be assumed by the controller at all. Beside loading and rendering template files, this kind of logic involves the preparation of the data fetched from the model for displaying purposes. The result of the preparation should, preferably, be a list of values of primitive types (strings, booleans, integers, arrays, etc) which can be easily "injected" into the template files during the load-and-render process.
Examples of presentation logic:
Example #1: If you would fetch the value 123.45 (from the column amount of a table revenues) from the model, the presentation logic would consist of formatting it to the string 123.45 USD, in order to be displayed in a template file.
Example #2: Formatting a fetched date value of 28/05/2019 to 2019-05-28 by using a code snippet like this:
$fetchedDateFromModel = '28/05/2019';
$time = strtotime($fetchedDateFromModel);
$formattedDate = date('Y-m-d', $time);
The value of $formattedDate would then be "injected" into a template file.
Example #3: Setting a boolean value based on some model data, in order to be used in a template file for deciding if a button ("Get Bonus") should be active or not.
$paidAmount = 512.79; /* model data */
$isActiveGetBonusButton = false;
if ($paidAmount > 500) {
$isActiveGetBonusButton = true;
}
The answer (in respect of your chosen MVC approach):
By using a View instance in all controllers, you would be forced to perform specific presentation logic in each controller - before passing its result (e.g. the list of the prepared values) to the used View instance, in order to further just be "injected" in a specific template file.
Whereas, if you are implementing a dedicated view class (like PostView - which, preferably, inherit a base class View containing the render() method) for a controller class (like PostController) - so a 1:1 relationship, but see it as a loose one! - you can pass the data fetched from the model, in an unprepared form, from the controller to the view. The view class would then correctly take the responsibility of preparing the data for displaying prior to actually load and render a specific template file. E.g. of performing the whole specific presentation logic.
Note: In "Web MVC Model 2" - where, ideally, the controller has no knowledge of the view component - the above argument is more obvious:
the PostController just updates the model (when an update step is required);
the PostView fetches data from model, prepares it for display, and displays it (by loading & rendering a template file like posts.html.twig, for example). In other words, the view component performs the whole presentation logic by itself.
The best way, IMO, is to have this View or Template class do all the work related to views with just one simple method: render(string $templateName, array $context = []).
This allows for easy extension or creation of adapters. You should make your controllers use this method. If you use a DI Container in your framework, you could do a TemplatingAwareInterface and implement that with a trait that allows setter injection. That will inject the templating service on fetching from the service container. That way, you can use $this->templating->render() in your controller, without having to either make it global, nor constructing the templating service inside the controller, nor injecting the container into the controller.
Having one view class for each type of controller is cumbersome, harder to maintain and I don't really see a reason for it.

Cakephp calling component from Model

One of my views have to display data that is from an external API call.
To manage all of these API calls i have create a component.
Now in order to costum paginate i have to create a function inside of my model however since i'm not using the models table but instead the component i have to call that component inside my model.
Is this possible or is there a work around?
To manage all of these API calls i have create a component.
This is plain wrong, mostly because you don't have to. Technically you can but it would be wrong architecture wise.
The most correct way to implement API access in CakePHP would be to create a data source for that API and use that data source with a model.
The data source page in the CakePHP book comes with a complete example of how to create a data source that calls a foreign API.
Doing it as a data source allows you to use the API with multiple models which makes sense if the API provides different things. For example you could have a GithubUser and a GithubRepository model using a GithubDatasource. Also the data source is easier to test then a component.
I will suggest better to implement all functionality of component into model by creating functions within model.
And you can share that model for multipal controller.
and as your problem, over here you can use your model function within model.

Should models representing a single row return data generated using multiple rows?

Some background:
This is for an MVC application built without using any frameworks, but follows the MVC paradigm.
I am using an ORM library called RedBean to talk to the database.
While RedBean represents data using "beans", it supports wrapping them into a model, so custom functions may be provided by the model:
$account = R::dispense('account');
$account->name = "john";
R::store($account);
$account->getFormattedLastUpdatedTime('America/New_York');
Now the question:
Currently, each instance of the model would represent 1 row in the database. If I have a collection of accounts, then I would have an array of "account" models.
In the application, I have a feature for custom profile fields (don't worry, I am not using EAV though :)). One of the tables stores metadata for those fields (name, description etc) for generating the form fields for those custom profile fields. Once again, each row of the metadata represents 1 form field and each row is represented by 1 model.
I now wish to write a method to convert all those rows into a form object which can then be used for rendering and processing the form. But, where should this method live? My initial thought was to place it in the model representing the custom profile field metadata.
Clarification: This function would not be in the account model, but instead in the profile_fields_meta model.
Problem
As each model should represent 1 row, it seems a bit "dirty" to have the model return an object that would be generated from MULTIPLE rows in the database. Am I correct to say this is not the best way to do it? What do you recommend I do instead?
It would be right to have extended ArrayObject (http://php.net/manual/en/class.arrayobject.php) or other container class to run methods for collection.
Try to modify query methods to return data in your custom collection class instead of array if specified.
There's nothing inherent to MVC that says "each model [instance] should represent one row." Often in MVC frameworks the model (as seen by the controller, at least) is entirely ignorant of the data store and doesn't have any concept of or direct mapping to a "row." This isn't necessarily the case with ORMs but a model needn't adhere to an ORM's constraints.
However, though it's hard to tell without knowing more about your schema and implementation, the functionality you're describing doesn't sound appropriate for your Account model. In fact, it sounds to me like you should consider having a "FormField" model such that, in Rails parlance, Account "has many" FormFields.
And for the record, EAV isn't always bad, it's just often misused.

CakePHP: Can I create a function in a controller that doesn't have an associated view?

I have an index action in my users_controller that get a list of users. For each user i want to calculate the number of projects they have associated (one user => many projects). I was thinking of using a method like getProjectTotal and calling it for each user. Would I put this method in the users_controller and call it like
$this->getProjectTotal($id)
in the view?
Thanks,
Jonesy
Sure. It sounds like this is just a helper method based on the call. I do that all the time. I'll typically set the method visibility to private or at least protected to keep it from being called accidentally in a rendering scenario.
I'm still relatively new to CakePHP, but I've been using the built-in counterCache in Cake 1.2 to track the number of hasMany records for a parent Model in one of my apps. Create a field in your parent Model to store the hasMany count, and enable counterCache in the $belongsTo property for the child Model, and you're good to go. It automatically updates the counterCache count field in the parent model whenever the # of "hasMany" records increases/decreases. I like this method of tracking as it keeps the controller a little cleaner if all you need is the count without any other conditions.
Docs: http://book.cakephp.org/view/816/counterCache-Cache-your-count
Also, I'm still new to MVC, but I think if you're going to gather the count via a private/protected controller method, you'd want to call it in the controller and then send the data to the view, not perform the actual method from the view, in this scenario.
Also - yes you can make a controller method for work that isn't going to render a view - BUT - in your case you should use counterCache / a Model function since you are either fetching / counting / manipulating actual data related to the Project model and it's relationship with the User model and current logged in User specifically.
When building out my controllers I tend to stick to methods that render a view or return data for an element called from requestAction. If the method is computational or setting up variables but doesn't require a template or isn't called from an element I move it to a component / helper / model / behavior. Combined with a docblock with #requestAction in the flags for introspection and I can get a list of regular actions, and data returning actions without worrying that a controller is full of other methods.

Blog in CodeIgniter : Where Does the Model start, and the Controller End?

I'm testing CodeIgniter, and trying to create a simple blog. The video tutorial on the CodeIgniter site is nice, but very incomplete. I'm not too familiar with the MVC structure, and I am wondering exactly how a model is used. For instance, I'm currently doing the "admin" portion of my blog, which allows you to create, delete, and modify entries. The view only contains xhtml, and the controller takes care of the rest. What should be in the model? Does everything database related occur in the model (i.e. inserts, updates, selects, etc.)?
Depends who you ask.
Some people like to put as much as possible in the model (validation, data retrieval, etc), and have the controller just poke it to get the data it needs, which it then hands over to the view.
Think about it like this: if you have more than one controller accessing a single model, then shouldn't common things between them be in a common place (as long as that common thing actually has something to do with the model)?
The Model should contain everything database related, and perform all of the basic CRUD operations (Create, Get, Update, Delete).
The Controller should handle all communication between the model and the view. So for example, if you have a form for adding a new post, you should have a view for that form, which is called from a controller. The Controller would check to see if anything has been submitted, and if something has, call the create/insert method from the Post Model.
For me, model is a where I do all 'dirty' work for my data. I fetch, insert, update data to database, all in a model. I create 1 model for 1 table in the db.
Controller will be logic central for a page that I build. It need as slim as possible. If a function go beyond 1 screen, then it's too long (except if it do form validation which is must be done in controller). This is where Model come to play. Controller just pass the data into model. I do checking, processing, and formatting the data in model. My controller then fetch processed data from model, pass it to view, finish.
model = is object that "talking with your database"
view = is object that building user interface
controller = is the commander .. he got command from user and then he pass it on the model and serve to the user through view.
to create a simple blog, try to read Codeigniter getting started. it will help you a lot after you watch the video. the codeigniter references are good documented and well explained. try that first.

Categories