Laravel : How can i insert data on multiple tables - laravel

Do not know which way is better to perform this operations.Having a two tables inquiry_master and inquiry_plan.Already define a relationship.
Migration files:
>> INQUIRY_MASTER
public function up()
{
Schema::create('inquiry_master', function (Blueprint $table) {
$table->increments('id');
$table->dateTime('created_date_time')->nullable();
$table->unsignedInteger('user_id')->nullable();
$table->string('stitch_video_path')->nullable();
$table->enum('completion_status',['Complete','Pending']);
$table->foreign('user_id')->references('id')->on('users');
});
}
>> INQUIRY_PLAN
public function up()
{
Schema::create('inquiry_plan', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('inquiry_id');
$table->string('title_vacation');
$table->string('email');
$table->string('phone_no', 20)->nullable();
$table->dateTime('start_date')->nullable();
$table->dateTime('end_date')->nullable();
$table->foreign('inquiry_id')->references('id')->on('inquiry_master');
});
}
Currently define a function to insert data only on inquiry_plantable.
function which define on my controller.
Controller Code :
public function addactivity(Request $request) {
$validator = Validator::make($request->all(), Inquiryplan::planRules(), Inquiryplan::PlanMessages());
if ($validator->fails()) {
return back()->with('error', "Unable to send contact request.!!")->withInput()->withErrors($validator);
}
$plandetails = Inquiryplan::SaveOrUpdate($request);
if($plandetails !== false) {
return redirect()->route('plan')->with('success', trans('Plan details added successfully.!!'));
} else {
return back()->with('error', "Unable to save plan details.!!")->withInput();
}
}
And finally save function on my model inquiryplan model.
Model code :
<?php
namespace App;
use Illuminate\Http\Request;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Input;
class Inquiryplan extends Model
{
protected $table = 'inquiry_plan';
protected $fillable = [
'inquiry_id',
'title_vacation',
'email',
'phone_no',
'start_date',
'end_date'
];
public $timestamps = false;
public static function SaveOrUpdate(Request $request) {
try {
$id = $request->get('id', false);
$plandetails = false;
DB::transaction(function () use ($request, &$plandetails, $id) {
$plandetails = $id ? Inquiryplan::findOrFail($id) : new Inquiryplan();
$plandetails->fill($request->all());
try {
$plandetails->save();
} catch (\Exception $ex) {
throw $ex;
}
});
return $plandetails;
} catch (\Exception $ex) {
throw $ex;
}
}}
Before saving a data on inquiry_plan table, one entry should go to the inquiry_master table.How can i do this ?

A couple things. First, Laravel already has exception handlers built into most if not all of it's functionality so providing you own exception is redundant. A good rule of thumb for this is - if you are expecting an error, this is not the case to use an exemption. So you can refactor this code significantly. As for the additional database entry, simply insert it before your inquiry_plan table logic:
public static function SaveOrUpdate(Request $request) {
$id = $request->get('id', false);
$plandetails = false;
DB::transaction(function () use ($request, &$plandetails, $id) {
$planDetails = $id ? Inquiryplan::findOrFail($id) : new Inquiryplan();
//plan_master
$inquiryMaster = ...
//plan_details
$planDetails->fill($request->all());
$planDetails->save();
});
return $planDetails;
}}
Hopefully this helps!
As an aside, I would recommend splitting the create and update tasks into different controller methods...makes the code cleaner and helps for maintainability down the road.

Related

Import [insert or update] Excel/CSV to MySQL database using maatwebsite in laravel 7

