Laravel custom soft delete restore not working properly - laravel-5

Adding new columns deleted_flag tiny integer to the Larave soft delete feature.
trait CustomSoftDeleteTrait
{
use SoftDeletes;
protected function runSoftDelete()
{
$query = $this->setKeysForSaveQuery($this->newModelQuery());
$time = $this->freshTimestamp();
$columns = [$this->getDeletedAtColumn() => $this->fromDateTime($time)];
$this->{$this->getDeletedAtColumn()} = $time;
if ($this->timestamps && ! is_null($this->getUpdatedAtColumn())) {
$this->{$this->getUpdatedAtColumn()} = $time;
$columns[$this->getUpdatedAtColumn()] = $this->fromDateTime($time);
}
$columns[$this->getDeletedFlagColumn()] = 1; //<-- here is the deleting
$query->update($columns);
}
protected function restore()
{
if ($this->fireModelEvent('restoring') === false) {
return false;
}
$this->{$this->getDeletedFlagColumn()} = 0; //<-- here is restoring
$this->{$this->getDeletedAtColumn()} = null;
$this->exists = true;
$result = $this->save();
$this->fireModelEvent('restored', false);
return $result;
}
public function getDeletedFlagColumn()
{
return defined('static::DELETED_FLAG') ? static::DELETED_FLAG : 'deleted_flag';
}
}
Migration for the model,
Schema::create('families', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->integer('family_type');
$table->timestamp('create_date')->nullable();
$table->timestamp('update_date')->nullable();
$table->timestamp('delete_date')->nullable();
$table->tinyInteger('delete_flg')->nullable();
});
Using the custom trait in model,
class Family extends Model
{
use CustomSoftDeleteTrait;
protected $guarded = [
'id',
];
const CREATED_AT = 'create_date';
const UPDATED_AT = 'update_date';
const DELETED_AT = 'delete_date';
const DELETED_FLAG = 'delete_flg';
}
When the model is deleted using $family->delete(), both columns delete_date and delete_flg are set. When the model is restored, only one field delete_date is set to null. The delete_flg field remains unchanged at 1.

This is quite a 'tricky' error to spot.
But all you have to do is changing the modifier of your restore() function from protected to public in your custom Trait.
protected function restore() { /**/ }
should turn into
public function restore() { /**/ }
The protected function cannot be accessed from your Family Model. So PHP simply uses the original restore() method from the Eloquent Soft Delete Trait.

Related

laravel update() is not working on some models

