updated_at timestamp not being updated when using sync in Laravel 4 - laravel-4

I use the following code to update tags and other information about an organization:
Route::put('org/{org}', function(Org $org){
$org->description = Input::get('description');
$org->website = Input::get('website');
$org->save();
$org->tags()->sync(Input::get('tags'));
return Redirect::to('org/'.$org->id)
->with('message', 'Seccessfully updated page!');
});
However, if I only change the tags associated with this org, the updated_at field is not updated. I added protected $touches = array('org'); to my Tag model, but this only seems to work for belongsTo relations, while the relation between orgs and tags is a many-to-many polymorphic relation.
Is there a way to allow the sync function to automatically update the default updated_at timestamp?
Doing it manually, like below, will update the timestamp even if my edit doesn't actually change anything:
$org->updated_at = \Carbon\Carbon::now()->toDateTimeString();
$org->save();

You have to setup touches array on Tag model, BUT it has limitation:
Eloquent guesses the relation name, so will work only if the name complies with the convention.
Organization model -> organizations relation.
And if you want to manually update the timestamp you can use this instead:
$model->touch();

Related

Laravel isDirty() & getOriginal() not working with pivot relationship in observer

In my project, I want to keep track of updated comments. So if a comment is updated, the old comment is saved in a comment_history table. I am using observer for this. But user can tag other users in a comment. So, I have a many-to-many pivot table comment_user.
I have defined a belongsToMany relationship in my comment model with the user model. So far I can insert it into comment_history when the comment field changes. But I also want to insert into comment_history when the tagged users are changed in a comment. I want the tagged user ids in comma-separated to be inserted in the old_tagged_users fields in comment_history. But isDirty() & getOriginal() doesn't work with pivot relationship.
class CommentObserver
{
public function updated(Comment $comment)
{
if($comment->isDirty('comment') || $comment->taggedUsers()->isDirty() ){
$history = new CommentHistory();
$history->old_comment = $comment->getOriginal('comment');
$history->old_tagged_users = //old tagged user_ids in comma separeted
$comment->history()->save($history);
}
return;
}
}

Laravel HasManyThrough CrossDatabaseRelation

strange question:
I have 3 Models
Order
with id as PK
Orderline
with id as PK and order_id as FK. brand and partnumber are two separatet colums
Article
with combined PK brand and partnumber
**which is on another database **
One Order hasMany Orderlines. Every Orderline hasOneArticle.
i had make a function within order:
public function articles()
{
$foreignKeys = [
'brand_id',
'article_number',
];
$localKeys = [
'brand',
'partnumber',
];
return $this->hasManyThrough('App\Models\Masterdata\Articles','App\Models\Oms\OrderLine',$foreignKeys,$localKeys,'id','id');
}
How can i retrieve all Attributes from articles through Order?
I tried something like this:
$order = Order::find($orderid)->articles();
dd($order);
//did not work
$order = Order::with('orderlines.articles')->where('id','=',$orderid)->get();
Do you have an idea for me?
You can configure more than one database in the database.php config, and specify the $connection name in the Model class.
For the most part, Eloquent doesn't do JOINs, it just does IN statements on the key values from the preceding query, and programmatically marries the results together after the fact. Partly to avoid the mess of keeping table aliases unique, and partly to offer this kind of support- that your relations don't need to live in the same database.
In other words, what you have there should work just fine. If there's a specific error getting thrown back though, please add it to your post.

Broken Eloquent relationship with extended model

I have a model Asset with documents() { $this->hasMany(Document::class); } through a table data_asset_document. I extend Asset into multiple models, one of which is Equipment. In my seeder for Equipment, I attempt to create a Document bound to the Equipment record:
$asset = Equipment::create([...]);
$document = Document::create([
'name' => "$type Purchase Order",
'tracking_number' => app('incrementer')->current()
]);
$asset->documents()->save($document);
Eloquent produces this query:
update `data_document` set `equipment_id` = 1, `data_document`.`updated_at` = 2019-09-20 14:39:48 where `id` = 1
This is obviously incorrect, since data_document does not have an equipment_id column (Documents "belong to" several models besides Asset). How do I rewrite Asset::documents so that produces the correct mapping, even in its extensions? Or do I need to save my Document through a means other than Asset::documents?
Since your extended asset model is called Equipment, Laravel expects your foreign key to be called equipment_id. You will need to specify the actual foreign key of asset_id in your relationship.
https://laravel.com/docs/6.x/eloquent-relationships#one-to-many
hasMany
documents() {
$this->hasMany(Document::class, 'asset_id');
}
The problem is, I'm not convinced your relationship is really hasMany since you mention what looks like a pivot table data_asset_document as being involved. Many-to-many relationships, like mentioned in your title, would use the belongsToMany method.
https://laravel.com/docs/6.x/eloquent-relationships#many-to-many
https://laravel.com/docs/6.x/eloquent-relationships#has-many-through