While importing/uploading an excel file, if the data is already present in the excel file then update it in the Database or else insert it. This means before inserting should check with the database. So, anyone please help to solve with this issue:
This is the Import class for customers:
<?php
namespace App\Imports;
use App\Customer;
use Illuminate\Validation\Rule;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Concerns\Importable;
class ImportCustomers implements ToModel, WithHeadingRow, WithValidation
{
use Importable;
/**
* #param array $row
*
* #return \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $row)
{
// Check mobile already exists
/* $count = Customer::where('mobile',$row['mobile'])->count();
dd($count);
if($count > 0){
return null;
} */
return new Customer([
'customer_name' => $row['customer_name'],
'mobile' => $row['mobile'],
'email' => $row['email']
]);
}
public function rules(): array
{
return [
'*.customer_name' => 'required',
'*.mobile' => 'required|unique:customers',
'*.email' => 'required',
];
}
}
/* This is Controller:*/
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Requests\CustomerImportRequest;
use App\Imports\ImportCustomers;
use App\Exports\ExportCustomers;
use Maatwebsite\Excel\Facades\Excel;
use DB;
use App\Customer;
use Illuminate\Support\Arr;
class ImportExportExcelController extends Controller
{
protected $customers;
public function __construct(Customer $customers){
$this->customers = $customers;
}
public function index()
{
$customers = $this->customers->orderBy('id', 'desc')->get();
return view('ImportExportExcel', compact('customers'));
}
public function importExcel(CustomerImportRequest $request)
{
try {
if ($request->hasFile('import_file'))
{
$file = $request->file('import_file');
$columnRead = (new ImportCustomers)->toArray($file);
$customerCheck = $this->customers->where('mobile',$columnRead[0][1]["mobile"])->first(); //**here not getting result, rather shows null**
//dd($customerCheck);
if($customerCheck)
{
$customers = $customerCheck;
/*
**How to update if duplicates are found and display old values updated. How to achieve this?**
*/
}else{
$customers = new $this->customers;
Excel::import(new ImportCustomers, $file);
return redirect()->back()->with('success','Data imported successfully.');
}
}
} catch (\Maatwebsite\Excel\Validators\ValidationException $e) {
$failures = $e->failures();
//dd($failures);
return redirect()->back()->with('import_errors', $failures);
}
}
public function exportExcel()
{
$customers = Customer::select(["customer_name", "mobile", "email"])->get();
return Excel::download(new ExportCustomers($customers), 'customers.xlsx');
}
}
/This is the database migration schema:/
public function up()
{
Schema::create('customers', function (Blueprint $table) {
$table->id();
$table->string('customer_name');
$table->string('mobile', 13)->unique();
$table->string('email')->nullable();
$table->timestamps();
});
}
Here "mobile" is unique, So if values like customer_name, and email are with modified values in an excel sheet with the same mobile no. then while importing, values should be updated.
excel sheet
I have used maatwebsite with Laravel 6
Controller :
Excel::import(new ImportCustomers(), $file);
then you could apply your logic at the Import class for customers:
public function model(array $row)
{
try {
$mobile = $row[1]; // referenced by row
$customer_name = $row[0];
$email = $row[1];
$customer = Customer::where('mobile', $mobile)->first();
//apply your logic
if (!$customer) { // you may not need if else, if no customer exists then create a new record and assign mobile
$customer = new Customer();
$customer->mobile = $mobile;
}
$customer->customer_name = $customer_name;
$customer->email = $email;
$customer->save();
return $customer;
} catch (\Exception $ex) {
dd($ex);
return;
}
}
Also please remove the rule about mobile, I think this should work
"*.mobile' => 'required',"
because your logic handles that mobile is unique.
//Check for the existing value in database and if result is found do this.
public function model(array $row)
{
// Check mobile already exists
$count = Customer::where('mobile',$row['mobile'])->first();
if($count){
return;
}
else{
return new Customer([
'customer_name' => $row['customer_name'],
'mobile' => $row['mobile'],
'email' => $row['email']
]);
}
}

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,
]);
}

Deleted_by is not changing while i delete a data using observers;

