I am currently navigating to a ticket using the slug set by the title example blah-blah-blah and want to use uuid instead of 336c64de-5dcb-34bc-9511-a48242b9zzzb. What is the best approach to take for Laravel 8? I am using Laravel Jetstream with Livewire stack.
Current model code
public function getRouteKeyName()
{
return 'slug';
}
public function setSlugAttribute($slug)
{
$this->attributes['slug'] = Str::slug($slug);
}
public function path()
{
return '/tickets/' . $this->slug;
}
Ticket Migration
Schema::create('tickets', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id');
$table->foreignId('ticket_type_id');
$table->string('slug')->unique();
$table->string('title');
$table->text('body');
$table->string('email')->nullable();
$table->string('url')->nullable();
$table->boolean('locked')->default(false);
$table->unsignedInteger('visits')->default(0);
$table->timestamps();
});
add uuid in migration
$table->uuid('uuid')->unique();
if you want to use uuid for foreign key you have to add
$table->uuid('ticket_type_id');
You can override boot() method of model and set closure to the creating event.
public function boot()
{
parent::boot();
static::creating(function($user) {
$user->uuid = (string) Str::uuid();
});
}
Related
I have a customer model that has many contacts. I defined a relationship to get the most recent contact of the customer using the "Has One Of Many" relationship in Laravel 8:
Models
class Customer extends Model
{
use HasFactory;
public function contacts()
{
return $this->hasMany(Contact::class);
}
public function latestContact()
{
return $this->hasOne(Contact::class)->ofMany('contacted_at', 'max')->withDefault();
}
}
class Contact extends Model
{
use HasFactory;
protected $casts = [
'contacted_at' => 'datetime',
];
public function customer()
{
return $this->belongsTo(Customer::class);
}
}
Migration (contact model)
class CreateContactsTable extends Migration
{
public function up()
{
Schema::create('contacts', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->softDeletes();
$table->foreignID('customer_id');
$table->string('type');
$table->dateTime('contacted_at');
});
}
}
In my view, I want to show all customers and order them by their latest contact. However, I can't figure out how to do that.
I tried to achieve it via the join method but then I obviously get various entries per customer.
$query = Customer::select('customers.*', 'contacts.contacted_at as contacted_at')
->join('contacts', 'customers.id', '=', 'contacts.customer_id')
->orderby('contacts.contacted_at')
->with('latestContact')
Knowing Laravel there must be a nice way or helper to achieve this. Any ideas?
I think the cleanest way to do this is by using a subquery join:
$latestContacts = Contact::select('customer_id',DB::raw('max(contacted_at) as latest_contact'))->groupBy('customer_id');
$query = Customer::select('customers.*', 'latest_contacts.latest_contact')
->joinSub($latestContacts, 'latest_contacts', function ($join){
$join->on([['customer.id', 'latest_contacts.customer_id']]);
})
->orderBy('latest_contacts.latest_contact')
->get();
More info: https://laravel.com/docs/8.x/queries#subquery-joins
I suspect there is an issue with your migration, the foreign key constraint is defined like this:
Check the documentation:
https://laravel.com/docs/8.x/migrations#foreign-key-constraints
Method 1: define foreign key constraint
public function up()
{
Schema::create('contacts', function (Blueprint $table) {
$table->id();
$table->foreignId('consumer_id')->constrained();
$table->string('type');
$table->dateTime('contacted_at');
$table->timestamps();
$table->softDeletes();
});
}
Method 2: define foreign key constraint
public function up()
{
Schema::create('contacts', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('customer_id');
$table->foreign('customer_id')->references('id')->on('customers');
$table->string('type');
$table->dateTime('contacted_at');
$table->timestamps();
$table->softDeletes();
});
}
I'm not sure if it's name is reverse relation or not but
I have event model which contains :
public function venue()
{
return $this->hasOne('App\Models\Venue', 'id','venue_id');
}
So basicly I can access to venue data with event model but also I want to access all event data for spesific venue. I know I can do this with queries etc. but is it possible to do that with relations.
Event Migration
$table->id();
$table->string('name');
$table->string('slug')->unique();
$table->unsignedBigInteger('venue_id');
$table->decimal('price');
$table->text('content');
$table->timestamps();
$table->foreign('venue_id')->references('id')->on('venues');
Venue Migration
$table->id();
$table->string('name')->unique();
$table->string('slug')->unique();
$table->string('address');
$table->text('about');
$table->timestamps();
Event Model
public function venue()
{
return $this->hasOne('App\Models\Venue', 'id','venue_id');
}
Venue Model
public function events()
{
return $this->belongsTo(Event::class, 'venue_id','id');
}
Yes it possible. You can use belongsTo
Venue
public function events() {
return $this->hasOne(Event::class);
}
Event
public function venue()
{
return $this->belongsTo(Venue::class);
}
Then you can access like below
$venue = Venue::with('events')->where('slug',$venue_slug)->get();
foreach($venue as $key=>$value){
dd($value->events);
}
Yes! Since, one venue can have multiple events, you can define a relationship like this in Venue Model:
public function events()
{
return $this->belongsTo(Event::class);
}
See: https://laravel.com/docs/8.x/eloquent-relationships#one-to-many-inverse
I have a laravel model based on the following table:
public function up()
{
Schema::create('things', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('label');
$table->foreignId('user_id')->nullable()->constrained('users');
});
There is also a pivot table that makes this a many-to-many self-referential model.
public function up()
{
Schema::create('thing_thing', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('message')->nullable();
$table->unsignedBigInteger('parent_id')->nullable();
$table->unsignedBigInteger('child_id')->nullable();
$table->unique(['parent_id', 'child_id']);
$table->foreign('parent_id')->references('id')->on('things')->onDelete('cascade');
$table->foreign('child_id')->references('id')->on('things')->onDelete('cascade');
});
}
When I create a Nova resource linked to this model, I would like to restrict the attaching of a thing to itself. So a thing with id = 1, for example, would not show up in the selector for attachments for the thing with id = 1. Here's my Nova resource:
public function fields(Request $request)
{
return [
ID::make(__('ID'), 'id')->sortable(),
Text::make('label'),
ID::make('user_id')->hideWhenUpdating()->hideWhenCreating(),
BelongsToMany::make('Trees', 'trees'),
BelongsToMany::make('Things', 'childOf'),
BelongsToMany::make('Things', 'parentOf')
];
}
You can solve this through the App\Nova\Ressource's relatableQuery method. Simply override the method in your nova resource:
class Thing extends Resource {
// ...
public static function relatableQuery(NovaRequest $request, $query)
{
// Make sure you only apply the filter to the things-things relatable query
if( $request->route('resource') === 'things' ) {
$currentId = $request->route('resourceId');
$query->where('id', '!=', $currentId);
}
return $query
}
}
You can find the docs here
In addition, you might want to make the column-combination of parent_id and child_id unique in your migration to further ensure uniqueness.
I'm trying to give ability on user to see his orders. I have created relationships but when i (dd) the result of the function, the related model attributes are empty.
I don't know what is wrong.
Here is my buyer function
//Buyer Orders
public function myOrders()
{
$user = User::find(auth()->user()->id);
$user = $user->products();
dd($user);// related model attributes shows empty
return view('myOrders')->with(compact('user'));
}
and here is my user
public function products()
{
return $this->hasMany(Products_model::class);
}
public function orders()
{
return $this->hasMany(Order::class);
}
public function allOrdersBuyerSeller()
{
return $this->hasMany(OrderProduct::class);
}
products_model
public function orders()
{
return $this->belongsToMany('App\Order', 'order_product');
}
public function user()
{
return $this->belongsTo('App\User');
}
User Migration
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
Product Migration
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('pro_name');
$table->integer('pro_price');
$table->text('pro_info');
$table->integer('stock');
$table->integer('category_id');
$table->string('image')->nullable();
$table->timestamps();
$table->bigInteger('seller_id')->unsigned()->index();
$table->foreign('seller_id')->references('id')->on('users')->onDelete('cascade');
});
}
I would like to see the attributes of the table like price, name, info, img and etc.
Barring the comments about your code, the reason you're not seeing the result of your products query is that you're not passing a closure to the query.
$user = $user->products();
Currently, $user is a QueryBuilder instance. Until you use a closure, like first(), get(), paginate(), etc, you won't be able to see the rows. Modify your code to the following:
$products = $user->products;
// OR
$products = $user->products()->get();
If you omit the (), it will load the relationship using products()->get(), unless already loaded.
Edit: You likely need to include foreign keys to your relationships as the Model name won't match:
User.php
public function products(){
return $this->hasMany(Product_model::class, "seller_id", "id");
}
Probably best to review the contents of the documentation for Relationships; https://laravel.com/docs/5.8/eloquent-relationships. There's a lot of incorrect practices going on with your naming, querying, etc.
The following code in tinker returns a null value while it should return the project to which the first task is linked.
App\Task::first()->projects;
Already tried renaming the method names, column names in migrations, tried exiting tinker and logging back in
Project Migration
public function up()
{
Schema::create('projects', function (Blueprint $table) {
$table->bigIncrements('id');
$table->text('title');
$table->string('description');
$table->timestamps();
});
}
Task Migration
public function up()
{
Schema::create('tasks', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedInteger('project_id');
$table->string('description');
$table->boolean('completed')->default(false);
$table->timestamps();
});
}
Project.php
use App\Task;
class Project extends Model
{
protected $fillable = ['title','description'];
public function tasks(){
return $this->hasMany(Task::class);
}
}
Task.php
use App\Project;
class Task extends Model
{
protected $fillable = [
'completed'
];
public function projects(){
return $this->belongsTo(Project::class);
}
}
If anyone could just review this piece of code and let me know where I have made any conventional\idiotic mistakes (since Im new to route model binding) it would be of great help!
A task belongs to a project, so rename projects to project as it is singular. If you keep projects then provide the column name as second parameter:
public function projects(){
return $this->belongsTo(Project::class, 'project_id');
}
// I suggest this
public function project(){
return $this->belongsTo(Project::class);
}
Your column types are different, for the id of the project you use Big Integer and for the reference you use Integer, so this:
$table->unsignedInteger('project_id');
should be this:
$table->unsignedBigInteger('project_id');
// also good to make the relationship on the Database level:
$table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade');