Laravel 6 - Updating the model timestamps - mysql

After some actions inside of my Laravel 6 app, I'm trying to update my model object $last (class CurrentConditions). As you can see below, I'm trying to update update_time property to current timestamp. Except this property, I have another timestamp property inside the CurrentConditions model: external_update_time and I want this property to stay the same after updating and saving $last object. Problem is that external_update_time property is updated to current time after saving the model.
/** #var CurrentConditions $last */
$last = $this->getLastUpdatedCurrentConditions($cityID);
$last->update_time = Carbon::now("UTC");
$last->save();
Here is my model:
class CurrentConditions extends Model
{
protected $table = 'current_conditions';
...
public $timestamps = false;
protected $dates = ['update_time', 'external_update_time'];
...
}
And here is my migration code:
Schema::create("current_conditions", function (Blueprint $table) {
$table->bigIncrements("current_conditions_id");
...
$table->timestamp("external_update_time");
$table->timestamp("update_time")->useCurrent();
});
So why is external_update_time updating as well? Thanks for any help.

Please check that external_update_time is not set on Update to set CurrentTimeStamp
in the schema table design

This is how MySQL 5.7 works - first timestamp will be updated with current timestamp. You should modify order of columns in your migration (assuming it's not deployed yet to live server) to achieve what you want:
$table->timestamp("update_time")->useCurrent();
$table->timestamp("external_update_time");

Related

How to save laravel model to 2 databases

Hi is there a way to do something like:
$model->name = 'newname'
$model -> save()
Change database connection
$model save()
Change back.
I know you can do it with manual queries
DB::Conection(conectio1)->update($SQLString)
DB:Coneection(conection2)->update($SQLString)
MYSQL replication is not instant
thnx in advance
I have actually never tried that but it should be possible using the setConnection() method of your model.
$model->setConnection('connection2');
But you will have to replicate the model before you change anything on the original model instance because otherwise it won't recognise changes of the same attributes with the same values anymore (if they don't differ from the values you used before).
$model2 = $model
->replicate()
->setConnection('connection2');
$model->name = 'name';
$model->save();
// You need the replicated model here because if you used the same model
// with a different connection the model can not say that `name` has changed
// because the value hasn't changed.
$model2->name = 'name';
$model2->save();
I found the easiest way.
public function saveMultipleDatabases($db)
{
Config::set('database.default', $db);
$model->name = 'newname'
$model->save()
}

Laravel Schema Default Value Function

I want the default value for my Server model's sid to be the uniqid() function to be run every time. Something like this, for example
$table->string('sid')->default(uniqid);
How can I achieve this result?
You can use an event listener to set the sid attribute on your model. You can do this using an event listener, model observer, or just a closure function inside your model's boot function.
// app\Models\YourModel.php
/**
* Define model event callbacks.
*
* #return void
*/
public static function boot()
{
parent::boot();
static::creating(function ($model) {
$model->sid = uniqid();
});
}
Unfortunately no, MySQL requires constants for the default. So, the default value must be a constant, it cannot be a function or an expression.
Only way is to allow the fields nullable and add uniqid() while creating records on the database like this:
$table->string('sid')->nullable();
Now, When you add records set sid value to uinqid() value
If you have model named Table then
$record = new Table();
$record-> -----
--------
--------
$record->sid = uniqid();
$record->save();
This is the way you can achieve.
UPDATE
You can set default value in model as well like this:
protected $attributes = array(
'sid' => uniqid(),
);
Hope you understand.
i think this is the easiest way
$table->unique('sid')->index()

Use a column value in an other table with laravel query builder

