Here is my model relationship...
class User extends Eloquent {
public function loginLog(){
return $this->hasMany('LoginLog');
}
}
class LoginLog extends Eloquent {
public function user(){
return $this->belongsTo('User');
}
}
When I insert data into the login_logs table in my database all the data is input correctly but it does not insert the id of the user into user_id (laravel expects this).
Here is how I am inserting into login_logs.
$user->loginLog()->insert(array(
'user_id' => $user->id, //I could put it here, but then what is the point in a relationship?
'email' => $user->email,
'ip_address' => Request::getClientIp(),
'country_code' => $country_code,
'status' => $status,
'created_at' => Helper::dateTimeNow()
));
You have to attach the user.
Its here in the docs
http://laravel.com/docs/eloquent#inserting-related-models
Update:
On rereading your question I think you want to find the user by their id first as you are doing $user->loginLog()->insert not $loginLog->insert
Try chaining it so:
$user::find($theIDYouWant)->loginLog()->insert
Related
since this "new" update came in laravel (laravel 8) I am struggling with factories. I need help on how to provide unique id from the User model to user_id column in profile factory. In my User model I have a relationship with profile:
public function profile()
{
return $this->hasOne(Profile::class);
}
In profile model:
public function user()
{
return $this->belongsTo(User::class);
}
And now I have to provide data to profile factory:
return [
'user_id' => ,
'image' => 'image',
'bio' => $this->faker->sentence,
...
If you will only create the Profile when you already have a corresponding User, you can leave the user_id out of the Profile factory, and then use the magic methods to create both at the same time.
User::factory()->hasProfiles(1)->create();
This will automatically create a profile to match the user.
Or, if you do need to create a profile before creating a user, you can define the user_id like this in your factory, and a User will be created by the Profile.
return [
'user_id' => User::factory(),
'image' => 'image',
'bio' => $this->faker->sentence,
];
'user_id' => $this->faker->unique()->numberBetween(1,5000),
'user_id' => $this->faker->unique()->numberBetween($min = 1, $max = 500)
Should be total quantity of your users.
I was using these codes in my controller to get all the data from my 2 tables and it works fine
$All = Customers::with('order')->paginate(10);
return response()->json([
'code' => 0,
'success' => true,
'data' => $All
], 200);
Here is how I define the relationship between these 2 tables
class Customers extends Model
{
public function order()
{
return $this->hasMany(Orders::class, 'customer_id', 'id');
}
}
class Orders extends Model
{
public function customers()
{
return $this->belongsTo(Customers::class, 'customer_id', 'id');
}
}
Now my desire output is to hide the order id, order timestamps and change the customer_id to customer's name (the customer's name is not in my orders db table).
I'm using 'data' => DataResource::collection($All) in my controller and this is my DataResource
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'order' => $this->order
];
}
and of course the output is same with the image above.
My database structure:
orders table:
customer table:
Can anyone help me with that?
The answer is simple and basically a copy of the official documentation. You simply need to wrap your orders in an OrderResource as well.
// DataResource
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'order' => OrderResource::collection($this->order)
];
}
// OrderResource
public function toArray($request)
{
return [
'items' => $this->items,
'quantity' => $this->quantity
];
}
I don't really understand why you would want to include the customer_name in your orders when it is already present on the customers object one hierarchy above. But if you really want to add it, you should be able to do so with: 'customer_name' => $this->customers->name.
As a side note: you really should be more consistent with your naming. Why is the resource called DataResource when it is about Customers? Why is your model called Customers in plural form rather than Customer in singular, which is the convention (and more logical if you consider that one model represents one customer). Why is your belongsTo relation called customers() in plural when it returns one customer, while your hasMany relation is called order whereas it returns one or more orders?
Below is a piece of code from my Register Controller. As you can see, every field has a value, but its not inserting into database. I have configured default values to these fields in database, if values are not present. It gives row don't have default value. I am unable to figure out the problem. I also have all fields fillable in Models.
protected function create(array $data)
{
$user = Account::create([
'wallet' => $data['wallet'],
'email' => $data['email'],
'balance' => 0,
'uqid' => rand(10000000,99999999) ,
'ref' => 0,
]);
$gnl = General::first();
$track = Track::create([
'account_id' => $user->id,
'speed' => $gnl->dhs_free,
'balance' => 0,
'uqid' => rand(10000000,99999999) ,
'ref' => 0,
]);
Account Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Account extends Model
{
protected $fillable = ['wallet','uqid','ref','bstatus','refcom','email','verified'];
public function deposit()
{
return $this->hasMany('App\Deposit','id','account_id');
}
public function withdraw()
{
return $this->hasMany('App\Withdraw','id','account_id');
}
public function track()
{
return $this->hasMany('App\Track','id','account_id');
}
Track Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Track extends Model
{
protected $fillable = array( 'account_id','speed','withdraw','status');
public function account()
{
return $this->belongsTo('App\Account');
}
}
When using the create function, it seems you are not filling all the fields in the table.
Either, ensure you're assigning values to all fields in the create() function, or ensure there are default values in the database. In the builder, use ->default(0) or something.
There are few things which can be identified in your code :
Firstly the number and name of the columns in the Model and create method are different :
Account Model contains :
protected $fillable = ['wallet','uqid','ref','bstatus','refcom','email','verified'];
But your create contains :
'wallet' => $data['wallet'],
'email' => $data['email'],
'balance' => 0,
'uqid' => rand(10000000,99999999) ,
'ref' => 0,
Create does not contain bstatus, refcom and so on... columns but those are present in your Model and in the database table.
Similarly, Track Model contains :
protected $fillable = ['account_id','speed','withdraw','status'];
But its create contains :
'account_id' => $user->id,
'speed' => $gnl->dhs_free,
'balance' => 0,
'uqid' => rand(10000000,99999999) ,
'ref' => 0,
Now, if your non-specified columns in create() function do not have any default value specified in database, you will get :
Error : row don't have default value
Solution either add values to those columns in create() or mark those columns are nullable using a migration.
I am having two tables. My primary table is Students. And my secondary table is Exams. I am trying to save both the tables using hasMany and belongsToMany Association. But It is saving data in Student table only, not in Exams. Can any one help me to resolve this problem.
Students Model :
class StudentsTable extends Table {
public function initialize(array $config) {
$this->addBehavior('Timestamp');
parent::initialize($config);
$this->table('students');
$this->primaryKey(['id']);
$this->hasMany('Exams', [
'className' => 'Exams',
'foreignKey' => 'student_id',
'dependent'=>'true',
'cascadeCallbacks'=>'true']);
}
}
Exams Model :
class ExamsTable extends Table {
public function initialize(array $config) {
parent::initialize($config);
$this->table('exams');
$this->primaryKey(['id']);
$this->belongsToMany('Students',[
'className'=>'Students',
'foreignKey' => 'subject_id',
'dependent'=>'true',
'cascadeCallbacks'=>'true']);
}
}
My school.ctp :
echo $this->Form->create();
echo $this->Form->input('name');
echo $this->Form->input('exams.subject', array(
'required'=>false,
'multiple' => 'checkbox',
'options' => array(
0 => 'Tamil',
1 => 'English',
2 => 'Maths')));
echo $this->Form->button(__('Save'));
echo $this->Form->end();
In my controller:
public function school() {
$this->loadModel('Students');
$this->loadModel('Exams');
$student = $this->Students->newEntity();
if ($this->request->is('post')) {
$this->request->data['exams']['subject'] =
implode(',',$this->request->data['exams']['subject']);
$student = $this->Students->patchEntity(
$student, $this->request->data, ['associated' => ['Exams']]
);
if ($this->Students->save($student)) {
$this->Flash->success(__('The user has been saved.'));
} else {
$this->Flash->error(__('Unable to add the user.'));
}
}
}
Patching BelongsToMany Associations
You need to make sure you are able to set exams. Set accessibleFields to allow you to patch associated data
$student = $this->Students->patchEntity(
$student, $this->request->data, [
'associated' => ['Exams'],
'accessibleFields' => ['exams' => true]
]
);
You can also do this with the $_accessible property in the entity.
I've never done hasMany to belongsToMany because i don't think it works that way (I mean no harm in my words.) But I'll try to explain. Your relationships should be both belongsToMany because exams will have many students and students will have many exams. So basically they're the same either way. What you need is another table to connect them which will be called students_exams or exams_students (i think its exams_students because E comes before S) because in cake if you name everything properly most of it happens automatically.
Assuming you know how patchEntity works, creating your $this->request->data properly will patch it automatically and save it in the correct table when you save it. If you have any more questions feel free to ask more. :)
I am converting an internal API from HTML (back-end) processing to JSON (using Knockout.js) processing on the client-side to load a bunch of entities (vehicles, in my case).
The thing is our database stores sensitive information that cannot be revelead in the API since someone could simply reverse engineer the request and gather them.
Therefore I am trying to select specifically for every relationship eager-load the columns I wish to publish in the API, however I am having issues at loading a model relationship because it seems like Eloquent automatically loads every column of the parent model whenever a relationship model is eager loaded.
Sounds like a mindfuck, I am aware, so I'll try to be more comprehensive.
Our database stores many Contract, and each of them has assigned a Vehicle.
A Contract has assigned an User.
A Vehicle has assigned many Photo.
So here's the current code structure:
class Contract
{
public function user()
{
return $this->belongsTo('User');
}
public function vehicle()
{
return $this->belongsTo('Vehicle');
}
}
class Vehicle
{
public function photos()
{
return $this->hasMany('Photo', 'vehicle_id');
}
}
class Photo
{
[...]
}
Since I need to eager load every single relationship listed above and for each relationship a specific amount of columns, I need to do the following:
[...]
$query = Contract::join('vehicles as vehicle', 'vehicle.id', '=', 'contract.vehicle_id')->select([
'contract.id',
'contract.price_current',
'contract.vehicle_id',
'contract.user_id',
'contract.office_id'
]);
[...]
$query = $query->with(['vehicle' => function ($query) {
$query->select([
'id',
'trademark',
'model',
'registration',
'fuel',
'kilometers',
'horsepower',
'cc',
'owners_amount',
'date_last_revision',
'date_bollo_expiration',
'bollo_price',
'kilometers_last_tagliando'
]);
}]);
$query = $query->with(['vehicle.photos' => function ($query) {
$query->select([
'id',
'vehicle_id',
'order',
'paths'
])->where('order', '<=', 0);
}]);
$query = $query->with(['user' => function ($query) {
$query->select([
'id',
'firstname',
'lastname',
'phone'
]);
}]);
$query = $query->with(['office' => function ($query) {
$query->select([
'id',
'name'
]);
}]);
[...]
return $this->response->json([
'error' => false,
'vehicles' => $vehicles->getItems(),
'pagination' => [
'currentPage' => (integer) $vehicles->getCurrentPage(),
'lastPage' => (integer) $vehicles->getLastPage(),
'perPage' => (integer) $vehicles->getPerPage(),
'total' => (integer) $vehicles->getTotal(),
'from' => (integer) $vehicles->getFrom(),
'to' => (integer) $vehicles->getTo(),
'count' => (integer) $vehicles->count()
],
'banner' => rand(0, 2),
'filters' => (count($input) > 4),
'filtersHelpText' => generateSearchString($input)
]);
The issue is: if I do not eager load vehicle.photos relationship, columns are loaded properly. Otherwise, every single column of Vehicle's model is loaded.
Here's some pictures so you can understand:
Note: some information have been removed from the pictures since they are sensitive information.
You can set a hidden property on your models which is an array of column names you want to hide from being output.
protected $hidden = ['password'];