view database data that was created today by a specific user

I'm creating a foodlog and I want a user to be able to search through the days and view food that was only logged that day.
For example, on the page for today's date I only want to see all the food items that I logged for today.
I have my table getting all data from that specific user from all dates, but how do I narrow it down to just today?
FoodlogController.php
public function show() {
$userId = Auth::user()->id;
$posts = Post::where('user_id', $userId)->get();
return view('foodlog', compact('posts'));
}
This is what my table looks like
I'm going to assume you have the default timestamps on, which add created_at and updated_at fields. If that's not the case, and you log time of creation with a different column, just replace the created_at with it.
Laravel comes with a hand package for dealing with dates - Carbon, which can be used by importing it from Carbon\Carbon namespace.
And Laravel's query builder has a method whereDate (scroll to "whereDate"), which can be used exactly for this.
Combining these 2, you could do this:
$posts = Post::where('user_id', $userId)->whereDate('created_at', \Carbon\Carbon::today())->get();
This will get the posts that were created today.
However
I would strongly recommend you create a hasMany relationship (user hasMany posts and inversely a post belongsTo a user), which would enable to use relationships and do something like this:
$posts = $user->posts()->whereDate('created_at', \Carbon\Carbon::today())->get();
And many more things, the Laravel way.

Questions related to soft delete in laravel