I am trying to update the database record but Laravel update() function is not working. I have fillable array in the model. but still, it is not working.
The Property Model:
class Property extends Model
{
use HasFactory;
protected $table = 'properties';
protected $primaryKey = 'proID';
public $timestamps = false;
protected $fillable = [ 'proID', 'ProStatus', 'ProPurpose', 'ProType', 'SubType', 'basePrice', 'unitPrice', 'Width', 'Length', 'LandArea','PropertyNumber', 'water', 'electricity', 'gas', 'severage', 'fk_Street', 'createdBy', 'delete'];
public function streets(){
return $this->belongsTo(Street::class,'fk_Street');
}
public function hasInstallments(){
return $this->hasMany(Installments::class,'proID');
}
The PropertyController:
public function destroy($id)
{
$property = Property::find($id);
$property->delete = true;
if($property->save()){
return response()->json(['success'=>true]);
}
}
the $property->update() always returns true but record does not update in database.
The method update() is for mass update wich require an array of attributes and bypass mutators.
public function destroy($id)
{
$property = Property::find($id);
$property->update(['delete' => 1]);
}
You might want to use save() instead
public function destroy($id)
{
$property = Property::find($id);
$property->delete = 1;
$property->save();
}
Both will update the record, you'll need to implement your method's return logic on top of this code but as for updating the record, I think you get the idea.
Your property table primary key is "proID"
public function destroy($id)
{
$property = Property::where('proID', $id)->first();
if($property->update(['delete' => 1])) {
return response()->json(['success' => true]);
}
}

My hasMany in laravel response null, my model its correct

I have problem my has many relation response null.
this is my model
class Diskusi extends Model
{
protected $table = 'tbl_diskusi';
protected $hidden = [
'topic'
];
public function user(){
return $this->belongsTo(User::class,'id_user');
}
public function category(){
return $this->belongsTo(Category::class);
}
public function pets_category(){
return $this->belongsTo(PetsCategory::class);
}
}
this is my another model
class PetsCategory extends Model
{
//
protected $table = 'tbl_pets_category';
public function diskusi(){
return $this->hasMany(Diskusi::class,'id_pets_category');
}
}
and another
class Category extends Model
{
//
protected $table = 'tbl_category';
public function diskusi(){
return $this->hasMany(Diskusi::class,'id_category');
}
}
and this is my migration for Diskusi
class CreateTblDiskusi extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('tbl_diskusi', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title');
$table->string('content');
$table->string('topic');
$table->unsignedBigInteger('id_user');
$table->unsignedBigInteger('id_category');
$table->unsignedBigInteger('id_pets_category');
$table->timestamps();
$table->foreign('id_user')->references('id')
->on('users')->onDelete('cascade');
$table->foreign('id_category')->references('id')
->on('tbl_category')->onDelete('cascade');
$table->foreign('id_pets_category')->references('id')
->on('tbl_pets_category')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('tbl_diskusi');
}
}
the condition is
i want my Diskusi have one category, and one pets_category
but when i create Diskusi like this
public function create(Request $request)
{
$diskusi = new Diskusi;
$diskusi->title = $request->title;
$diskusi->content = $request->content;
$diskusi->topic = $request->topic;
$diskusi->id_user = Auth::user()->id;
$diskusi->id_category = $request->id_category;
$diskusi->id_pets_category = $request->id_pets_category;
if ($request->photo != ''){
foreach ($request->photo as $itemPhoto) {
# code...
$photo = new Photo;
$rand = $this->generateRandomString() . 'jpg';
//taroh foto di server
// file_put_contents('storage/photo/diskusi/' . $rand , base64_decode($request->photo));
$photo->path_photo = $rand;
$photo->save();
}
}
$diskusi->save();
$diskusi->user;
$diskusi->category;
$diskusi->pets_category;
return response()->json([
'success' => true,
'message' => 'posted',
'post' => $diskusi
]);
}
the response like this
please help me, i tried with many tutorial relational laravel but it's not working for me. i dont know where my false, please tell me my false.
*note: sorry for bad english
You've to define your foreign key in relationship.
public function category(){
return $this->belongsTo(Category::class,'id_category','id');
}
public function pets_category(){
return $this->belongsTo(PetsCategory::class,'id_pets_category','id');
}
If you don't pass the foreign key then by default it judges 'category_id' or 'pets_category_id' but you've given id_category and id_pets_category

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();

How to display a table in a popup box?

