I am making a Joomla 3.2 component by following the Lendr tutorial. They seem to add all of the database columns to their model as protected fields (use helper get/set functions to manipulate them) and CRUD operations as functions. Their table class only contains a constructor:
function __construct( &$db ) {
parent::__construct('#__lendr_books', 'book_id', $db);
}
When they are getting or saving an item, they return an instance of their table class rather than an updated version of the model e.g. if you saved a new item, the protected ID field on the model would be zero, but the ID on the returned table object would be non-zero.
So to me, it doesn't make sense to put all of the columns on the model and it would be better to explicitly declare them on the table class, or keep them updated on the model and don't return any table objects.
Components built into Joomla aren't using the new MVC convention and seem to be all over the show with where to but the CRUD operations.
Is there a clear definition of what the Model should do and what the Table should do in Joomla 3.2 using the non-legacy MVC classes?
It appears to be like this:
JTable Seems to be similar to Ruby on Rails' ActiveRecord::Base. It models the database and there is not really a need to put anything extra in here besides a constructor which declares the table name and primary key and possibly override some methods e.g. check. Basic CRUD operations are provided by JTable which will usually be called by your class that extends JModelBase.
function __construct( &$db ) {
parent::__construct('#__my_table', 'id', $db);
}
JModelBase handles the business logic of your model as well as preparing queries (which will often return the corresponding JTable values. The controller should always deal directly with this and not JTable.
In both cases there is not a need to explicitly add the database columns as properties on the class (just like in Rails).
Related
How can you use the syscomputedcolumn class to retrieve a table or field name for an entity? this is fairly easy using virtual field entity postload method something like
public class SysDatabaseLogHeaderEntity extends common
{
public void postLoad()
{
super();
this.TableName = tableId2Name(this.table);
}
}
but there's a rumour that virtual fields won't be supported in upcoming synapse link for D 365 FnO so want to know how to do this with computed columns...
https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/data-entities/data-entity-computed-columns-virtual-fields
SysComputedColumn is used to help create computed columns in views.
Supposing for some reason you want a column in which every row contains the string value "CustTable", you'd create create a method (AX 2012 syntax):
public static server string TableNameColumn()
{
return SysComputedColumn::returnLiteral(tableStr(CustTable));
}
and then you'd add a computed column to the view as outlined here: https://learn.microsoft.com/en-us/dynamicsax-2012/developer/walkthrough-add-a-computed-column-to-a-view
Note: hopefully this is a toy example, there is no reason to ever actually do this particular column. Or really any fully static columns.
View computed columns are essentially based on static server methods which return the SQL definition for the computed column, and then the SysComputedColumn class has a bunch of helper methods to let you build those SQL string statements without using specific implementation knowledge of the backend database such as column names.
A complete description is beyond the scope of this comment, but the big one you'll use is SysComputedColumn::returnField(view,datasource,field) which gets the specified field from the specified datasource in the specified view. You want to use intrinsic functions for these parameters to keep your cross references valid (https://learn.microsoft.com/en-us/dynamicsax-2012/developer/intrinsic-functions).
There will be a lot you can't do though. These are sql only so they cannot send individual rows into X++ business logic. You need to reconstruct said business logic in SQL which can't always be done easily.
I like to keep those methods public so I can info them out and test them in SQL directly. I'm guessing you can't access the sql in d365, but looking at the string returned from your method can still help in troubleshooting.
I want to do horizontal partitioning for the "users" table which is having a large number of rows. So I split the table and will have then users_1, users_2 etc. These tables are generated dynamically.
My issue is how to set the table name dynamically in laravel models. I have tried below option and it works fine.
$hash = 1;
$user = new User();
$user->setTable('users_'. $hash);
$user->where('id', 23)->get();
Here I get the result from the users_1 table;
But when I call
User::all();
It is using the table users and not users_1.
I have also tried by using setTable() in the __construct method of model. But the issue is $hash is calculated based on the value used in controller which is not getting in the construct method of model.
Is there any solution for this?
You can make a scope that switches the "from" part of the query builder
add this in the model -
public function scopeFromTable($query, $tableName)
{
$query->from($tableName);
}
Then use
$DynamicTableData = ModelName::fromTable($tableName)->get();
you can use all Eloquent methods by this approach
It is due to User::all() is called statically getting a new Model class object and looking for table users by default. If you can use the instance you have created $this with setTable() then you can call with dynamic table names. $this refers the member variables and function for a particular instance.
Best solution for your case, would be to use the database level partitioning. So you don't need to manage the hashing. Just give a partitioning key static or range, with created_at field and then you can call to a single table with User::all() to get all the users and no need to call dynamically. Or can checkout database shard.
May be this can help you:
$data = new Model;
$data->setTable('users');
dump($data->get());
$data->setTable('users_status');
dump($data->get());
die;
Good Luck.
I have a model class named Server, it contains many navigation properties and properties, which I want to prevent users from binding it. So I find two approaches of doing so to avoid over-posting attacks.
The first approach is to go to each model class and define an Exclude Bind list , with all the properties and navigating properties that should not be bind by users , as follow:-
[MetadataType(typeof(TMSServer_Validation))]
[Bind(Exclude = "Technology,IT360SiteID, VirtualMachines, TMSServer1,DataCenter,OperatingSystem,Rack,ServerModel,TechnologyBackUpStatu,TechnologyRole,TechnologyStatu ")]
public partial class Server {
}
}
The second approach is to create a view model class , with only the properties that can be modified by users as follow:-
public class ServerViewModel
{
public int ServerSize { get; set; }
[Required]
public String OperatingSystem { get; set; }
public String Commnet { get; set; }
}
I find that the first approach is faster to implement , as I only need to define the Exclude list, while the second approach will require me to create view-model class for each of the domain classes. So which approach is recommended to use and why ?
Thanks
Over-posting occurs due to the default model binder not knowing which fields you actually included in the form.
It will try to map all values in the request to object. Attackers can use your form to add additional fields to
query strings/form post data and add properties as part of the request. The default model binder won't
know the difference. Your Server class will deactivate once the mapping is complete and the update is processed.
To prevent over-posting, set the annotation to include fields in the binding, or create a ViewModel like you mentioned in your code.
So which approach is recommended to use and why ?
Both annotation and ViewModel allow binding only on specified fields, but when you use ViewModel you will not bind against business objects or entities, and you will only have properties available for the input you expected.
Once the model is validated, you can then move values from the input model to the object you used in the next layer.
k. Soctt Allen has a good article about which approach is better, you can take a look at by the following link:
http://odetocode.com/blogs/scott/archive/2012/03/11/complete-guide-to-mass-assignment-in-asp-net-mvc.aspx
It's difficult to tell without seeing the rest of your code, but in general I'd say using the ViewModel is probably a better approach for the following reasons:
You separate your view from your business logic
It is safer. If in the future someone adds a property on Server and forgets the Bind-exclude, you're exposed to over-binding without knowing it. If you use the ViewModel-approach you have to explicity add new properties
Maybe this question is a little bit ambiguous because the answers are going to be based on opinions or something. But I'll try to answer it the best I can and indeed is kind of my opinion. So this is the way I see it:
First approach (Bind attribute): Is faster to implement because you only need to add on your class the name of the property you don't want to expose, but the problems comes when you want your class to exclude some properties for one feature and other properties for another feature, and you can't add fields and sometimes in MVC, the views need more fields that the ones provided by the model class and then you're gonna need to use ViewBag or something else. This approach is very handy for fast and smalls projects, but I still don't like to use ViewBag (For aesthetics reasons)
Second approach (ViewModels): Is more work, and more time but at the end (again in my opinion) you get a cleaner and ordered code and you don't need to use the ViewBag, because you can have the perfect object to send to the view depending on what this View needs, so if you a have an object with different views, again depending on the needs, they could share the same ViewModel or they could have a ViewModel for each one. If you have a solution or a big web project, this approach is going to be very handy to keep an ordered code.
Let me know.
Before asking my question I would like to explain little about my architecture.My data is of mixed types like String , Array Collection , Boolean I have to populate the data into appropriate UI component - for example Boolean to check box , Array to List...... so We have created a factory class which will return 3 different type of component based on the input argument
CTextfield -> extends mx.controls.Text
CList -> extends mx.controls.List
CCheckBox -> extends custom.MultiLineCheckBox
.
MultiLineCheckBox which extends mx.controls.CheckBox and few methods are overridden to bring the multiple line label.
http://spy6.blogspot.com/2008/09/flex-multiline-checkbox.html
It works perfect.Am using the MultiLineCheckBox in the entire application wherever I want check Box.
Now I went into a scenario where I want check Box instead of MultiLineCheckBox. How to rewrite my CCheckBox to handle MultiLineCheckBox and also default CheckBox?
Note : Each of the CCheckBox class has lot of methods init.
You need an abstract factory that extends from your concrete factory (http://cnx.org/content/m17203/latest/AbstractFactory.jpg) then write the logic of handle the different scenarios in it, when to use checkbox vs multilinecheckbox
I just want to make sure I understand correctly the best practices for ASP.NET MVC2 with LINQ-TO-SQL.
Please correct me if I am wrong at any of the following points:
LINQ TO SQL generates classes for
you, based on your tables
The generated classes are Models
Those are the models we are supposed to use in the Views
If we want to add validation to the models, we extend the partial class and set data
annotations. Something like this.
Generally my question is about the data validation. What I used to do is create a "shadow" Model for each of my LINQ-to-SQL generated classes and put the data validation there. Then, in the controllers I was creating an instance of the "shadow" model and also retrieve data (using Repository pattern). Mapped from the entity to the shadow model and passed it to the view. So, something like that (in the Controller):
// Car is class generated by LINQ-to-SQL, based on the Car table
// Use repository class to retrieve the data (Car)
Car car = myDatabaseRepository.GetCar(1);
// CarModel is my 'shadow' model, which has all the data validation.
// For example, it makes sure Year is before 2010 (let's say).
CarModel carModel = new CarModel();
carModel.Year = car.Year;
carModel.Make = car.Make;
carModel.Model = car.Model;
return View(carModel);
This is wrong, right (no pun intended)? It should have been only:
// Car should have been extended (as partial) and data annotation
// should have been in the extended class, rather than a whole separate
// model class.
Car car = myDatabaseRepository.GetCar(1);
return View(car);
Right?
I think it is a best practice to have a ViewModel (what you termed "shadow" model) that is used to pass only relevant data model information to a view and incorporating UI validation metadata. You can also use a library such as AutoMapper to copy over the values, rather than coding each one by hand.
A Table = Model approach can work in very simple scenarios (few tables + simple UI exactly matching database schema). In order to save yourself a lot of pain later on it is recommended to use ViewModels.