Is it OK to call model's function in views?
I need to make a table with table-child insides it.
Just like this:
row1
row1.1
row1.2
row2
row2.1
row2.2
row3
row3.1
row3.2
CONTROLLER:
$data['test'] = $this->model_test->get_parent_row()->result_array();
$this->load->view('test_view', $data);
I use multi-foreach in views; first foreach to show every single parent row, and the sub-foreach to show the row-child. But it means I have to call a query to get the row-child based on the parent row.
Any advise?
To keep the logic in the controller, I would recommend to create two different views. One with the child-row data, and one with the parent data. The secret is to pass the parameter TRUE when calling the view to return the data into a variable instead of printing it out to the browser. Something like this in the controller:
$parent = $this->model_test->get_parent_row()->result_array();
$children = ''; // INITIATE STRING TO STORE ALL CHILD VIEWS...
// LOOP THROUGH PARENTS...
foreach($parent as $child){
// CREATE YOUR QUERY TO GET CHILD ROW HERE...
// ADJUST TO WHATEVER YOUR MODEL NAME OR PARAMETERS ARE:
$child_row = $this->model->get_child_row($child)->result_array();
// THE TRUE PARAMETER RETURNS DATA FROM THE VIEW INSTEAD OF OUTPUT TO THE BROWSER
$children .= $this->load->view('child_view', $child_row, TRUE);
}
$this->load->view('parent_view', array('test'=>$children));
Hope you understand the logic. Find more info about views in the documentation (scroll down to the end): https://www.codeigniter.com/user_guide/general/views.html
Easier would be to create a model that returns all data at once, and then pass the array to one view where you can loop through all parents and their children at once.
You can do this array structure inside your model
Try below logic to maintain parent-child logic and you can directly pass it to your view.
On model:
function your_function_name() {
//select parent category
$parent_array = array();
$query1 = $this->db->get('parent-table');
foreach($query1->result() as $row1) {
$child_array = array();
// query for children
$query2 = $this->db->get('chilr-table')->where(id, $row1['id']);
foreach($query2->result() as $row2) {
$child_array[] = array(
'id' => $row2['id'],
'name' => $row2['name']
);
}
$parent_array[] = array(
'id' => $row1['filter_group_id'],
'name' => $row1['name'],
'children' => $child_array
);
}
return $parent_array;
}
On Controller :
Load your model
$this->load->model('model_name');
pass to view
$data['test'] = $this->model_name->your_function_name();
$this->load->view('test_view', $data);
I hope it will help you
Related
I'm fetching data from database, inside foreach loop i have to add one array index list_array
$list = Lists::where('name',$request->name)->get();
$Data=[];
foreach($list as $key => $list_row)
{
$list_row['list_array'][]=$list_row['data_1'];
$list_row['list_array'][]=$list_row['data_2'];
$Data[]=$list_row;
}
It should be of array type but when i declare it as array it is not working,
message: "Indirect modification of overloaded property
App\Models\Lists
Any solution to create list_array as an array index inside foreach loop. Thanks
You are not dealing with an array, you are dealing with an App/Models/Lists model. What you probably instead want to do is adding a custom attribute to the model. This happens one step before.
// your model
class Lists
{
protected $appends = ['list_array'];
public function getListArrayAttribute()
{
$data = [
// your array data from where ever
];
return $data;
}
}
You then can access (without adding it when you want to access the data) the new attribute from within the model, like so:
// where you access your data
$lists = Lists::where('name', 'whatever')->get();
foreach($lists as $list) {
dd($lists->list_array)
}
You can read more about the so called Accessors here:
https://laravel.com/docs/8.x/eloquent-mutators#defining-an-accessor (Laravel 8)
https://laravel.com/docs/9.x/eloquent-mutators#defining-an-accessor (Laravel 9)
I hope I got the intention of your question right. From your question it's not very clear what data you want to add and where it is coming from. There might be other and better ways too.
Edit:
Based on the comment from #user3653474 the Accessor function could look like this.
public function getListArrayAttribute()
{
$data = [
$this->data_1,
$this->data_2,
];
return $data;
}
data_1 and data_2 are the column names in the table of the same model.
I fetched data from model in controller . i want to display this data in view inside another view. its showing blank page.
here is my code..
controller -
public function Listblog()
{
$listblog=$this->Login->listblog();
$listblogwithpage=$this->load->view('list_blog',$listblog);
$this->load->view('Welcome_message',$listblogwithpage);
}
model -
public function listblog()
{
$query=$this->db->get('new_employee');
return $query->result();
}
To assign a view to a variable the 3rd param must be true:
$listblogwithpage=$this->load->view('list_blog',$listblog, true);
Further the 2nd param must be an array. E.g. $data['listblog'] = 123;
$var = $this->load->view('somepage', $data, true);
This applies to any usage of view.
If you want to pass data from a controller to the first view and then have the second view pass data to the second view, you should do the following, always remembering that CI expects data passed to a view to be in form of an array. Take this and feel free to adapt it to suit your needs
In controller:
// populate an array and pass it to the first view
$first_view_data = array(
'listblog' => $listblog_query_result,
);
$this->load->view('firstview', $first_view_data);
In the first view, populate a new array with whatever data you need and call the second view from within the first one, passing the second data array:
$second_view_data = array(
'second_data_var' => $variable,
'other_data_var' => $other_var,
);
$this->load->view('second_view', $second_view_data);
CI is intelligent enough to let you call a view from within a view and pass data from each to the next in this way. Just remember, it has to be an array.
Using the data:
In the first view you'd call $listblog
In the second view, you would access $second_data_var and $other_data_var
$listblog $second_data_var and $other_data_var each could be single variables, arrays, objects and mostly anything as long as they are passed to the view as elements of an array
try this way.
//Controller
function Listblog() {
$data = array();
$data['listblog']=$this->Login->listblog();
$this->load->view(''list_blog',$listblog');
}
in view page you have to call that data array $listblog
I am new to MVC, I am porting a project written in non-MVC style to MVC, but I am stuck on a problem where it is necessary to call Model function in View.
Scenario:
Table1 - Products:
contains product_id, product_name etc. and for each product there can be multiple versions.
Table2 - Versions:
contains version_id, version_name, ... , product_id etc.
Now in the View I am displaying products and under each product heading I have to display version list of that product, in non-MVC style it was pretty simple, I can use the following code snippet in View:
foreach ($product as $row)
{
echo $row['product_name'];
if ($main->getVersionList($vresult,$row["product_id"]))
{
foreach ($vresult as $vrow)
{
echo $vrow['version_name'];
}
}
}
Now, I can pass Product array from controller to view but what about each Version array which needs to be generated corresponding to each product?
Update:
This is my final working solution (used a map), in controller:
$this->load->model ( 'product_mod' );
$data ['products'] = $this->product_mod->getProductList ();
$data ['versions'] = array ();
foreach ( $data ['products'] as $product )
{
$data ['versions'] [$product['product_id']] = $this->product_mod->getVersionList ( $product['product_id'] );
}
MVC or not to MVC
The first thing I should note is that It is impossible to write classical MVC in PHP. In fact the MVC-like PHP frameworks such as CodeIgniter or Yii implements sort of MVP in which:
view is passive and unaware of model
presenter (controller) changes state of model, reads information and passes it to view
Credits to tereško
CodeIgniter Approach
However, particularly in CodeIgniter, you have 3 steps:
Create a Model to query through the database and return the data (as an array or object)
Create a Controller to load and fetch the result from the Model (a method of the Model), and pass the returned data to the view
Create a View and use PHP loops to echo the result out, build the HTML.
Getting all together
Considering the above approach, you need to fetch the result from the database in your Model:
application/models/product.php
class Product extends CI_Model
{
public function get_product($product_id)
{
$this->db->select('*')->from('products');
$this->db->where('product_id', $product_id);
$this->db->join('versions', 'versions.product_id = products.product_id');
$query=$this->db->get();
return $query->first_row('array');
}
}
Then fetch and pass the result within the Controller:
application/controllers/products.php
class Products extends CI_Controller
{
public function view($product_id)
{
$this->load->model('product');
// Fetch the result from the database
$data['product'] = $this->product->get_product($product_id);
// Pass the result to the view
$this->load->view('product_view', $data);
}
}
Finally, use the returned data in the view, to generate the list:
application/views/product_view.php
// Use $product to display the product.
print_r($product);
You should do mysql query in your model, for example products_model (don't forget to load it)
Example Query : This is just select * from products
public function All_Products()
{
$this->db->select('');
$result = $this->db->get('products')->result_array();
return $result;
}
So as I see , you are foreach guy like me, rather than using mass queries.
In your controller you could load $products my your model.
$products = $this->products_model->All_Products();
My solution is creating a new array then putting new values in it.Also you need to getVersionList function in your model.
$newArray = array ();
foreach ( $products as $values ) {
$version = $this->products_model->getVersionList($values['product_id']);
$tmp = array (
'product_id' => $values ['product_id'],
'product_name' => $values ['product_name'],
'version' => $version
);
array_push ( $newArray, $tmp );
}
So add your new array to $data you could have them in your view file.
$data ['products'] = $newArray;
Sorry I didnt figure out all your queries but I think its better to teach how to catch fish than giving a fish.
Using the below code you can call the model's method in the view file. It's worked for me and is so simple also.
$CI =& get_instance();
$CI->model_name->method_name();
I've a custom data provider in my Model
I tryied this in controller
public function actionMonthTotal()
{
$model=new Rapporti();
$this->render('monthTotal',array(
'dataProvider'=>$model->monthTotal(),
));
}
Where monthTotal is the model function that give me a DataProvider
Actually 'monthTotal' is a copy/past of view.php and it uses a clistView using _monthTotal, that is a copy/past of _view.php
I Need to simply get the dataset from dataProvider (a 'SELECT COUNT, SUM, SUM, etc...") and iterate into recordset to echo a simple TABLE into monthTotal view . So ...
how to use a dataProvider from a view to get records and how to iterate trough recors?
My month total is this and is in 'Report' Model
Actually report is in a relation Report N -> 1 Pionierato (sorry for italian terms, but are only object names)
public function totalMonth() {
$criteria = new CDbCriteria();
$criteria->with = array ('pionierato');
$criteria->condition = 'dataBetel=:month';
$criteria->select = "COUNT(t.id) as numProclamatori,
pionierato.tipo as tipoPionierato,
SUM(libri) as sommaLibri,
SUM(opuscoli) as sommaOpuscoli,
SUM(ore) as sommaOre,
SUM(riviste) as sommaRiviste,
SUM(visite) as sommaVisite,
SUM(studi) as sommaStudi";
$criteria->group = "t.dataBetel, t.pionieratoId";
$criteria->params = array ('month' => "2012-09-01");
$dataProvider=new CActiveDataProvider('Rapporti',
array ('criteria' => $criteria)
);
return $dataProvider;
}
I need to use this dataprovider to get the 3 record it will output and print a 3-row table. Static.
Using suggestion from first answer, i got this:
I obtained the result in this way:
<?php
foreach ($dataProvider->getData() as $id => $singleRecord) {
$this->renderPartial('_monthTotal', array('data' => $singleRecord));
}
?>
and removing the clistview widget.
But your answer helped my a lot, so I'll give my preference to you, thanks !
Try:
public function actionMonthTotal()
{
$model = Rapporti::model()->monthTotal();
$this->render('monthTotal',array(
'dataProvider'=>$model,
));
}
That should work, you are creating an object with the name $model which has a value equal to the return value of the method monthTotal() in the Rapporti model
If that doesn't work, check that you are actually getting a result from your monthTotal function by copying it (minus the return part) into your controller instead of calling it from the model.
In your monthTotal view you can iterate through the active records using CListView like so:
<?php $this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_view',
)); ?>
Each iteration calls in a subview called "_view". The data for that record can be accessed using $data (eg: $data->id);
Here is an example of querying without using CActiveDataprovider:
$model = Rapporti::model()->findAll(array(
'condition' => 'dataBetel=:month',
...
));
You can try that... Alternatively you can use findAllBySql() instead of findAll() and type in your query that way. You will then be able to iterate through your data set using a foreach() loop
I'm having trouble getting the results of a has_many query using php idiorm/paris. Following the example from the paris site the has_many result for posts returns as an object.
That's great, and I can run through the object and access individual methods, but what I want to be able to do is pass the result set as an associative array off to my template engine for display.
Example:
class Post extends Model {
}
class User extends Model {
public function posts() {
return $this->has_many('Post'); // Note we use the model name literally - not a pluralised version
}
}
The api works this way:
// Select a particular user from the database
$user = Model::factory('User')->find_one($user_id);
// Find the posts associated with the user
$posts = $user->posts()->find_many();
I am able to access the posts object and print the result set like this:
// echo each post id
foreach ($posts as $post) {
echo $post->id;
}
What I'd really like to be to do though, is use as_array() to get the entire resultset as an associative array, limited by certain fields in the way as_array works for an individual row, e.g.
$post_list = $posts()->as_array(id,title,post,date);
This, or a call on something like $user->posts()->find_many()->as_array() don't work.
What is the correct way to access this type of result set using paris?
Adding this method to idiorm.php gives me the desired functionality.
public function find_array() {
if (func_num_args() === 0) {
return $this->_run();
}
$args = func_get_args();
$array = array();
foreach ($this->_run() as $r) {
$array[] = array_intersect_key($r, array_flip($args));
}
return $array;
}
Now I can call $post_list = $posts()->find_array(); or $posts()->find_array('id','title'); etc.
find_one returns a Model object, find_many returns an array of Models.
If you want to get the entire result set as an array of associative array, one solution should be to use array_map
function model_as_array($model) {
return $model->as_array();
}
$posts = $user->posts()->find_many();
$my_view->posts = array_map(model_as_array, $posts);
var_dump($my_view->posts);
or in php 5.3+ (not tested)
$aa_posts = array_map(function($model) {return $model->as_array();} , $posts);