Unable to enable timestamps again - php

I have used this code to disable updated_at timestamp
public $timestamps = ['created_at'];
const UPDATED_AT = null;
Now I want to bring it back, I have removed above code, added column, but it's null. Tried to drop migration, migrated with $table->timestamps(), it's still null (on creation and doesn't listen to protected $touches). I have tried public $timestamps = true;, but still null.
My model is that simple:
class Visitor extends Model
{
use HasFactory;
protected $guarded = [];
public function visits()
{
return $this->hasMany(Visit::class);
}
}
Any idea what happened and why I am unable to bring timestamp back?
p.s. I tried clearing cache too

You can also create a migration like this for required table.
$table->timestamp('created_at')->default(\DB::raw('CURRENT_TIMESTAMP'));
$table->timestamp('updated_at')->default(\DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));

Related

Eloquent Belongs-to-Many relation using custom intermediate Table Models without 'updated_at' field

I'm using Laravel 8 and in my application, I have Belongs to Many relations with a custom model, and I want to remove the 'updated_at' field.
Relation
public function tracks()
{
return $this->belongsToMany(Track::class)
->using(CollectionTrack::class)
->withPivot('sort' , 'created_at' , 'id');
}
Custom model
class CollectionTrack extends Pivot
{
use Sortable;
public const UPDATED_AT = null;
public $incrementing = true;
public static function enableAutoSort () {
return false;
}
}
The issue is that when I want to sync, it tries to fill the updated_at field.
Column not found: 1054 Unknown column 'updated_at' in 'field list'
However, I removed the updated_at from the Model using the following line.
public const UPDATED_AT = null;
And also, only get the created_at in withPivot.
When I remove the created_at from withPivot, the issue goes away, but in that case, when I retrieve the data created_at won't be in the fields.
Note: my goal is to disable the updated_at timestamp and only have created_at so when I attach a new record, the created_at set and when I retrieve it, the model has these pivot fields 'sort', 'created_at', 'id.'
I think you can remove $table->timestamps() from your migration and just add a field created_at having default value current time stamp.
$table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
should work I guess.
There is another answer you can refer.
You either have to declare public $timestamps = false; in every model, or create a BaseModel, define it there, and have all your models extend it instead of eloquent. Just bare in mind pivot tables MUST have timestamps if you're using Eloquent.
Update: Note that timestamps are no longer REQUIRED in pivot tables after Laravel v3.
Update: You can also disable timestamps by removing $table->timestamps() from your migration
ORIGINAL ANSWER: https://stackoverflow.com/a/59171175/14290461
In your model add these two lines:
public $timestamps = ["created_at"]; //only want to used created_at column
const UPDATED_AT = null; //and updated by default null set
second way:
public $timestamps = false; //by default timestamp false
add function like this:
public function setCreatedAtAttribute($value) {
$this->attributes['created_at'] = \Carbon\Carbon::now();
}
for more info about laravel timestamp see

How do I return my OUTPUT clause in Laravel DB::insert

I am using Laravel and sqlsrv, connected to SQL Server 2016 and all is working great until I try to use an output clause in my insert query.
Query is something like
INSERT INTO TABLE(Columns) OUTPUT INSERTED.MyDesiredReturnColumn VALUES(Value)
This is working perfectly in SQL Server, and returning the desired value, but using Laravel's DB::insert functionality it is only returning a 1 (for successful insert)
I have a workaround that I would rather not have right now, using the CreatedOn field to return the most recently created row, but this has potential issues.
UPDATES: The field I am attempting to retrieve is a uniqueidentifier field (guid) that is created in SQL, not from Laravel-side
After attempting #PrathameshPalav's recommendation of using the Eloquent model creation, the values are being inserted correctly into the DB, but it is not returning the uniqueidentifier still.
$inserted = MyModel::create($information);
print "inserted id is " . $inserted->MyModelId;
This is printing "inserted id is "
Here is my model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class MyModel extends Model
{
//
protected $table = 'MyModelBase';
protected $primaryKey = 'MyModelId';
public $incrementing = false;
protected $keyType = "string";
public $timestamps = false;
protected $fillable = ['field1', 'field2', 'etc'];
}
Any ideas would be greatly helpful.
You can use Eloquent ORM for this purpose:
$insertedObject = ModelName::create($input_array);
It will return inserted model object in response. Or if you want only inserted record id then use
DB::table($tablename)->insertGetId($input_array);
The way that I solved this was by incorporating an Eloquent model (as pointed out by #PrathameshPalav), then (loosely) following this tutorial https://danielkoch.work/log/laravels-eloquent-guids.html
Specifically this part
public static function boot() {
parent::boot();
// Hook when a model is created
static::creating(function ($model) {
// Select a new ID
$result = DB::select( DB::raw('Select NewID() NewUUID') );
$model->{$model->getKeyName()} = $result[0]->NewUUID;
});
}
After that, I added the primary key I had defined to the $fillable array and tested, and it works =)
Thank you both for your help!
Yes, when you use insert it will return a bool. You can use insertGetId to get the the id.
If the table has an auto-incrementing id, use the insertGetId method
to insert a record and then retrieve the ID:
$data = [....]; // data that will be inserted
$id = DB::table('xxx')->insertGetId($data);
More info:
https://laravel.com/docs/5.5/queries#inserts

