Can eloquent ignore irrelevant data in Laravel 4 - laravel

I have a form that accepts data which will be used to create two new database table entries. The form takes both the users details and their address. The user details will be stored using the User::create(Input::all()) method into the users table, and the address details will be stored using the Address::create(Input::all()) method into the addresses table of the database.
The issue I'm currently having is that Eloquent is complaining that street, city, country etc do not exist on the users table. This is true, that data is to be used for the address side of things.
Is there any way to have eloquent ignore irrelevant data in the Input::all() array when it's passed to the create methods?
P.s. I'm aware that mass-assignment isn't a good idea, I'm only using it here to simplify my question.

Sure enough you can use $fillable array in your model to declare fields allowed for mass-assignment. I believe this is the most sufficient solution in your case.
class User extends Eloquent {
protected $fillable = [
'first_name',
'last_name',
'email'
];
}

Have you tried looking at Input::only('field1','field2',...);, or even Input::except('field3')? They should be able to accomplish what you are looking for.
Source: http://laravel.com/docs/requests

You'll have to unguard that model using these http://laravel.com/docs/eloquent#mass-assignment and then manually unset those values before you execute save(). I highly recommend using a form object or something similar to complete this kind of service for you outside of your model since it's safer and usually clearer to intended behavior.

#cheelahim is correct, When passing an array to Model::create(), all extra values that aren't in Model::fillable will be ignored.
I would however, STRONGLY RECOMMEND that you do not pass Input::all() to a model. You really should be validating and verifying the data before throwing it into a model.

Related

Can this block of code of mine can be improved

[This is to populate data from two tables that one has two foreign keys from the same column as reference on the other table]
https://i.stack.imgur.com/D8fiv.png
[This is my schema for the table with the foreign key]
https://i.stack.imgur.com/eYDL0.png
This is written in laravel and it is working however i have an itchy feeling that this is wrong
As someone else has commented, you should put the code in your question. More context might also be necessary as it's not clear what you are trying to return from your view(). Are you returning $citizen, $family, or both? It would also be helpful to include what version of Laravel you are using. I'll assume you are using the latest Laravel 8.
Your code should work but you are making more work for yourself if you don't utilize Laravel's relationships. If you do, all the query stuff you have in your code can be reduced to just a few short lines of code such as this:
public function view(Citizen $citizen)
{
$citizen->load('family');
return $citizen;
}
Database Migration
You can shorten your migration by using foreignId(). See docs for details
https://laravel.com/docs/8.x/migrations#foreign-key-constraints
Before:
$table->integer('client_id')->unsigned();
$table->foreign('client_id')->references('id')->on('citizens');
After:
$table->foreignId('client_id')->constrained();
Route Model Binding
I'm assuming your view() method is in your controller and is called from a route. Since the one parameter required is the client's id, you can use Route Model Binding and skip fetching the client from the database.
https://laravel.com/docs/8.x/routing#route-model-binding
public function view(Citizen $citizen)
{
// your code
}
Relationships
You seem to have relationships set up but you aren't using them to load data. You should be able to load the related objects without any manual queries.
If you have a belongsTo(One to Many) relationship on the Citizen model to the Family model, you can load it like this:
$citizen->load('family');
or just use it like this
$relationship = $citizen->family->relationship;
I don't know what the relationships between your models are but you should read up on the different relationship types in the docs.
https://laravel.com/docs/8.x/eloquent-relationships

Which relation to use in Laravel?

Which relation to use in Laravel to bind two table through third?
When Doctors can be assigned to some Centers. The intermediate table will be as:
doctor_id | center_id
How to create model in Laravel for this case?
You don't need a model for the intermediate table, simply use attach
Example:
$center = Center::create();
$doctor = Doctor::find(1);
$doctor->centers()->attach($doctor->id);
This is a very simple example but should give you the idea, of how to approach it.
All of it of course requires you have set up your Center and Doctor model with the correct many to many relations
Doctor.php model:
public function centers()
{
return $this->belongsToMany(Doctor::class);
}
See the documentation, for more information.
You could obviously create a model called DoctorsCenter and create it manually by doing this, whenever you want to attach a relation.
DoctorsCenter::create(['center_id' => $center->id, 'doctor_id' => $doctor->id]);
I don't see any good reason for doing this, and would not recommend it.
You can use hasMany or belongsTo relationship of Laravel.
See the laravel documentation, for more information

Models responsability

I have a doub about Laravel. The models are used to define the relationships between the models like hasMany, belongsTo, etc. Also the models are used to define the fillable fields. But he models are only for that? Because I already check some examples that it seems that some queries are executed in the models instead of the controller so Im not understanding if the models should also have the querying of the relationships or not. Can you give a help to understand better what is the correct use of models (what should be placed in the models)?
Its same way to execute queries on model or controller. Written queries in model make your controller more clean. We can write mutator, accessor or query scope in eloquent model. Correct me if I'm wrong.
Visit https://laravel.com/api/5.5/Illuminate/Database/Eloquent/Model.html
You can refer this documentation, it's quite helpful if you want to know deep basics and responsibilities about particular part in Laravel.
Models are mostly used to make an outlook of the data i.e what fields are going to be saved in the database and we also use it to associate the relationships with other related data as you already know but we also use it to alter the values that are either going in/out of the data base which you can check in the documentation in link bellow https://laravel.com/docs/5.6/eloquent-mutators
the main purpose is to divide the code between controller and model (were it best fit to be)