I have two table witch named users & Inbox
In the Inbox table I have a column named sender_id that have the user_id of the sender
I want to show this message in the view. I need a query to get the sender_id from the inbox table and use that to select a certain user from the users table
I need to do this with all messages and all users.
Laravel is basicly straith foward when you use eloquent. You can always customise it.
First, almost all the time, I create a model and a migration at the same time using this : php artisan make:model Something --migration
I know you already make some models and/or migrations, but I'll go step by step to help you understand it.
So, in your case, it'll be php artisan make:model User --migration and php artisan make:model Inbox --migration. Doing this, you get two model named User and Inbox and two migration named date_create_users_table.php and date_create_inboxs_table.php. Maybe you already did the default user table with php artisan make:auth. If it's the case, don't remake one.
I'm not sure about how laravel will name the Inbox model migration... Since, I think, Laravel 5.3, the plurialisation changed and don't always just add an "S" at the end.
Then, now you got your models and migrations, let's add some line into your migration files. Since you want to do a one to many relationship. You don't need to touch the user one. Only the Inbox migration. Each Inbox is related to one User and Users can have many Inboxs. Add something like this in your migration:
public function up()
{
Schema::create('inboxs', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->foreign('user_id')->references('id')->on('users');
all other columns...
});
}
There, you can change the column's name if you need to have a sender, a recipient, etc... Do this instead :
public function up()
{
Schema::create('inboxs', function (Blueprint $table) {
$table->increments('id');
$table->integer('sender_id');
$table->foreign('sender_id')->references('id')->on('users');
$table->integer('recipient_id');
$table->foreign('recipient_id')->references('id')->on('users');
all other columns...
});
}
What we just did, it's creating the Foreign key that Laravel will use to build the query. There is one last part before the fun one. We need to create the relation in our Model. Begin with the user one:
App/User.php
public function inboxs() {
return $this->hasMany(Inbox::class);
}
And now into the App/Inbox.php model:
public function user() {
return $this->belongsTo(User::class);
}
If you need to have a Sender/Recipient/etc... go this way instead:
public function sender() {
return $this->belongsTo(User::class);
}
public function recipient() {
return $this->belongsTo(User::class);
}
Note that each of your function need to be writen in the same way it's into your migration. sender_id need a relation named sender().
Now, that our relations are done, we can simply call everything using eloquent.
$inboxs = Inbox::with('sender')->get();
This will return an array of all your Inbox into the inboxs table. You can access the sender this way: $inboxs[0]->sender();
You need the id, do this: $sender_id = $inboxs[0]->sender_id;
The sender name : $sender_name = $inboxs[0]->sender->name;
If you want to get one Inbox and you have the id, just do this $inbox = Inbox::with('sender')->find($id);
This way you don't get an array, only one result and can access the sender directly using $sender_name = $inbox->sender->name; instead of having to add [0] or using a foreach loop.
You can get all messages sended by a user using something like this:
$inboxs = Inbox::where('sender_id', $sender_id)->get();
Finally, you can pass your data to the view using:
return view('path.to.view')->with('inbox',$inbox);
Into the view you do this to show the sender's name:
//If view.blade.php
{{$inbox['sender']['name']}} //work a 100%
{{$inbox->sender->name}} //I'm not sure about this one
//If not using blade
<?php echo $inbox['sender']['name']; ?>
There is a lot of thing you can do using Eloquent and you can add as much condition you want. The only thing I suggest you to really do if you want to use Eloquent, be aware about the n+1 problem. There is a link where I explain it. Look for the EDIT section of my answer.
If you need some documentation:
Laravel 5.3 Relationships
Laravel 5.3 Migrations
Laravel 5.3 Eloquent
I think you should update your code like:
$user_messages = DB::table('messages')
->select('messages.id as msgId','messages.message as message','users.id as userId','users.user_name as user_name')
->join('messages','messages.user_id','=','users.id')
->where('messages.user_id',$user_id)
->get();
return view("view.path")
->with('messages',$user_messages);
Hope this work for you!
In Model :
namespace App;
use Illuminate\Database\Eloquent\Model;
class Messages extends Model
{
protected $table = 'table_name';
public function sender()
{
return $this->belongsTo('App\User', 'sender_id', 'id');
}
}
In Controller :
public function functionName($user_id){
$messages = Messages::where('sender_id', $user_id)->get();
return view("view.path")
->with('messages',$messages);
}
In view, you can access seder details like this $message->sender->name for name for id $message->sender->id

Model::insert() is not updating timestamps