Laravel 5.3 Eloquent Model Relationship not working, Returns NULL

I am new to Laravel and am struggling with this:
Database - MSSQL existing DB schema cannot be modified as other software depends on it. (not sure if this is a problem or not)
Model/Table setup:
INFO_ALL Table - ID is primary key
PERSON Table - ID is foriegn key
ID's are hex values and I notice eloquent removes the 0x from the start of the value and am not sure if this is causing the relationship to fail or not. example: in the DB I see 0x123456789 in my returned eloquent data I see 123456789
Person Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Person extends Model
{
protected $table = 'PERSON';
protected $primaryKey = 'ID';
public $incrementing = false;
public $timestamps = false;
public function info_all(){
return $this->belongsTo(Info_All::class, 'ID', 'ID');
}
}
Info Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Info_All extends Model
{
protected $table = 'INFO_ALL';
protected $primaryKey = 'ID';
public $incrementing = false;
public $timestamps = false;
public function person(){
return $this->hasOne(Person::class, 'ID', 'ID');
}
}
How I am testing the relationship:
php artisan tinker
$person = App\Person::first();
$person->info;
NULL
php artisan tinker
$info= App\Info::first();
$info->person;
NULL
I know this relationship exists in the DB and I can manuualy get them together with a query but the relationship feature of this framework would really be nice to get figured out.
Beign new to Laravel there are a few things I am unsure about, like if the third argument in the realationship is neccesary since I am declaring the $primaryKey. I declared the $primarykey in the first model because I assummed it is case sensative and my table has ID not id. That being said, I have been stuck on this for a couple days and feel like I have tested everything in every different combination.
Any help is appreciated.
Your relation is defined incorrectly. Try by adding following relation:
Person Model
public function info()
{
return $this->hasOne(Info_All::class, 'ID', 'ID');
}
Info_All model
public function person()
{
return $this->belongsTo(Person::class, 'ID', 'ID');
}
Then try it out in tinker:
$person = App\Person::first();
$person->info;
I am not sure but if eloquent removes the 0x from the start of the value then it can also cause the problem.
Try by removing 0x from your tables.

Laravel Unknown Column 'updated_at'

