Doctrine Schema: Enum and ON UPDATE CURRENT_TIMESTAMP - doctrine

Doctrine documentation sucks. I can not find solution to my problem there.
I have code like this:
$logsTable = $schema->createTable('name');
$logsTable->addColumn('status', 'enum', ['notnull' => true, 'default' => 'first']);
$logsTable->addColumn('updated_at', 'datetime', ['notnull' => true]);
Qestions:
How can I add enum options (first, second) for status column ?
How can I define ON UPDATE CURRENT_TIMESTAMP on updated_at column ?

enum and ON UPDATE CURRENT_TIMESTAMP is not supported with doctrine's schema.

Related

Carbon::now() wrong date and time

Current UTC time is: 2022-08-19 00:50
When I create a new record in my database I set created_at like:
'created_at' => Carbon::now()
But it stores Datetime like this -> 2022-08-18 20:50
Anyways, after couple of minutes I update this record and set updated_at like:
'updated_at' => Carbon::now()
And it stores it like this -> 2022-08-19 00:50 which is correct but not completely, because couple of minutes passed and it should be like 2022-08-19 00:53
Here is my migration file:
public function up() {
Schema::create('items', function (Blueprint $table) {
$table->id();
$table->timestamp('created_at');
$table->timestamp('updated_at')->nullable();
});
}
/config/app.php:
'timezone' => 'UTC',
My Item Model:
class Item extends Model {
use HasFactory;
public $timestamps = false;
}
Seriously, whats wrong with this datetime thing in laravel? Why it doesn't work like every other frameworks?
Note: I'm sick of laravels default $table->timestamps() it works even worse.
The answer listed here might be useful: How to update the updated_at column when the user logs in?
//instead of
'created_at' => Carbon::now()
// simply this:
$user->touch();
It was a problem related to database.
When you create a column this way $table->timestamp('created_at'), it creates a column in database with this structure:
|----------------------------------------------------------------------------|
| Name Type ... Null Default |
|----------------------------------------------------------------------------|
| created_at timestamp No current_timestamp() |
| |
|----------------------------------------------------------------------------|
If you pay attention to the Default column, you find out that this function uses the mysql server timestamp to set value for the created_at column and ignores your entry in laravel create() method.
To fix this problem you only have to set created_at to a nullable column like so:
$table->timestamp('created_at')->nullable();

Set the value in the model so that when inserting or updating automatically added to the database in laravel?