I want to have fields created_by,updated_by and deleted_by and want to update these fields automatically. created_by,updated_by is working but deleted_by is not working.i am using an observer to perform this task. When i use dd($model) in deleting function in observer it shows the collection or values but the deleted_by is not updating.
My model
namespace App\Model;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Observers\UserIdFinderObserver;
class supplier extends Model
{
use SoftDeletes;
protected $fillable = [
'name', 'address', 'contact','contact_person_name','country','email'
];
public static function boot()
{
parent::boot();
$class = get_called_class();
$class::observe(new UserIdFinderObserver());
}
}
my migration file
public function up()
{
Schema::create('suppliers', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('contact_person_name');
$table->string('country')->nullable();
$table->text('address')->nullable();
$table->string('contact')->nullable();
$table->string('email')->nullable();
$table->string('created_by')->nullable();
$table->string('updated_by')->nullable();
$table->string('deleted_by')->nullable();
$table->softDeletes();
$table->timestamps();
});
}
My delete function in controller
public function destroy(supplier $supplier)
{
try{
$supplier->delete();
return redirect()->route('supplier.index')->with('success', 'Supplier is deleted successfully');
}catch(Exception $e){
return redirect()->back()->withErrors($e->getMessage());
}
}
My Observer
namespace App\Observers;
class UserIdFinderObserver
{
private $userID;
public function __construct(){
$this->userID = auth()->id();
}
public function saving($model)
{
$model->created_by = $this->userID;
}
public function updating($model){
$model->updated_by = $this->userID;
}
public function creating($model)
{
$model->created_by = $this->userID;
}
public function deleting($model)
{
$model->deleted_by = $this->userID;
}
}

Completion system with Laravel + VueJS

I've been tring for hours to define my relations for a completion system but I failed.
I have a table Users and a table Episodes, and I would like to get in my views if the User has completed an episode.
I created a "completions" table with user_id and episode_id and a boolean field called "completed"
Is it a manytomany relation ? I'd like to have something like $episode->completed which gave me True if the logged in user finished the course, but I can't find my way... I just wanna know how to define my relations, not a whole work done.
Thank you very much !!!!
I believe you can tell Laravel what table to use and also query the pivot column.
//user model
public function episodes(){
return $this->belongsToMany( 'App\Episode', 'completions', 'user_id', 'episode_id' );
}
public function completedEpisodes(){
return $this->belongsToMany( 'App\Episode', 'completions', 'user_id', 'episode_id' )
->wherePivot('completed','=', true)->get();
}
//episode model
public function users(){
return $this->belongsToMany( 'App\User', 'completions', 'episode_id', 'user_id' );
}
The alternative would be to create your pivot as episode_user and laravel will auto detect it as the pivot, add a completed boolean to that table and it would function with just:
//user model
public function episodes(){
return $this->belongsToMany('App\Episode');
}
public function completedEpisodes(){
return $this->belongsToMany('App\Episode')
->wherePivot('completed','=', true)->get();
}
//episode model
public function users(){
return $this->belongsToMany('App\User');
}
Query if episode is complete:
//maybe, haven't tried this
//user
public function hasCompletedEpisode($id){
return $this->belongsToMany('App\Episode')->wherePivot('episode_id','=', $id)
->wherePivot('completed','=', true)->get();
}
//episode
public function hasCompletedEpisode($id){
$user_id = Auth::id();
return $this->belongsToMany('App\User')->wherePivot('user_id','=', $user_id)
->wherePivot('completed', true)->get();
}
If I was you, I would use a custom intermediate table. You can implement this as follows:
Migrations
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->timestamps();
});
Schema::create('episodes', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->timestamps();
});
Schema::create('watches', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('epsiode_id');
$table->boolean('completed');
$table->timestamps();
});
Models
class User extends Model
{
protected $guarded = [];
public function watchedEpisodes()
{
return $this->hasMany(Episode::class)->using(Watch::class);
}
public function watches()
{
return $this->hasMany(Watch::class);
}
}
class Episode extends Model
{
protected $guarded = [];
public function users()
{
return $this->hasMany(User::class)->using(Watch::class);
}
}
class Watch extends \Illuminate\Database\Eloquent\Relations\Pivot
{
protected $table = 'watches';
protected $guarded = [];
public static function create(User $user, Episode $episode, bool $completed = false)
{
$watch = new self();
$watch->user_id = $user->id;
$watch->epsiode_id = $episode->id;
$watch->completed = $completed;
$watch->save();
return $watch;
}
public function user()
{
return $this->hasOne(User::class);
}
public function episode()
{
return $this->hasOne(User::class);
}
}
Example Use
$user = User::create(['name' => 'Big Watcher']);
$episode1 = Episode::create(['name' => 'Episode 1']);
$episode2 = Episode::create(['name' => 'Episode 2']);
$episode3 = Episode::create(['name' => 'Episode 3']);
$episode4 = Episode::create(['name' => 'Episode 4']);
Watch::create($user, $episode1);
Watch::create($user, $episode2);
Watch::create($user, $episode3);
return $user->watchedEpisodes;