Laravel relations with composite, non-standard foreign keys

I unfortunately need to import data from a third-party vendor and use their non-standard database schema with my laravel project. In addition, I need to store multiple "firms," each with their own set of users in my database.
I'm trying to figure out the best way (if it can be done) to use Eloquent to handle the relationships between these tables. So for instance, with my table structure like this:
BmPerson
'id',
'firmId',
'personId'
BmCoverage
'id',
'firmId',
'personId',
'securityId'
BmSecurity
'id',
'firmId',
'securityId'
... for instance, I need to associate a "BmPerson" with many "BmSecurity" through the "BmCoverage" table.
But I need to somehow use composite keys, because I am storing multiple "firms" in each table (per the 3rd party vendor's database schema).
One approach I've used so far is scoping, e.g.: for my BmCoverage model:
public function scopeFromFirm($query,$firmId){
return $query->where('firmId','=',$firmId);//->where('personId','=',$personId);}
public function scopeFromPerson($query,$personId){
return $query->where('personId','=',$personId);//->where('personId','=',$personId);}
Then I can retrieve the coverage list for an individual person, but I still need to somehow be able to associate the "BmCoverage" with the "BmSecurities." I suppose I could just add a scope the BmSecurities class too, but it would be nicer to just use Eloquent.
Has anyone come up with a good way to use composite keys in laravel model relationships, or should I just stick with the scoping method?
There is a package here that seems to be perfect for your case:
Compoships offers the ability to specify relationships based on two
(or more) columns in Laravel 5's Eloquent. The need to match multiple
columns in the definition of an Eloquent relationship often arises
when working with third party or pre existing schema/database.
You would use it like this:
class BmPerson extends Model
{
use \Awobaz\Compoships\Compoships;
public function bmCoverages()
{
return $this->hasMany('App\BmCoverage', ['firmId', 'personId'], ['firmId', 'personId']);
}
}
If every BmSecurity belongs to exactly one BmCoverage, and every BmCoverage belongs to exactly one BmPerson its probably easier to replace 'firmId', 'personId' with bmperson_id in BmCoverage DB; and 'firmId', 'securityId' with bmcoverage_id in BmSecurity. Then you can use default hasMany relations with one key.
Everything you need for this can be found here https://laravel.com/docs/5.2/eloquent-relationships
You can easily define which cols sohuld be the referenced key.
Example:
public function bmCoverages() {
return $this->hasMany('App\BmCoverage', 'firmId', 'id');
}
This would probably belong to your App\Firm or whatever it is called.
In general the hasMany relations looks like this
return $this->hasMany('App\Comment', 'foreign_key', 'local_key');
As you can see you can specify the keys.
As the others have said, you need to use the HasMany and HasManyThrough relationship.
Here from your table definitions, you simply need access to:
Person->BmCoverage(s)
Person->BmSecurity(s) of an individual.
What I think is the major problem here is linking the BmSecurity with BmCoverage as apparently there's no coverage_id per BmSecurity but rather, a composite mapping through firmId and securityId.
In this case, Laravel does not officially support composite keys unfortunately, although you could use a trait like this... but you could also achieve the same with some tricky hasMany.
i.e. on BmCoverage
$this->hasMany('BmSecurity', 'securityId', 'securityId')
->andWhere('firmId', '=', $this->firmId);
Same applies for BmSecurity from BmPerson using HasManyThrough.
Hope that helps.
read laravel hasManyThrough relationship . it will help you to write this query more easily
https://laravel.com/docs/5.1/eloquent-relationships#has-many-through

Laravel change stored value of polymorphic relationship

I am trying to make the stored value of a polymorphic relationship more readable by other applications. Currently the polymorphic model type is stored as the FQCN of the model. Using the example in the Laravel Docs, imageable_type could be "App\Product", or "App\Staff". However, this value can be a little more difficult to manage if any non-laravel applications which aren't based on this convention and are also accessing the same database. Also, if the model FQCN ever gets refactored, you have to modify your other applications to account for the change.
Is there a way to change the type to something more consistent and readable, and then have a mapping class that maps the keys to the model? (e.g. have "product" map to "App\Product")
Yes. This is a change that was recently implemented.
Add this to your service provider (in the boot method):
Illuminate\Database\Eloquent\Relations\Relation::morphMap([
'product' => App\Product::class
]);
If you simply pass an array of model names, it'll default to using the table names:
Illuminate\Database\Eloquent\Relations\Relation::morphMap([
App\Product::class,
App\Staff::class,
]);
if you are adding morphMap method to service provider, you might want to use
'product' => \App\Product::class
( "\" before App),otherwise your namespace can be wrong.

Resources