I added the timestamps in the Migration(Schema) and the model
$table->timestamps(); //In the Schema
public $timestamps = true; //In the model
I made an array with all fields of the database and inserted into the database.
Checkin::insert($input);
In the table, it updates all the fields except the updated_at, created_at timestamps
I have another(default) model for Users and it updates the timestamps. In that model, I am using the ->save() method
Instead of insert, you should use create if you want the timestamps to be set:
Checkin::create($input);
You can also do
$checking = Checkin::create($input);
which will give you the just created checkin.
Make sure the fields are fillable by adding this to your model:
protected $fillable = array(
'name',
'field_1',
'field_2',
... // all the fields you want to be mass-assignable here
);
Also, there's no need to set public $timestamps = true; as that is the default in Laravel if you're using Eloquent models.

Codeigniter timezone mysql settings

Just realised WHY my site is now showing all datetime variables as -1 hr... I'm using Codeigniter for the first time! (Never had this problem before)
So, I have included the following code in my main index.php file
/*
|---------------------------------------------------------------
| DEFAULT TIMEZONE
|---------------------------------------------------------------
|
| Set the default timezone for date/time functions to use if
| none is set on the server.
|
*/
if( ! ini_get('date.timezone') )
{
date_default_timezone_set('GMT');
}
However, it's still showing as -1 hr, so I'm assuming I need to set some sort of default setting for MySQL...
I have included the following line of code in my model:
function __construct()
{
// Call the Model constructor
parent::__construct();
$this->db->query("SET time_zone='+0:00'");
}
Still no difference... Help!
My code is:
<h3><?=date('D, jS F # g:ia', strtotime($row->datetime))?></h3>
The $row->datetime variable is nothing more than a DATETIME column value from my MySQL database. The echoed variable in view is ALWAYS 1 hour less than the value in my database...
My model code is:
function coming_up()
{
$this->db->query("SET time_zone='+0:00'");
$query = $this->db->query('SELECT * FROM events1 WHERE datetime >= NOW() ORDER BY datetime LIMIT 2');
return $query->result();
}
In config/autoload.php, set a model to load on each page load. then call $this->db->query("SET time_zone='+0:00'"); in that model constructor.
config/autoload.php
$autoload['model'] = array('default_model');// for ex, "say default_model"
In application/models, create a new model file with name of "default_model.php" and add below code.
application/models/default_model.php
class Default_model extends CI_Model {
function __construct()
{
// Call the Model constructor
parent::__construct();
$this->db->query("SET time_zone='+0:00'");
}
}
On each page load, this constructor will be called and mysql timezone will be set to +0:00.
Add these line in your config file and then check, it is working for me
$config['time_reference'] = 'gmt';# Default should be GMT
date_default_timezone_set('UTC');# Add this line after creating timezone to GMT for reflecting
am also face this problem.
i tried this way..
$this->db->query("SET LOCAL time_zone='Asia/Kolkata'");
$query="SELECT * FROM offers where NOW() between offfer_from and offer_to";
$res=$this->db->query($query);
it will work fine in my project and i'm not using anything new default model.. if you want global solution means you can use auto-load some model.
SET default time_zone for MySQL :
Go to : Your_Project/system/core/Model.php And then update this function :
public function __construct() {
$this->db->query("SET time_zone='YOUR_TIME_ZONE'");
}
SET default_time_zone for PHP :
Go to Your_Project/index.php
And then update here :
define('ENVIRONMENT', isset($_SERVER['CI_ENV']) ? $_SERVER['CI_ENV'] : 'development');
date_default_timezone_set('YOUR_TIME_ZONE');
I like the solution proposed by Kumar however, I didn't need to set this globally, only when showing dates stored in UTC time in my db.
In my api model I have the following function.
public function setDBTimeOffset(){
$dt = new DateTime();
$offset = $dt->format("P");
$result = $this->db->query("SET time_zone='$offset';");
return $result;
} # END FUNCTION setDBTimeOffset
From my controller, I call the following first.
$this->api->setDBTimeOffset();
Followed by the call to the function that queries the db. For example, I am fetching some user history.
$data["viewData"]["allHistory"] = $this->api->getUserHistory("ALL", 0, 10000);
When I display the output, the dates are in my timezone. I hope this helps someone, somewhere in time (couldn't resist).
You can set it in the index.php file in your project folder on top and after <?php
<?php
date_default_timezone_set('Asia/Bangkok');