I have the form below, with 4 comboboxes "Metier=profession" "tache=task" "tacrification=pricing" and "technicien=technician", I select a Metier and a tache, after this I want that a popup box appears and show me a table that contains all the "techniciens" and their "tarification" (of course only the "techniciens" that are related with the "tache" already selected).
Please see the second form. After this I select a "technician" from that table a now the form is completely filled with the "technician" and it's "pricing".
What I'm trying to do:
intervention
Schema::create('interventions', function (Blueprint $table) {
$table->increments('id');
$table->date('date_intervention')->nullable();
$table->string('description');
$table->dateTime('duree_prevu');
$table->boolean('statut');
$table->integer('technicien_id')->unsigned();
$table->foreign('technicien_id')->references('id')-
>on('techniciens');
$table->integer('tarification_id')->unsigned();
$table->foreign('tarification_id')->references('id')-
>on('tarificationtaches');
$table->integer('client_id')->unsigned();
$table->foreign('client_id')->references('id')->on('Clients');
$table->timestamps();
});
tarificationtache
Schema::create('tarificationtaches', function (Blueprint $table) {
$table->increments('id');
$table->float('tarif', 8,2);
$table->integer('tache_id')->unsigned();
$table->foreign('tache_id')->references('id')->on('taches');
$table->datetime('deleted_at')->nullable();
$table->timestamps();
});
Intervention class
class Intervention extends Model
{
protected $fillable = [ ];
protected $guarded = [];
public function avisintervention()
{
return $this->hasMany(AvisIntervention::class);
}
public function technicien()
{
return $this->belongsTo(technicien::class);
}
public function client()
{
return $this->belongsTo(Client::class);
}
public function tarificationtache()
{
return $this->belongsTo('App\Tarificationtache','tarification_id');
}
tache class
class tache extends Model
{
use SoftDeletes;
protected $guarded = [];
protected $dates = ['deleted_at'];
public function metier()
{
return $this->belongsTo(Metier::class);
}
public function tarificationtache()
{
return $this->hasMany(Tarificationtache::class);
}
}
metier class
class metier extends Model
{
use SoftDeletes;
protected $guarded = [];
protected $dates = ['deleted_at'];
public function taches()
{
return $this->hasMany(Tache::class);
}
public function techniciens()
{
return $this-
>belongsToMany('App\technicien','technicien_zone','metier_id','technicien_id');
}
}
tarificationtache class
class tarificationtache extends Model
{
use SoftDeletes;
protected $guarded = [];
protected $dates = ['deleted_at'];
public function tache()
{
return $this->belongsTo(Tache::class);
}
public function techniciens()
{
return $this->belongsToMany('App\technicien','technicien_tarificationtache','tarificationtache_id','technicien_id');
}
public function intervention() {
return $this->hasMany(intervention::class);
}
}
intervention controller
public function create()
{
$client = client::orderBy('id', 'asc')->get();
$metiers = metier::orderBy('id', 'asc')->get();
$technicien = Technicien::orderBy('id', 'desc')->get();
$tarifications = tarificationtache::orderBy('id', 'desc')->get();
return view('intervention.create')->with('technicien',
$technicien)->with('client',$client)->with('metiers',$metiers)-
>with('tarifications',$tarifications);
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(InterventionRequest $request)
{
$intervention = new Intervention();
$intervention ->description =$request->input('description');
$intervention ->duree_prevu =$request->input('duree_prevu');
if($request->has('statut')){
$intervention->statut = $request->input('statut');
}else{
$intervention->statut = 0;
}
$intervention ->technicien_id = $request->input('technicien_id');
$intervention ->client_id = $request->input('client_id');
$intervention ->tarification_id = $request->tarificationtache_id;
$intervention->save();
return redirect('intervention');
}
Check this to know how to create a Modal: Bootstrap Modal W3school
Next put your table inside this div
<div class="modal-body">
//put your table in here
</div>
After populate the table using this Javacript code
$.ajax({
type:'GET',
url:your_url,
dataType: 'json',
success:function(employee_list){
$table_body = $("#tbl_body_name");
$table_body.empty();
if (employee_list.length > 0) {
div_no_data.style.display = 'none';
$.each(employee_list, function (index, value) {
$table_body.append('<tr class="deselected" onclick="rowSelect(this)">' +
'<td style="text-align: left;">' + value.technician_id + '</td>' +
'<td style="text-align: left;">' + value.tache_id + '</td>' +
'</tr>');
});
}
}
});
Next use this function to get selected row information and set it to your desired dropdown
function rowSelect(currentRow){
//this is the code to set a dropdown menu using jquery
var technician_id = selectedRow.children[0].innerHTML;
$("#your_technician_dropdown_menu_id").val(technician_id);
}

Laravel 4 - Model not being saved

Having this code:
class SearchIndex extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'searchindex';
//no timestamps
public $timestamps = false;
//mass-assignment
public $fillable = array('url', 'content', 'version', 'digest');
public $guarded = array();
public static function updateIndex($url, $version, $content)
{
self::retrieveSearchEntry($url, $version)->updateContent($content)->save();
}
public static function retrieveSearchEntry($url, $version)
{
try
{
return self::withoutContent()->where('url', $url)->where('version', $version)->firstOrFail(array('url', 'version', 'digest'));
}
catch(\Illuminate\Database\Eloquent\ModelNotFoundException $e)
{
return new SearchIndex(array('url' => $url, 'version' => $version));
}
}
public function updateContent($content)
{
$hash = md5($content);
if (!isset($this->digest) || ($this->digest != $hash))
{
$this->content = $content;
$this->digest = $hash;
}
return $this;
}
public static function search($content)
{
}
}
If I call updateIndex providing a new combination of url+version, an entry is created.
If I call updateIndex providing an existing pair of url+version, the entry is not updated with the new content. I'm seeing it has something to do with the fact that I'm omitting the 'content' field (reason: is huge, and I want to set it, not get it, in that function).
question: How can I not-get the content field, but be able to set it when saving?
Solved. Reason: I was not selecting the "id" field when doing the custom selection in firstOrFail(). In that way, id was null and the generated SQL tried to update (since it was an existent object) "where id is NULL", which would affect 0 rows.

Resources