Laravel : foreign key -> doesn't have a default value

Hi ! I read other questions but I don't find my answer.
I want to create data but give me this error:
SQLSTATE[HY000]: General error: 1364 Field 'user_id' doesn't have a
default value
Controller:
public function store(BannerRequest $request)
{
Banner::create($request->all());
flash()->success('Success', 'Your banner has been created.');
return back(); // temporary
}
and my Table:
Schema::create('banners', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
$table->string('street', 40);
$table->string('city', 40);
$table->string('zip', 15);
$table->string('country', 40);
$table->string('state', 40);
$table->integer('price');
$table->text('description');
$table->timestamps();
});
and this is my model :
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\Banner;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class Photo extends Model
{
protected $table = 'banners_photos';
protected $fillable = ['name', 'path', 'Thumbnail_path'];
protected $file;
public function banners()
{
return $this->belongsTo(Banner::class);
}
public static function formFile(UploadedFile $file)
{
$photo = new static;
$photo->file = $file;
$photo->fill([
'name' => $photo->fileName(),
'path' => $photo->filePath(),
'Thumbnail_path' => $photo->ThumbnailPath()
]);
return $photo;
}
public function fileName()
{
$name = sha1(time() . $this->file->getClientOriginalName());
$extension = $this->file->getClientOriginalExtension();
return "{$name}.{$extension}";
}
public function filePath()
{
return $this->baseDir() . DIRECTORY_SEPARATOR . $this->fileName();
}
public function ThumbnailPath()
{
return $this->baseDir() . '/tn-' . $this->fileName();
}
public function baseDir()
{
return 'images/photos';
}
public function upload()
{
$this->file->move($this->baseDir(), $this->fileName());
$this->makeThumbnail();
return $this;
}
public function makeThumbnail()
{
Image::make($this->filePath())->fit(200)->save($this->ThumbnailPath());
return $this;
}
}
This code worked already and after refactoring become difficult.
Thank for your helps.
According to that message user_id is not set, therefore it's likely not present in $request->all().
If user_id is present, then you might want to check the user_id is in the $fillable property of your Banner model.
If you are trying to assign your banner to the current user, you could do something like this:
$data = $request->all();
$data['user_id'] = $request->user()->id;
Banner::create($data);
Assuming all other data in the BannerRequest is correct and the user is signed in this should work.
SIDE NOTE: ->onUpdate('cascade') looks dangerous, if the user is modified the database will try and drop the banner. not sure if that is your intention.
Solution :
In public function store :
$banner = auth()->user()->publish(new Banner($request->all()));
add public function publish in User model:
public function publish(Banner $banner)
{
return $this->banners()->save($banner);
}
In your migratin you have this
$table->integer('user_id')->unsigned();
the errors is because in your request->all() you don't have an user_id field, if you need it add it, if not in your migration add
$table->integer('user_id')->unsigned()->nullable();

Resources