In the database I have columns: id, name, order, createdAt, updatedAt, createdBy, updateBy .
In controller : PostController.php
public function store(Request $request)
{
$req = Validator::make($request->all(), [
'name' => 'required',
'order' => 'required',
]);
if ($req->fails()) {
return response()->json(['error' => $req->errors()], 400);
}
$data = $request->all(); // name and order
Post::insert($item);
}
I want when I add data. Then createAt column and createBy column will be added. Instead of setting date('Y-m-d H:i:s) and $request->user()->id in controller, Then I want it to be placed in model, when i insert createAt and createBy columns are added. If it's update then I want the updatedAt and updatedBy columns to be added
You can add both createdAt and updatedAt in your migration file.
That will insert the current timestamp while inserting values into the table without adding them into the controller.
Please try like this while adding migration
Schema::create('table_name', function (Blueprint $table) {
$table->timestamp('createdAt');
$table->timestamp('updatedAt');
});
Instead of doing POST::insert($data); you could create/update a model more explicitly.
To add a new Post with only createdAt and createdBy you could do something like this:
$post = new Post;
$post->createdAt = $dateTime;
$post->createdBy = $userId;
$post->save();
Of course you can set any other attributes you are wanting to include before you save. And your updatedAt and updatedBy columns will have to be nullable in the database so that you don't get an error when you try to insert a record without including them.
Also as a note, Laravel has a feature that includes created_at and updated_at columns if you have: $table->timestamps(); included in your table's migration file. These fields will get automatically updated whenever a database entry is created/updated.
in your migration, you can just use the timestamps, it by default creates created_at and updated_at, and when you update an entry, Eloquent will update the value automatically for you, as for the created_by and updated_by, you can create them as well in migration, then setup an observer to set the values on create/update
ref: https://laravel.com/docs/8.x/eloquent#observers

Laravel 5.5 - update or create bulk insert

i am trying to preform update or create action on many records using laravel model.
Normal insert with updateOrCreate works perfectly with foreach but i want to avoide it as it slowing things down.
I have something like 200k records.
Is there is any way to achive it?
I tried this answer below
https://stackoverflow.com/a/34815725/1239122
But it is not super elegant.
Any ideas?
You can try this library for batch insert and update.
https://github.com/mavinoo/laravelBatch
I didn't find a way to bulk insert or update in one query. But I have managed with only 3 queries. I have one table name shipping_costs. Here I want to update the shipping cost against the shipping area. I have only 5 columns in this table id, area_id, cost, created_at, updated_at.
// first get ids from table
$exist_ids = DB::table('shipping_costs')->pluck('area_id')->toArray();
// get requested ids
$requested_ids = $request->get('area_ids');
// get updatable ids
$updatable_ids = array_values(array_intersect($exist_ids, $requested_ids));
// get insertable ids
$insertable_ids = array_values(array_diff($requested_ids, $exist_ids));
// prepare data for insert
$data = collect();
foreach ($insertable_ids as $id) {
$data->push([
'area_id' => $id,
'cost' => $request->get('cost'),
'created_at' => now(),
'updated_at' => now()
]);
}
DB::table('shipping_costs')->insert($data->toArray());
// prepare for update
DB::table('shipping_costs')
->whereIn('area_id', $updatable_ids)
->update([
'cost' => $request->get('cost'),
'updated_at' => now()
]);
You can use insert() in Query Builder to bulk insert. But update statement needs conditions. Please read the document:
https://laravel.com/docs/5.7/eloquent#updates
As far as I know, you can not do it for the update as you need to check the condition for the update, But you can do it for insert
$data = array(
array('name'=>'John', 'phone'=>'1234567890'),
array('name'=>'Deo', 'phone'=>'9876543210'),
//...
);
Model::insert($data);

laravel backpack crud display relationship in list view filter by and update

How can you display relationships fields and filter by in the list and update views?
lets say I have a transactions table
Id, customer_id, product_id, purchase_date, payment_status
a customer table
Id, first_name, last_name, email, password
a products table
Id, product_name, product_description, product_price, stock
for example. And I wanted to show in my transactions view:
ID, customer.first_name customer.last_name, product.product_name, purchase_date, payment_status
and wanted to filter the results by customer name and product name, I have read through the docs and cannot see how to achieve this.
In your CrudController in the setup() method :
$this->crud->setListView('your-custom-view');
If you want, you can use the default list view as a starter and modify it
you can find the default file in vendor/backpack/crud/src/resources/views/list.blade.php.
Don't modify it there because it will show on all Crud views..just take it as a template and save 'your-custom-view' in views.
Maybe this will be of help : https://laravel-backpack.readme.io/v3.3/docs/filters
Edit:
Instead of customer_id you want the customer first_name and so on right? This will do the trick:
In your TransactionCrudController:
$this->crud->addColumn([
// 1-n relationship
'label' => "customer", // Table column heading
'type' => "select",
'name' => 'customer_id', // the column that contains the ID of that connected entity;
'entity' => 'customer', // the method that defines the relationship in your Model
'attribute' => "first_name", // foreign key attribute that is shown to user
'model' => "App/Models/Customer", // foreign key model
]);
Is this what you are looking for? If not let me know.

Timestamps (updated_at, created_at) are null in Laravel 5

I have a problem with updated_at, created_at fields in Laravel 5.
Here is my migration:
Schema::create('lots', function (Blueprint $table) {
$table->increments('id');
$table->integer('lot');
$table->integer('is_active');
$table->timestamps();
});
But when I insert some data into this table, updated_at and created_at fields are null. How make them auto-complete with current timestamps?
I insert data like this:
\DB::table('admin_lots')->insert([
'lot' => $request->cycle_lot,
'is_active' => '1',
]);
Thanks.
You have to use the create method instead of the insert method in Laravel.
The create method automatically adds timestamps for created_at and updated_at fields:
// GOOD:
User::create(array(
'name' => 'John'
));
On the contrary, the insert method bypasses Eloquent, (it uses the query builder) and does not update updated_at/created_at columns!
// BAD:
User::insert([
'name' => '[[ test name ]]',
]);
dd(
User::where(['name' => '[[ test name ]]'])->first()->create_date
);
You probably do not use Eloquent when inserting data, in this case you should add timestamps manually.
If you do not want to do this, but you still need filled timestamps, use this hack:
$table->timestamp('created_at')->default(\DB::raw('CURRENT_TIMESTAMP'));
$table->timestamp('updated_at')->default(\DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
Update
Based on your updated code, here's another solution:
\DB::table('admin_lots')->insert([
'lot' => $request->cycle_lot,
'is_active' => '1',
'created_at' = \Carbon\Carbon::now()->toDateTimeString(),
'updated_at' = \Carbon\Carbon::now()->toDateTimeString()
]);
Check if your model has this line.
public $timestamps = false;
If it has, delete it.
When you instert data directly, Laravel won't know about your timestamps.
You can either set the timestamps manually in the insert statement, or switch to using Eloquent models , which handle many things out of the box for you, including timestamps. It's also way easier to maintain than straight queries, where applicable.
Eloquent ORM
You need to use Laravel's awesome Eloquent feature to make timestamps written to the Database automatically...
As by seeing your example the code for eloquent will go something like this:
$lot_inputs = array(
'lot' => $request->cycle_lot,
'is_active' => 1
);
$new_lot = Lot::create($lot_inputs);
Please note that you should have the Model for the table = 'lots' (and it must extend Eloquent) so that you can easily use Eloquent methods and its properties...
It would be great if you use Eloquent ORM as much as possible so that if in future you want to change your DB technology then you won't need to specify the written eloquent queries again (e.g: the conversion of query to different DB languages is automatically done by Eloquent)
Thanks I hope this will help you to resolve your issue..!!

Resources