Asked  7 Months ago    Answers:  5   Viewed   26 times

I'm in the process of converting one of our web applications from CodeIgniter to Laravel. However at this moment we don't want to add the updated_at / created_at fields to all of our tables as we have a logging class that does all this in more depth for us already.

I'm aware I can set $timestamps = false; in:

VendorlaravelframeworksrcilluminateDatebaseEloquentModel.php

However I'd rather not change a core file for Laravel, or have everyone of my models have that at the top. Is there any way to disable this elsewhere for all models?

 Answers

71

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.

Wednesday, March 31, 2021
 
cusejuice
answered 7 Months ago
73

You should not eager load directly on the relationship. You could eager load the user always on the GroupTextPost model.

GroupTextPost.php

<?php

namespace AppModels;

use IlluminateDatabaseEloquentModel;

class GroupTextPost extends Model
{
    protected $table = 'group_text_post';

    /**
     * The relations to eager load on every query.
     *
     * @var array
     */
    protected $with = ['user'];

    public function user()
    {
        return $this->belongsTo('AppModelsUser');
    }

    public function group()
    {
        return $this->belongsTo('AppModelsGroup');
    }
}

Or you could use Nested Eager Loading

$group = Group::with(['messages.user'])->find($groupID);
$group->messages[0]->user->firstname
Wednesday, March 31, 2021
 
Ula
answered 7 Months ago
Ula
16

You could use a Many-to-Many relationship between the Listing and the ListingFeatureValue models, then group the related listing features for a given listing by their type using the groupBy Collection method.

The Listing model:

class Listing extends Model {

    protected $hidden = [
        'features'
    ];

    protected $appends = [
        'feature_types'
    ];

    public function features(){
        return $this->belongsToMany(ListingFeatureValue::class, 'listings_features', 'listing_id', 'feature_id');
    }

    public function getFeatureTypesAttribute()
    {
        return $this->features->groupBy(function ($feature, $key) {
            return $feature->type->id;
        })->map(function($features, $key){
            $type = ListingFeatureType::find($key);
            $type->features = $features;
            return $type;
        })->values();
    }

}

The getFeatureTypesAttribute() is the star of the show here, because you can combine that with the appends array to force the Eloquent model to append that to any toArray() calls to the model instance, which is what toJson() uses when converting your model to JSON.

It may seem a little convoluted to first fetch all the listing values then divide them using the groupBy and map collection methods, but there is no native Eloquent mechanism for using hasManyThrough via many-to-many relationships. There's a different approach here if you don't like this one.

The ListingFeatureValue model:

class ListingFeatureValue extends Model
{
    public $table = 'listings_features_values';

    public function type()
    {
        return $this->belongsTo(ListingFeatureType::class, 'feature_type_id');
    }
}

I'm showing this model here because the type() relationship is called in the getFeaturesByTypeAttribute() method above and didn't want there to be any confusion.

And, just for the sake of completeness, the ListingFeatureType model:

class ListingFeatureType extends Model
{
    public $table = "listings_features_types";

    public function listings()
    {
        return $this->hasMany(ListingFeatureValue::class, 'listing_feature_type_id');
    }
}

If you wanted to eager-load the listings with their features and types for a full output of all your listings, you could do so like this:

AppListing::with('features.type')->get()->toJson();

My migration files look like this:

//create_listings_table
Schema::create('listings', function (Blueprint $table) {
    $table->increments('id');
    $table->string('uuid');
    $table->timestamps();
});

//create_listings_features_values_table
Schema::create('listings_features_values', function (Blueprint $table) {
    $table->increments('id');
    $table->string('listing_feature_text');
    $table->integer('listing_feature_type_id')->unsigned();
    $table->timestamps();
});

//create_listings_features_types_table    
Schema::create('listings_features_types', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->timestamps();
});

//create_listings_features_table
Schema::create('listings_features', function(Blueprint $table){
    $table->integer('listing_id')->unsigned();
    $table->integer('listing_feature_id')->unsigned();
});

You can learn more about the Collection methods here:

https://laravel.com/docs/5.3/collections#available-methods

...and eager-loading here:

https://laravel.com/docs/5.3/eloquent-relationships#eager-loading

...and many-to-many relationships here:

https://laravel.com/docs/5.3/eloquent-relationships#many-to-many

Saturday, May 29, 2021
 
aWebDeveloper
answered 5 Months ago
96

Every field from a record that comes out of the database is going to be a string.

This is just how many db extensions in PHP seem to work.

Ruby on Rails keeps a constant map of the schema to know that tableA.field1 is an integer, so it can convert anything to an int when it fetches the database. This obviously has some overhead to it, but it can be a useful feature. Laravel opted to not do this in the interest of performance over convenience.

You can use accessors and mutators to manually replicate this functionality.

Saturday, May 29, 2021
 
Teno
answered 5 Months ago
25

You can achieve what you need by reverting the constraints on last_day and first_day - this way there is no need to use NOT clause.

Instead of doing

WHERE NOT(`last_day` <= '2001-06-01' OR `first_day` >= '2022-12-01');

you can do

WHERE `last_day` > '2001-06-01' AND `first_day` < '2022-12-01';

And with Eloquent builder the following should do the trick:

$query = $query->where('last_day', '>', $first_day)->where('first_day', '>', $last_day);
Saturday, May 29, 2021
 
avon_verma
answered 5 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :