Create function endpoint: endpoint: /api/product/get_data/{id} - laravel

i have two tables, 'products' and 'sellers'
`Schema::create('products', function (Blueprint $table) {
$table->id();
$table->foreignId('seller_id');
$table->string('product_name');
$table->string('product_size');
$table->integer('quantity');
$table->timestamps();
$table->foreign('seller_id')->references('id')->on('sellers');`
`Schema::create('sellers', function (Blueprint $table) {
$table->id();
$table->string('seller_name');
$table->timestamps();
});`
How to create function for show only product_name, product_size and seller_name aslo how to create validation for product_size need bigger then 2(for example)
i create ProductResource
`phone_name' => $this->product_name,
'display_size' => $this->product_size,
'seller_name' => SellerResource::collection($this->whenLoaded('seller'))`
but return only product_name and product_size.
And create relationships one to many
I try to: create validate on method 'show'
response()->validate([
'product_size' => ['numeric|min:5']
]);
try to filter bu operator 'like'.
try to create 'Requests'
public function rules(){
return [
'product_size' => 'numeric|min:5'
];
}
data needs only show and validate

It almost sounds like you need to create a custom validator. Does that make sense?
The custom validator might look like
class ProductSizeValidationRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'product_size' => 'numeric|min:2',
];
}
}
You'd use it like this. UNTESTED, I hope this makes sense
https://laravel.com/docs/9.x/validation#custom-validation-rules
public function show($id)
{
$product = Product::findOrFail($id);
$this->validate(request(), (new ProductSizeValidationRequest)->rules());
return new ProductResource($product);

Related

Laravel - I want to get all the messages between the auth user and the receiver

I have a users table, a message table and a user-message table.
i want to get all the messages between the authenticated user and the receiver.
here are the tables and the models:
the users table and model are obvious.
Message model :
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Message extends Model
{
protected $fillable = [
'parent_id', 'message', 'type','status',
];
public function user_messages(){
return $this->hasMany('App\UserMessage');
}
public function users(){
return $this->belongsToMany('App\User','user_messages','message_id','sender_id')->withTimestamps();
}
}
User_message model :
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class UserMessage extends Model
{
protected $fillable = [
'message_id', 'sender_id', 'receiver_id','type','seen_status','deliver_status',
];
public function message(){
return $this->belongsTo('App\Message');
}
}
Message table :
* #return void
*/
public function up()
{
Schema::create('messages', function (Blueprint $table) {
$table->id();
$table->integer('parent_id')->nullable();
$table->longText('message')->nullable();
$table->integer('type')->default(1)->comment('1 : message , 2 : file');
$table->integer('status')->default(1);
$table->timestamps();
});
}
User_message table :
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('user_messages', function (Blueprint $table) {
$table->id();
$table->integer('message_id');
$table->integer('sender_id');
$table->integer('receiver_id');
$table->integer('type')->default(0)->comment('1 : groupe message , 0 : personal message');
$table->integer('seen_status')->default(0)->comment('1 : seen');
$table->integer('deliver_status')->default(0)->comment('1 : delivered');
$table->timestamps();
});
}
so all i want to know is how the logic inside the controller function will be.
I found the solution :
public function getMessages($id, $ids){
$final_messages_list = array();
$auth_id = $id;
$friend_id = $ids;
$messages = UserMessage::where('sender_id',$auth_id)->where('receiver_id',$friend_id)->orderby('created_at','desc')->get();
foreach($messages as $message){
$final_messages_list[] = $message->message;
}
return response()->json([
'status' => 200,
'messages' => $final_messages_list,
]);
}

Laravel return value of a specific column in a relationship

I am extremely new to Laravel. You could help me with a small problem:
I can not return in a collection, only the value of a specific column in a relation defined in the model. I will explain:
I have 2 tables:
1 - Tomos
2 - Documents
Migrations:
1- Tomos
private $table = 'tomos';
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create($this->table, function (Blueprint $table) {
$table->increments('id');
$table->string('name')->nullable(false);
$table->text('description')->nullable(true);
$table->boolean('active')->default(true);
$table->timestamps();
});
}
2- Documents
private $table = 'documents';
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create($this->table, function (Blueprint $table) {
$table->increments('id');
$table->date('date')->nullable(false);
$table->integer('provider_id');
$table->integer('tomo_id');
$table->string('folio')->nullable(false);
$table->integer('user_id');
$table->text('description');
$table->timestamps();
$table->foreign('provider_id')
->references('id')->on('providers');
$table->foreign('tomo_id')
->references('id')->on('tomos');
$table->foreign('user_id')
->references('id')->on('users');
});
}
Relations
1- Tomo
public function document()
{
return $this->hasMany(Document::class);
}
2- Document
public function tomo()
{
return $this->belongsTo(Tomo::class);
}
Controller
class Documents extends Controller
{
public function read(Request $request)
{
$provider = $request->only('id');
$documents = Document::select(['id', 'date', 'tomo_id', 'description'])
->with([
'tomo' => function ($query) {
$query->select('id', 'name');
}
])->orderBy('date', 'ASC')
->paginate(25);
return $documents;
}
}
I'm getting the following response in JSON:
current_page 1
data […]
0 {…}
id 2
date 2018-12-01
tomo_id 1
description 1
tomo {…}
id 1
name Tomo 1
But ... I do not want the key ('tomo') to return an object, I want it to return the value of the column ('name') as a string. Example:
current_page 1
data […]
0 {…}
id 2
date 2018-12-01
tomo_id 1
description 1
tomo Tomo 1
Thank you very much in advance..
First you need to add protected $appends = array('tomo_name'); as attribute, because this is one that doesn't exist on the model table.
public function getTomoNameAttribute()
{
return $this->tomo()->name;
}
After this, you can access the tomo name like this ->tomo_name
I'm not 100% sure that this code will work with just copy paste, but you might get the idea and work on it a little bit more.
Oh and be aware that loading the attribute, will query the database for that "tomo" every time.
Thank you very much to: Peter and Munteanu Petrisor
In special to : Munteanu Petrisor
I have been able to solve my problem with the solution that you propose to me, previously I had achieved it using 'join':
class Documents extends Controller
{
public function read(Request $request)
{
$provider = $request->only('id');
$documents = Document::join('tomos', 'documents.tomo_id', '=', 'tomos.id')
->join('users', 'documents.user_id', '=', 'users.id')
->where(['provider_id' => $provider])
->paginate(25, array(
'documents.id',
'documents.date',
'documents.folio',
'documents.description',
'tomos.name as tomo',
));
return $documents;
}
}
And now with your help, using attributes works wonders:
Document Model
protected $appends = [
'tomo_name',
'user_fullname'
];
public function getTomoNameAttribute()
{
return $this->tomo()->first()->name;
}
public function getUserFullNameAttribute()
{
return $this->user()->first()->first_name . ' ' . $this->user()->first()->last_name;
}
Document Controller
class Documents extends Controller
{
public function read(Request $request)
{
$provider = $request->only('id');
$documents = Document::select(['id', 'date', 'tomo_id', 'user_id', 'folio', 'description'])
->where(['provider_id' => $provider])
->orderBy('date', 'ASC')
->paginate(25);
return $documents;
}
}
And now it returns the data the way I expected
data […]
0 {…}
id 2
date 2018-12-01
tomo_id 1
user_id 1
folio 1
description 1
tomo_name 1
user_fullname First Last
Thank you so much!
try this
class Documents extends Controller
{
public function read(Request $request)
{
$provider = $request->only('id');
$documents = Document::select(['id', 'date', 'tomo_id', 'description'])
->with('tomo:id,name') // get relationship with id and name
->orderBy('date', 'ASC')
->paginate(25);
return $documents;
}
}
In your controller, try:
$documents->getCollection()->transform(function ($item) {
$item->tomo = $item->tomo->name;
return $item;
});
return $documents;

Why the related Answer model doesn't get project_id?

I have the next models:
Project <(Many to Many)> Experiment (One to Many)> Question (One to Many)> Answer
When I try Project::with('experiments.questions.answers')->find(1)
as result, I get answers not only from project with id: 1, but from others too.
Structure Answer model:
<?php
use App\Models\Answer;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateAnswersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('answers', function (Blueprint $table) {
$table->increments('id');
$table->string('answer')->nullable();
$table->integer('confidence_score')->unsigned()->default(0);
$table->integer('state')->unsigned()->default(Answer::READY);
$table->integer('element_id')->unsigned();
$table->integer('question_id')->unsigned();
$table->integer('project_id')->unsigned();
$table->timestamps();
$table->foreign('question_id')->references('id')->on('questions')->onDelete('cascade');
$table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('answers', function ($table) {
$table->dropForeign(['question_id']);
$table->dropForeign(['project_id']);
});
Schema::drop('answers');
}
}
If I add the next condition, it is work:
Project::with(['experiments.questions.answers' => function($query) {$query->where('project_id', 1);}])->find(1)
But how can I remove it from the code and to make it global?
I can't figure out why this selection touch other projects, however, if you want to create a handy shortcut to fetch project with relations - create a method in a Model or your Repository:
public function findWithExperiments($id) {
$project = Project::find($id);
$project->load(['experiments.questions.answers' => function ($query) use ($id) {
$query->where('project_id', $id);
}]);
return $project;
}
Try this code
Project::with('experiments.questions.answers')->find([1])

Get posts from multiple users in Laravel

In my site, I have a table of Users. Users can follow each other. A user can created any number of Post's.
I want to be able to see the most recent Post's from the users I've followed.
Currently my models are defined like this:
User Model:
class User extends Authenticatable
{
public function followers(){
return $this->hasMany('App\Follower', 'following');
}
public function following(){
return $this->hasMany('App\Follower', 'id');
}
public function posts(){
return $this->hasMany('App\Post', 'createdby');
}
}
Follower Model:
class Follower extends Model
{
public function postsFollowing(){
return $this->hasMany('App\Post', 'createdby', 'following');
}
}
Post Model:
class Post extends Model
{
public function user(){
return $this->belongsTo('App\User', 'createdby', 'id');
}
}
My tables are as such:
Table Name, column names
User id, name
Follower id, following
Post id, created_by
In the Follower table, id represents the user, and following represents the user being followed. If user 3 follows user 537, then id = 3, following = 537. Hope that made sense.
What I've tried:
User::following()->posts - doesn't work because
User::following() returns an Eloquent Collection object. You have
to loop through this
Looping through my followed users to get their Post's - This
doesn't work either since I want to get the top n entries sorted by
date.
Update #1
Follower Model (Updated)
class Follower extends Model
{
public function followingPosts(){
return $this->hasManyThrough(
'App\Post', 'App\Follower',
'following', 'createdby', 'id'
);
}
}
Controller
$user = Auth::user();
$posts = $user->followingPosts;
I updated followingPosts() in the Follower class with the above. The result: $posts is null
Update #2
I moved the followingPosts() to the User model:
public function followingPosts(){
return $this->hasManyThrough(
'App\Post', 'App\Follower',
'following', 'createdby'
);
}
Controller:
$user = Auth::user();
$posts = $user->followingPosts;
Now I just get all posts, even from the users I didn't follow.
Your requirement - "Users can follow each other. A user can created any number of Post's. Being able to list recent posts (limited to number) of followers or whom user is following".
You can define many-to-many relationship on the User Model (Many-To-Many relationship on self - User Model).
Create two Pivot tables
Follower-User Pivot Table
class CreateFollowerUserPivotTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('follower_user', function (Blueprint $table) {
$table->integer('follower_id')->unsigned();
$table->foreign('follower_id')->references('id')->on('users')->onDelete('cascade');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
$table->primary(['follower_id', 'user_id']);
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('follower_user');
}
}
Following-User Pivot Table
class CreateFollowingUserPivotTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('following_user', function (Blueprint $table) {
$table->integer('following_id')->unsigned();
$table->foreign('following_id')->references('id')->on('users')->onDelete('cascade');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
$table->primary(['following_id', 'user_id']);
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('following_user');
}
}
Then define the relationships in your User Model
class User extends Model
{
public function followers()
{
return $this->belongsToMany(User::class, 'follower_user', 'user_id', 'follower_id')->withTimestamps();
}
public function following()
{
return $this->belongsToMany(User::class, 'following_user', 'following_id', 'user_id' )->withTimestamps();
}
//Assuming posts table has user_id as foreign key
public function posts()
{
return $this->hasMany(Post::class);
}
//Assuming posts table has user_id as foreign key
public function recent_posts()
{
return $this->hasMany(Post::class)->take(10)->orderBy('created_at', 'desc');
}
}
Now to get who a given user is following
//Say for example we take the logged in user
$user = User::with('following.recent_posts')->whereEmail(auth()->user()->email);
foreach($user->following as $following)
{
$posts = $following->recent_posts;
}
Hope this is what you are trying to accomplish.
You can use has-many-through for this as:
public function followingPosts()
{
return $this->hasManyThrough(
'App\Post', 'App\Follower',
'follow', 'createdby', 'id'
);
}
Then you can access the posts as:
$user->followingPosts; // returns collection of post model
Note: Assuming you have a follow column in Follower table.

Display values of a list table in eloquent using laravel 5

I have this table with 4 id's related to other tables.
Table List:
id table1_id table2_id table3_id table4_id
1 2 3 2 1
2 1 4 3 3
I want now to output the values related to that table's ids
id table1_name table2_name table3_name table4_name
1 jay student singer actor
2 jeane teacher drummer actress
ListController:
public function index()
{
$res = ListModel::with('table1','table2','table3','table4')->get();
$foreach($res as r){
return $r->table1_name;
}
return view('list.index',compact('res'));
}
My problem here is that the output will be null instead of jay.How can I display now the values?Please help..
list table
public function up()
{
Schema::create('list_table', function (Blueprint $table) {
$table->increments('id');
$table->string('table1_id');
$table->string('table2_id');
$table->string('table3_id');
$table->string('table4_id');
$table->timestamps();
});
}
//additional info
Table1 Model
public function list(){
return $this->belongsTo('App\ListModel');
}
List Model
public function table1(){
return $this->hasMany("App\Table1",'id','table1_id');
}
Updated Values
id crime_type_id crime_name_id crime_suspect_id crime_victim_id
1 1 1 1 1
Expected output:
crime_type_des crime_name_des crime_suspect_name victim_name
against property theft Mcdonald Hillary
ReportController:
public function index()
{
$display_crime = CrimeReport::all();
return view('crimereports.index',compact('display_crime'));
}
report_table:
public function up()
{
Schema::create('crime_reports', function (Blueprint $table) {
$table->increments('id');
$table->string('crime_type_id');
$table->string('crime_name_id');
$table->string('suspect_id');
$table->string('victim_id');
$table->timestamps();
});
}
//additional info
CrimeName Model
public function crimeReport(){
return $this->belongsTo('App\CrimeReport');
}
Crime Report Model
public function crimeName(){
return $this->hasMany("App\CrimeName",'id','crime_name_id');
}
//Rest for CrimeReportController
public function index()
{
$display_crime = CrimeReport::all();
return view('crimereports.index',compact('display_crime'));
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
$display_crime_type = CrimeType::lists('crime_type','id');
$display_crime_name = CrimeName::lists('crime_description','id');
return view('crimereports.create',compact('display_crime_type','display_crime_name'));
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(CrimeNewReportRequest $request)
{
$input = $request->all();
CrimeReport::create($input);
return redirect()->back()->withSuccess("Fields were inserted!");;
}
Change your relation definition as below:
Table1 Model
public function list(){
return $this->hasMany('App\ListModel');
}
List Model
public function table1(){
return $this->belongsTo("App\Table1");
}
You need update your index method as below, you could dump $rows to check if this work.
ListController
public function index()
{
$res = ListModel::with(['table1','table2','table3','table4'])->get();
$rows = [];
$foreach($res as r) {
$rows[] = [r->table1->name, r->table2->name, r->table3->name, r->table4->name];
}
dd($rows);
}
Your accessing table1_name on the original model change the _ to -> ( $r->table1->name)
EDIT:
Now it's starting to become much more readable. Here are what I think the relationships should be.
CrimeReport.php
public function crimeType()
{
return $this->belongsTo(CrimeType::class);
}
public function crimeName()
{
return $this->belongsTo(CrimeName::class);
}
public function suspect()
{
return $this->belongsTo(Suspect::class);
}
public function victim()
{
return $this->belongsTo(Victim::class);
}
There really doesn't seem to be a need to define the inverse of any of there relationships right away, if the need arises later then add them but there is no point creating the relation just because its there.
Now to make showing the report easy lets use some joins instead or eager loading.
CrimeReportController.php
public function index()
{
$results = CrimeReport::query()
->join('crime_types as ct','ct.id', '=', 'crime_reports.crime_type_id')
->join('crime_names as cn','cn.id', '=', 'crime_reports.crime_name_id')
->join('suspects as s','s.id', '=', 'crime_reports.suspect_id')
->join('victims' as v','v.id', '=', 'crime_reports.victim_id')
->get([
'crime_report.*', //to get ids and timestamps
'ct.name as crime_type',
'cn.name as crime_name',
'suspect.name as suspent_name',
'victim.name as victim_name'
])
dd($results->toArray());
}
Now $results will still be a collection of CrimeReport so you can still have access to all the model goodies you might want to throw in there. In addition to that you also already have your table, you can just print these out into an html table and you have your report.
If you were wanted to add some cool search stuff to the query then you can use whereHas to do that:
//this would just go before the get()
$query->whereHas('suspect', function($q){
$q->where('hair_color','=','brown')
->whereBetween('height',5.8,6)
})
Of course you might also want to make some of those leftJoins instead since I assume they won't all have a victim/suspect

Resources