I've just started with Laravel and I get the following error:
Unknown column 'updated_at' insert into gebruikers (naam, wachtwoord,
updated_at, created_at)
I know the error is from the timestamp column when you migrate a table but I'm not using the updated_at field. I used to use it when I followed the Laravel tutorial but now that I am making (or attempting to make) my own stuff. I get this error even though I don't use timestamps. I can't seem to find the place where it's being used. This is the code:
Controller
public function created()
{
if (!User::isValidRegister(Input::all())) {
return Redirect::back()->withInput()->withErrors(User::$errors);
}
// Register the new user or whatever.
$user = new User;
$user->naam = Input::get('naam');
$user->wachtwoord = Hash::make(Input::get('password'));
$user->save();
return Redirect::to('/users');
}
Route
Route::get('created', 'UserController#created');
Model
public static $rules_register = [
'naam' => 'unique:gebruikers,naam'
];
public static $errors;
protected $table = 'gebruikers';
public static function isValidRegister($data)
{
$validation = Validator::make($data, static::$rules_register);
if ($validation->passes()) {
return true;
}
static::$errors = $validation->messages();
return false;
}
I must be forgetting something... What am I doing wrong here?
In the model, write the below code;
public $timestamps = false;
This would work.
Explanation : By default laravel will expect created_at & updated_at column in your table.
By making it to false it will override the default setting.
Setting timestamps to false means you are going to lose both created_at and updated_at whereas you could set both of the keys in your model.
Case 1:
You have created_at column but not update_at you could simply set updated_at to false in your model
class ABC extends Model {
const UPDATED_AT = null;
Case 2:
You have both created_at and updated_at columns but with different column names
You could simply do:
class ABC extends Model {
const CREATED_AT = 'name_of_created_at_column';
const UPDATED_AT = 'name_of_updated_at_column';
Finally ignoring timestamps completely:
class ABC extends Model {
public $timestamps = false;
}
Link to laravel documentation https://laravel.com/docs/9.x/eloquent#timestamps
Nice answer by Alex and Sameer, but maybe just additional info on why is necessary to put
public $timestamps = false;
Timestamps are nicely explained on official Laravel page:
By default, Eloquent expects created_at and updated_at columns to exist on your >tables. If you do not wish to have these columns automatically managed by >Eloquent, set the $timestamps property on your model to false.
For those who are using laravel 5 or above must use public modifier other wise it will throw an exception
Access level to App\yourModelName::$timestamps must be
public (as in class Illuminate\Database\Eloquent\Model)
public $timestamps = false;
In case you still want the timestamps, but simply forgot to add them in the migration, adding the following to your migration file, will also work:
class AddUsersTable extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->timestamps(); // <-- Add this to add created_at and updated_at
});
}
}
Don't forget to re-run your migration afterwards.
php artisan migrate:rollback
php artisan migrate
First Solution
If not necessary created_at and updated_at, please write the below code in the model.
public $timestamps = false;
Second Solution
If you need to use created_at and updated_at in the future, you can add columns.
Create migration file:
php artisan make:migration add_timestamps_fields_to_users_table
Edit migration file:
class AddTimestampsFieldsToUsersTable extends Migration
{
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->timestamps();
});
}
}
Run migration:
php artisan migrate

Laravel Eloquent::Find() returning NULL with an existing ID

It's pretty straightforward as it's the most basic thing but I don't know what I'm missing:
Having a model called Site
I'm using Eloquent ORM, so when I call (in a controller)
$oSite = Site::find(1)
and then
var_dump($oSite);
It returns a value of NULL.
But when I check the database, the table 'sites' actually contains the following item:
id: 1
user_id: 1
name: test
In my Site model I have the following code:
use Illuminate\Database\Eloquent\ModelNotFoundException;
Class Site extends Eloquent {
protected $table = 'sites';
protected $fillable = ['user_id', 'name'];
}
Instead, if I gather the item with the following:
$oSite = DB::table('sites')
->where('id', 1)
->first();
It works and I get the correct register.
What I'm doing wrong? Which part of the documentation I didn't get?
EDIT:
Model code can be checked above.
Controller:
use Illuminate\Support\Facades\Redirect;
class SiteManagementController extends BaseController {
...
public function deleteSite()
{
if (Request::ajax())
{
$iSiteToDelete = Input::get('siteId');
$oSite = Site::find($iSiteToDelete);
return var_dump($oSite);
}
else
{
return false;
}
}
}
EDIT 2: (SOLVED)
Real reason why wasn't working:
I had originally in my model code the following:
use Illuminate\Database\Eloquent\SoftDeletingTrait;
use Illuminate\Database\Eloquent\ModelNotFoundException;
Class Site extends Eloquent {
protected $table = 'sites';
use SoftDeletingTrait;
protected $dates = ['deleted_at'];
protected $fillable = ['user_id', 'name'];
}
Problem was I added a 'deleted_at' column after I started the project and when I applied migrations, I didn't have softdeleting enabled.
Obviously, I did a second error, forgetting to enable 'deleted_at' to be nullable, hence all inserts went had a wrong timestamp (0000-00-00 ...).
Fix:
Made nullable 'deleted_at' column.
Set all wrong 'deleted_at' timestamps to NULL.
Check you are getting Input::get('siteId') correctly. if you are getting it then try to convert it into integer i.e
$iSiteToDelete = intval(Input::get('siteId'));
You're not returning your model.
var_dump prints output and returns nothing.
do this instead:
dd($oSite); // stands for var_dump and die - a helper method
and even better, simply return the model:
return $oSite; // will be cast to JSON string
In my case I was using a custom query with the DB facade. I neglected to skip records that have a deleted_at in my DB query. When showing all the records, it worked with IDs that had already been deleted, so methods like find that if they were considering the deleted_at, did not find the record.
Layer eight.
For the future if you encounter a similar problem you can check what SQL queries laravel is sending to the database.
Todo so just enable query logging by using DB facade:
\DB::enableQueryLog();
Before sending request to database.
Then after using find() or get() you can get all requests by:
\DB::getQueryLog();
You can getQueryLog into dd() function and see what database queries were made.

Categories