I have some questions relating to soft delete in laravel. I have search up on what it does and what it means and the most understandable part about soft delete is from this sentence
"When models are soft deleted, they are not actually removed from your
database. Instead, a deleted_at attribute is set on the model and
inserted into the database. If a model has a non-null deleted_at
value, the model has been soft deleted. To enable soft deletes for a
model, use the Illuminate\Database\Eloquent\SoftDeletes trait on the
model and add the deleted_at column to your $dates property:"
So here are my questions based from that sentence:
Q1:
So when I use soft delete in my code, and when I try to delete some
data, does the data in the view page(blade.php) disappear while the
database still contain those data?
Q2:
I saw some people using something called static::deleting, I don't
really quite get how this work? Could you explain what it does? Thank
you
Q3:
How do you delete data using soft delete? I saw people just putting
some stuff into their model instead of using button, so does that mean
you can only delete it manually inside the model instead of just
clicking the delete button in the view page?
Question 1
By default: Yes.
It depends on your query. When using soft deletes, Laravel will query all models that are not soft-deleted by default. When you also want to get the soft-deleted models, you need to call the withTrashed() method on your query. Read more here:
https://laravel.com/docs/5.5/eloquent#querying-soft-deleted-models
To understand what withTrashed() does, you need to understand how soft-deleting works. Soft-deleting models works by adding a new column to your database tables called deleted_at. It's value defaults to null. When you soft-delete a model, Laravel will put the current timestamp into that column. Therefore, this field doesn't contain a null value anymore.
When querying models when using soft-deletes, Laravel appends a deleted_at is null condition to the query. Calling the withTrashed() method, removes that condition from the query.
Have a look on the source of the default query modifier and the withTrashed method.
Question 2
That are events. You can call that to tell Laravel, that it should execute that specific closure when this event happens. In your example, it is listening for the "deleting" event. See more on that here:
https://laravel.com/docs/5.5/eloquent#events
Question 3
You can entirely delete soft-deletable models with the forceDelete() method. See "Permanently Deleting Models" here:
https://laravel.com/docs/5.5/eloquent#querying-soft-deleted-models
Q1: So when I use soft delete in my code, and when I try to delete
some data, does the data in the view page(blade.php) disappear while
the database still contain those data?
Yes. The soft delete fill the deleted_at column in the database. Since that, Eloquent will not retrieve these data (except if you ask for). If you use custom SQL request, you'll need to add a WHERE deleted_at IS NULL
Q2: I saw some people using something called static::deleting, I don't
really quite get how this work? Could you explain what it does? Thank
you
I'm not using that day to day, but it's an event you can call (see here ) to automatically delete content related (for example, if you remove an user, you can also remove all his post. It's kind of cascading delete)
Q3: How do you delete data using soft delete? I saw people just
putting some stuff into their model instead of using button, so does
that mean you can only delete it manually inside the model instead of
just clicking the delete button in the view page?
To use the soft delete, you just $object->detroy($id) or $myEloquentRequest->where(...)->delete()
If you want to force a real delete (so the entries will be definitly removed from the database), you can use $flight->forceDelete();
See here for more.
You can do the delete wherever you want. The click on a button bring the user to the delete() method in your controller. You can delete there or call a method inside the model to trigger the delete (and maybe some more complex deleting like event ... )
Soft delete means not delete records in database.So we handle one flag
for manage records is deleted or not.
Let's i explain more with examples :
In our records many user so we add one fields delete_at into database and defaults it's value null so it's records is not deleted.
Now when we fetch all user data we write query like
Select * from user where delete_at = null
So this query return all user data which is not deleted.
Now we delete this user so when we click on delete button we create custom query and update this user delete_at fields with current datetime
Update delete_at=date() where user_id = 1
so now this records is soft delete.
Now i answer your question:
Q.1)No data not displaying after soft delete because when we fetch data it's check delete_at fields null or not.
clarifying your points.
1. So when we use soft delete in code, deleted_at will be updated to present timestamp from null, so while querying data from that particular table from anywhere in your project the eloquent model will automatically return data whose deleted_at is set NULL i.e., it is not soft deleted.
people using something called static::deleting.
you might have seen somewhat like this example if I am understanding your question in right way:
class X-Model extends Eloquent
{
public function xy()
{
return $this->has_many('XY_Model');
}
// this is a recommended way to declare event handlers
protected static function boot() {
parent::boot();
static::deleting(function($x) {
// before delete() method call this
$user->xy()->delete();
// do the rest of the cleanup...
});
}
}
This is a use-case for Eloquent events to delete a record which will use the "deleting" event to do the cleanup.
delete data using soft delete
now after calling this, you can soft delete the data from the table and also u can soft delete the data from other dependent tables if relationships are maintained properly in models. this is actually known as cascading effect. example for you to understand.
Model structure:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Utilities\Uuids;
use Illuminate\Database\Eloquent\SoftDeletes;
use Iatstuti\Database\Support\CascadeSoftDeletes;
class XFolder extends Model
{
use SoftDeletes, CascadeSoftDeletes;
use Uuids;
protected $connection = 'XDB';
protected $table = 'x_folder';
protected $dates = ['deleted_at'];
public $incrementing = false;
protected $cascadeDeletes = ['XReference']; //related table with foreign keys
protected $visible = [ 'id', 'x_id', 'xz_id', 'at_id', 'title', 'description', 'description', 'status', 'created_on' , 'is_active'];
protected $fillable = [
'x_id',
'xz_id',
'at_id',
'title',
'description',
'status',
'created_on',
'is_active'
];
public function XReference()
{
return $this->hasMany('App\Models\XReference', 'x_id');
}
}
now in the controller you can call like this:
public function deleteData($id)
{
$results = $this->getModel()->where('id', $id)->deleteData();
return $results;
}
this will delete data (soft delete in cascading format).
Q1: So when I use soft delete in my code, and when I try to delete some data, does the data in the view page(blade.php) disappear while the database still contain those data?
Yes, if your model use softDelete, than the search query will be like this: Select * from table_name where delete_at = null
Q2: I saw some people using something called static::deleting, I don't really quite get how this work? Could you explain what it does?
You can do it with: Modelname::destroy($id) static action
It destroys the model object where the $id is set. On destroying I mean: it updates the deleted_at column, so the aplication will see it as a soft deleted object
Q3: How do you delete data using soft delete? I saw people just putting some stuff into their model instead of using button, so does that mean you can only delete it manually inside the model instead of just clicking the delete button in the view page?
Example of one of my project:
I have a delete button at the partner screen what routes to partner/{{ id }}/delete
at the routes: Route::get('/partner/{id}/delete', 'PartnerController#deletePartner');
What goes to this action:
public function deletePartner($partnerId = 0){
if ($partnerId > 0){
Partner::destroy($partnerId);
}
return redirect("/partner");
}
So: If I click to delete button it check, that the ID is set and then "destroys it" (soft delete). After deletion it redirects back to the partner
EDIT:
For the example given in the question 3, when you delete the data, does the database data disappear or only the view?
It will dissapear only from the view. In the database it will be stored as:
id name ... created_at updated_at deleted_at
1 foo ... 2017-10-01 00:00 2017-10-01 00:00 NULL
2 bar ... 2017-10-01 00:00 2017-10-01 00:00 2017-10-25 16:00
The first one is a non-deleted the second one is a soft-deleted object and the view only will show the first one

Resources