When I loop data from database I need value from that to query again. I query database directly from view. I want to know that is my code wrong? If wrong what is the better way?
foreach($data->result() as $row1) {
echo '<li>';
echo $row1->Name;
echo '<ul>';
$this->db->select('Photo');
$this->db->from('tblPhoto');
$this->db->where('User_id', $row1->User_id);
$photo = $this->db->get();
foreach($photo->result() as $row2) {
echo '<li>';
echo $row2->Photo;
echo '</li>';
}
echo '</ul>';
echo '</li>';
}
The way you're doing it will work, but you may want to consider separating your code to make your code more reusable. For example:
<~~~~ controller ~~~~~>
// your_controller.php:
$this->load->model('your_model');
$data = $this->your_model->get_data();
foreach($data as $key => $obj)
{
$data[$key]->photos = $this->your_model->get_photos($obj->User_id);
}
$this->load->view('test', array('my_data' => $data));
<~~~~ model ~~~~~>
// your_model.php
function get_data()
{
return $this->db->get('yourTable')->result();
}
function get_photos($user_id)
{
return $this->db->get_where('tblPhoto', array('User_id' => $user_id))->result();
}
<~~~~ view ~~~~~>
your_view.php
<?php foreach($my_data as $row1): ?>
<li>
<?php echo $row1->Name;?>
<ul>
<?php foreach($row1->photos as $row2): ?>
<li><?php echo $row2->Photo; ?></li>
<?php endforeach; ?>
</ul>
</li>
<?php endforeach; ?>
Ideally view is not right place to do this.
Firstly all data must be processed between controller/model and should be passed to view.
If case you have a scenario where you want to get data from view after rendering, you should make an ajax call from view to controller and then ask controller to get data from model(data layer).
And respond with data from controller to view and reflect html changes in view depending upon the data received if any changes required.
This is how an MVC architecture should be.
#lyhong, your code is programmatically right.
But, using Codeiginter MVC standards is advisable.
The queries should reside in Models.
So that they can become reusable.
Queries written in Views will serve only that view.
Also, if your write queries in View files, following issues should occur:
In case you do not get
$row1->User_id
the errors should be displayed directly on the page.
Also, it will load your view file slowly.
Benefit of sticking to MVC standards is huge extendibility.
The accepted answer is certainly as good as it gets. I would say that it's worth describing /WHY/ we don't make db queries inside the view. Imagine the view as just that - a view, or a way of viewing the data, or a version of viewing the data (it could be presented in many ways, and the version of how it's presented might change over time, such as they way FaceBook looks now vs. 10 years ago).
And an HTML view is only one way it could be presented; the data could be "viewed" as a PDF, a spreadsheet, a JSON package to be consumed by a microservice, etc. etc.. So if you're NOT calling a database for more information, it's a good indication that you've configured your data well, and it's likely it could be used in multiple ways, robustly.
OK, so guess what? Everything I just said is garbage. I hope you didn't believe it. In actuality, modern presentations and customization present their own complexities such that how the view is to be presented depends on what the data is, the resulting query of which is going to make the needed $data payload needed to be much more complex and possibly take unnecessary time for something that doesn't want to be shown. Run that through to it's logical conclusion, and you'll see the limitations of passing every possible scenario through the view data.
What #abhinsit said above about calling the ancillary stuff via AJAX is a valid point, but know that that adds complexity. But if done well it could save time and make things simpler overall. A good example is including the user information (Hello John Smith) by post-rendering with AJAX. Don't feel guilty if you see a valid need to call the database in the view, but try and structure your view (and your entire framework) so that the important things are already set in state.
Related
Thanks to sof for its support.
I have developed my site in codeIgniter. Now my client came up with a requirement that to put website in different languages.
I have checked with
http://backlink-generator.arxiki.com/free-translate-translator-translation.html
It provided a button for translation.But Iam confused whether it is the perfect procedure or not.Please help me Iam new to this concept.
I have even checked this
How to setup CodeIgniter for a truly multi language website?.
Mywebsite is fully developed .I just to make it work for different languages.
There will not be a one button solution for that.
You will need to use a Language library like this: http://jeromejaglale.com/doc/php/codeigniter_i18n
and then get all your texts in the language files , this means that under the language folder you will have a folder for each language you support and in there you will have PHP files with variables that will hold the texts for all the pages. this files will be duplicated to each language folder and the content will be then translated.
On your controllers you will load the right language file and then in the view you will just call the string variable name and according to the language the user is currently in it will pull the string from the language file.
The url of your application will be like this http:www.domain.com/en/controller
hope this helps
Change existing website to multi language website : codeigniter
For this you can use language class. See the steps,
Step 1:
create a new file content_lang.php in application/language/english/ for english language. create another content_lang.php file directory dutch for dutch language in application/language/dutch (Create a directory if not exist).
In this file we can write the different languages. Like,
application/language/english/content_lang.php
<?php
$lang['key']='en';
$lang['home']="Home";
$lang['about']="About Us";
$lang['login']="Sign In";
?>
application/language/dutch/content_lang.php
<?php
$lang['key']='dh';
$lang['home']="huis";
$lang['about']="over ons";
$lang['login']="Aanmelden";
?>
Step 2:
Put the language values at the view at the place text. application/views,
Like,
application/views/index.php
<ul>
<li class="current_page_item"><?php echo $language['home'];?></li>
<li><?php echo $language['about']?></li>
<li><?php echo $language['login']?></li>
</ul>
Step 3:
In your controller you can load the language files like,
application/controllers/users.php
function Index()
{ $languages = $this->session->userdata('languages');
$lg=$languages['language'];
if($lg=='en'){
$this->lang->load('content','english');
}
elseif($lg=='dh'){
$this->lang->load('content','dutch');
}
else{
$this->lang->load('content','english');
}
$data['language']=array(
'home'=>$this->lang->line('home'),
'about'=>$this->lang->line('about'),
'login'=>$this->lang->line('login')
);
$lg=$this->lang->line('key');
$data['val']=array(
'lang'=>$lg
);
$this->load->view('index',$data);
}
Here we can pass two language data and their key value for switching language to view. $data['language'] and $data['val'].
To change the language, (application/controllers/users.php)
function changeLanguage(){
if(isset($_POST)){
$this->session->unset_userdata('languages');
$lg=$this->input->post('sel_lang');
$lang=array(
'language'=>$lg
);
$this->session->set_userdata(array('languages'=>$lang));
redirect('users/Index');
}
}
Step 4:
Code to switching languages on views. (application/views/index.php)
<form id="frm_lg" action="changeLanguage" method="post">
<?php echo $language['lang_select'];?>
<select id="sel_lang" name="sel_lang">
<option value='en' <?php if($lang=='en'){?> selected <?php } ?>>English</option>
<option value='dh' <?php if($lang=='dh'){?> selected <?php } ?>>Nederlands</option>
</select>
</form>
Like this way we can load nay number of languages.
Download the example code, Github
When I use Massive ORM to retrieve a record using the .Find() method, it returns a Massive.DynamicModel.Query object which doesn't get along very well with the ASP.MVC 3 View.
Controller:
public ViewResult Details(int id)
{
// Massive ORM Find syntax requires this next statement to use 'dynamic' not 'var'
dynamic table = new Things();
// Thing will return as type Massive.DynamicModel.Query
var Thing = table.Find(ThingId:id);
return View(Issue);
}
In the View, I've tried both #model dynamic and #model Massive.DynamicModel.Query, but neither will allow me to access the properties of my 'Thing' object using the normal #Model.Name syntax.
There is some discussion on here about how to handle ExpandoObjects with MVC3 views, but nothing in particular about the Massive.DynamicModel.Query implementation that has worked for me so far.
Any general ideas how to convert the Massive.DynamicModel.Query object to something typed?
Two words: View models. Strongly typed view models, that's what you should be passing to your views. Not dynamics, not expandos, not anonymous objects, not ViewData, not ViewBag => only strongly typed view models. So start by defining a view model which will represent the data this view will be working with. Then have your controller action do the necessary in order to convert whatever your repositories spit into a view model which will be passed to the view.
Failing to follow this basic rule, your ASP.NET MVC experience could quickly turn into a nightmare.
I think the easiest way is to use ViewBag because it's dynamic already.
You'd better watch the production because it's about Rob's opinionated way of development more than it is about MVC 3, and describes using Massive and other Rob tools.
But even if you don't make sure to check the code sample here for the production (free), to see how he integrates Massive to MVC 3:
https://github.com/tekpub/mvc3
You can see his production controller looks like. Quite interesting ways.
I'm experimenting with dynamics and Massive now. I'm using a dynamic viewModel:
public ActionResult Index() {
_logger.LogInfo("In home");
dynamic viewModel = new ExpandoObject();
var data = _tricksTable.Query("SELECT TOP(10) * FROM Tricks ORDER BY DateCreated DESC");
viewModel.TenTricksNewestFirst = data;
var data2 = _tricksTable.Query("SELECT TOP(10) * FROM Tricks ORDER BY Votes DESC");
viewModel.TenTricksMostPopularFirst = data2;
return View(viewModel);
}
In my view there is no reference to anything strongly typed on the first line eg NOT THIS:
#model IEnumerable<MvcApplication2.Models.Thing>
so in my view I do stuff like this:
#foreach (var item in Model.TenTricksNewestFirst) {
<div class="post block">
<div class="tab-image-block">
<a href="/tricks/#URL.MakeSpacesMinuses(#item.Name)" title="#item.Name">
<img src="/public/images/#item.Thumbnail" alt="#item.Name" class="woo-image thumbnail" /></a>
</div>
<h2 class="title">
#item.Name</h2>
<span class="date">#Dates.ShortDate(#item.DateCreated)</span>
<span class="likes">Likes: #item.Votes</span>
</div>
}
Experience so far is that I'm writing a lot less code.
Because of anonymous type are always annotated as "internal" so you can't access your dynamic type instance from View as they are in different scopes.
I find a better way make it work than using ViewBag. And the answer is Mono.Cecil. Grab it handy from NuGet.
With Mono.Cecil's help you can change MSIL code generated from your ASP.NET MVC project and change the type's accessible modifier to "public".
I write a little console program and host it on GitHub.
You can invoke the program from command line or add a post-build event in your ASP.NET MVC project's Build Events:
"$(SolutionDir)DynamicHelper\bin\Debug\DynamicHelper.exe" "$(TargetPath)"
NOTICE: "DynamicHelper" is the the code's project name and you can change it depending on your situation.
I was just wondering what the best practice approach is for deciding where to create an action/view in certain situations.
If User hasMany Video
where is the best place to create the action/view to show user videos?
So within the Users account page 'My Videos' link do you
just create a users/my_videos action and view.
create videos/my_videos action and view.
or as is most likely you would already have a Controller/Action of videos/index which would have search functionality. Simply use this passing in a user id.
Any thoughts/advice greatly appreciated
Thanks
Leo
One potential option is to do the following:
Since the videos likely have much more code around them than a simple which user has which videos lookup the video list action should be in the VideosController.
In past projects I have (in CakePHP 1.3) used prefix routing to address some of this.
In config/core.php make sure you enable routing.prefixes to include a 'user' prefix.
<?php
... in routes.php ...
Routing.prefixes = array( 'user' );
?>
In the videos controller make an action with the following signature:
<?php
...
public function user_index( $userID = null ){
...
}
?>
and in the views where you link to the list of users videos the html::link call should look similar to the following:
<?php
...
echo $this->Html->link( 'User\'s Videos', array(
'controller' => 'videos',
'action' => 'index',
'prefix' => 'user',
$this->Session->read( 'Auth.User.id' )
));
?>
Of course this assumes you are using the Auth component here to track the logged in user. The Session helper code to read the authenticated user id might need tweaking.
This lets you a) Not worry too much about routing aside from enabling prefix routing and b) will quickly let you have pretty links like so -- site.com/user/videos/index/419
Couple this with some Slug love ( this is the best link for this I have seen - no slug field required on the db layer - http://42pixels.com/blog/slugs-ugly-bugs-pretty-urls )
You could even end up with urls like so quite easily: site.com/user/videos/index/eben-roux
and with just a tiny bit of editing to app/config/routes.php you could eliminate the /index/ portion and the results would be SEO friendly and user friendly in the format:
site.com/user/videos/eben-roux
http://book.cakephp.org/view/945/Routes-Configuration
As always with code you have the two extremes of:
1) Putting everything in a single controller
2) Having every action in a separate controller
The ideal approach will nearly always be somewhere between the two so how to decide what is grouped together and what is separated?
In MVC I tend to look at the Views and see what the commonalities are: as you point out Users have a ref to a collection of Videos in the Model, but would you want both sets of Data in any single View? i.e. In this example is it likely that you would be on a page that both managed user details, and displayed the list of vids? If not then I'd suggest separate controllers.
If either controller would then be extremely simple - e.g. one method, then may be worth considering merging the two.
I like to keeps things separate.
What I'd do is an index action in videos controller, passing user's id as argument and then displaying only current users video.
public function index($id = null){
$this->paginate = array( 'conditions'=> array('Video.user_id' => $id));
$this->set('videos', $this->paginate());
}
My take is that it depends on the responsibility you assign to the controllers.
I would say that something like a User or a Video controller should be concerned with only those entities.
You may want to consider something like a UserDashboard (or something similar but appropriately named) as alluded to by Dunhamzzz in the comments. This can aggegate all the functionality from an "entry" point-of-view. The same way a banner / shortcut / action menu would work.
Your UserDashboard would use whatever data layer / repository is required to get the relevant data (such as the IVideoRepository or IVideoQuery implementation).
Usually when something doesn't feel right it isn't. Try splitting it out and see how it works. You can alsways re-arrange / refactor again later.
Just a thought.
I don't think there's a 'one-rule-fits-all' solution to this question, but I would try to take an approach in which you would determine what the main object is that you're dealing with, and adding the action/view to that object's controller.
In your example I'd say that your main object is a video and that the action you're requiring is a list of video's filtered by a specific property (in this case the user's id, but this could very well be a category, a location, etc.).
One thing I would not do is let your desired URL determine in which controller you put your functionality. URLs are trivially changed with routes.
In Codeigniter I want to know the best practice for using the same views with various functions in a controller.
For eg in the index function I have
$locals['somevar'] = "some thing";
$this->load->view('welcome_message', $locals);
in my view I have something a bit like this:
<?php if($somevar):?>
<?=$somevar?>
<?php endif;?>
Attempting to do a Ruby on Rails thing where I can check the existence of Flash/notice before showing it.
However in the test function
(i.e not passing a variable to the view this time)
$this->load->view('welcome_message')
the view seems to need a $somevar value and errors.
My question is this: Do I have to declare (repeat) the variables and set them to something on every function in a controller tnat wants to use that particular view? I am probably missing something obvious and there is probably a better way of approaching this. Thanks for you help in advance.
<?php if (isset($somevar)): ?>
<?php echo $somevar; ?>
<?php endif; ?>
I am developing my first big application using codeigniter and need a little help as I am fairly new to it all. I know how to get records out of the DB and display them, but I now have to get results from two tables and display them. I pass $data to the view, it works fine for $data['prop'] but I can't get the rest.
$data['prop'] = $this->ManageProperty_model->get_property_details($p_id);
$data['img'] = $this->ManageProperty_model->get_property_images($p_id);
$this->load->model('ManageBranch_model');
$data['branch'] = $this->ManageBranch_model->get_branch_details($p_id);
I usually echo out results like so:
<?php foreach ($prop as $p) : ?>
<?php echo $p->ID; ?>
<?php endforeach; ?>
Even if there is only 1 row being returned as I am not sure of another way.do I need a foreach for img and branch?
How about using a join?
I dont know whats in your model but if you try something like
$this->db->from('property');
$this->db->join('branch', 'branch.id = property.id');
You can put a where statement in there too if you need something particular.
This means you have a more complex model but less loops and arrays and messy stuff in the view which is what you want.
Yes, currently you're just getting one or the other. You're probably better to put it into a multilevel array like $data['property']['prop'].