how can i save a record in 2 different tables.
I have my article model and my article controller in this way. My second table is called History
I hope you can help me, thank you very much
my article model:
protected $fillable =[
'idcategoria','codigo','nombre','precio_proveedor','precio_venta','iva','ieps','stock','stock1','descripcion','condicion'
];
public function categoria(){
return $this->belongsTo('App\Categoria');
}
my article controller, store method:
protected static function boot()
{
parent::boot();
// this triggers everytime an Article model is saved
static::saved(dd($articulo) { dd($article);
$historial = new Historial();
$historial->nombre = $articulo->nombre;
$historial->precio_proveedor = $articulo->precio_proveedor;
$historial->stock = $articulo->stock;
$historial->save();
});
}
In my history table I only need to save nombre, precio_proveedor,
stock
You can use observers for this. Add this in your Article model:
protected static function boot()
{
parent::boot();
// this triggers everytime an Article model is saved
static::saved(function (Article $article) {
$history = new History();
$history->nombre = $article->nombre;
$history->precio_proveedor = $article->precio_proveedor;
$history->stock = $article->stock;
$history->save();
});
}
Reference: https://www.larashout.com/how-to-use-laravel-model-observers
Related
As I mentioned in Question, the current Laravel 6.0 project I am working on has bit weird DB setup, where the Model's(the MainModel here) MySQL table has been set with AutoIncrement as NULL. And client won't allow to change the Table's definition at all.
I want to reliably find the next and previous IDs of the Model(since I can't find from table as AutoIncrement is set to NULL) before inserting record, so that I can make an entry of relevant record(for eg. image(s) of a testimonial/faq or any WYSIWYG content field) into another referential table first, by correctly inserting the main Model's ID into the refrential ID field of that another table.
Currently I have this in my main Model, but the next method doesn't reliably return the exact incremented ID consistently:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Te7aHoudini\LaravelTrix\Traits\HasTrixRichText;
class [MainModel] extends Model
{
use HasTrixRichText;
protected $guarded = [];
public $timestamps = false;
protected $primaryKey = 'id';
protected $connection = '[connection1]';
protected $table = '[main_table]';
protected $fillable = ['id', '[titlefield]', '[wysiwyg_field]'];
/**
* Setup model event hooks
*/
public static function boot()
{
parent::boot();
self::creating(function ($model) {
$model->id = $model->max('id') + 1;
});
}
/**
* Get next available Faq Id
*/
public function next()
{
return ++$this->id;
}
}
Any help is appreciated...
As I understand you are confused about how to call statically model queries. You can achieve the same logic by using a static self-reference static.
public static function next()
{
return static::max('id') + 1;
}
This would be equivalent to.
MainModel::max('id');
Bonus to make it a transaction to avoid id clashing. This can lock the database in fun ways, but will avoid you have the same ids, something similar to this, very simple example.
DB::transaction(function () {
$id= MainModel::next();
$newModel = MainModel::create(['id' => $id]);
});
As I understanding, in order to get the next increment id, you need to call the following line.
Model::lastest()->first()
Morning everyone,
I have foreign keys set to on delete cascade in laravel 5 and mysql on a couple of tables where the existence of a employee depends on the existence of the country he was born in.
$table->foreign('id_estado_municipio')
->references('id_estado_municipio')
->on('cat_municipios')
->onDelete('cascade')
->onUpdate('cascade');
Problem is when I delete the country, the employee that must get erased along with it, gets erased from the database, but the employee's record keeps on showing at the index view.
Have tried setting engine to InnoDB in the config file, model observers to delete dependents but still can't figure out how to make it work.
Hopefully someone can give some light. It would be very much appreciate it.
Here you are my models and modelcontrollers
class Municipio extends Model
{
//
protected $table = 'cat_municipios';
protected $primaryKey = 'id_estado_municipio';
...
public function trabajadores()
{
return $this->hasMany(Trabajador::class,'id_trabajador');
}
protected static function boot() {
parent::boot();
static::deleting(function($municipio) {
// delete related stuff ;)
$municipio -> trabajadores() -> delete();
});
}
class MunicipioController extends Controller
{
...
public function destroy($id)
{
//
$municipio = Municipio::findOrFail($id);
$municipio -> trabajadores() -> delete();
$destruido = Municipio::destroy($id);
if($destruido)
return redirect()->route('Municipio.index')->with('info','Municipio eliminado con éxito.');
else
return redirect()->route('Municipio.index')->with('error','Imposible borrar Municipio.');
}
}
////////////////////////////////////////
class Trabajador extends Model
{
//
protected $table = 'trabajadors';
protected $primaryKey = 'id_trabajador';
...
public function municipio()
{
return $this->belongsTo(Municipio::class,'id_estado_municipio');
}
...
}
class TrabajadorController extends Controller
{
public function index()
{
//
$criterio = \Request::get('search'); //<-- we use global request to get the param of URI
$estadosciviles = EstadoCivil::orderBy('id_estado_civil')->paginate(50);
$estados = Estado::orderBy('id_estado') -> paginate(50);
$municipios = Municipio::orderBy('id_estado_municipio')->paginate();
$religiones = Religion::orderBy('id_religion')->paginate();
$trabajadores = Trabajador::where('nombre', 'like', '%'.$criterio.'%')
->orwhere('id_trabajador',$criterio)
->orwhere('a_paterno',$criterio)
->orwhere('a_materno',$criterio)
->orwhere('curp',$criterio)
->orwhere('rfc',$criterio)
->orwhere('seguro_social',$criterio)
->sortable()
->orderBy('id_trabajador')
->orderBy('nombre')
->paginate();
return view('Trabajador.index', array('trabajadores' => $trabajadores,'estadosciviles' => $estadosciviles,'estados' => $estados,'municipios' => $municipios,'religiones' => $religiones));
}
...
}
So i've got two models, Client and Project, and Client has a hasMany relationship with projects. I'm just trying to add the project count for the client into the JSON response but I can't get it to work.
My controller just returns all the projects;
public function index(Client $client)
{
return $client->all();
}
And my model contains the below;
protected $appends = ['client_projects_count'];
/**
* Create a relationship between this client and it's projects
*/
public function clientProjects() {
return $this->hasMany('App\Project');
}
public function getClientProjectsCountAttribute()
{
return $this->withCount('clientProjects');
}
This just adds client_projects_count to the response but it's an empty array. I'm close, if I dd($this->withCount('clientProjects')->get()) I can see the client_projects_count with the correct count, but if I remove the dd and keep the ->get() then I get an internal server error.
Also, it is possible to only load this for the index() method rather than every one?
From the Documentation
$clients = Client::withCount('projects')->get();
foreach ($clients as $client) {
echo $client->projects_count;
}
So I managed to resolve it myself, although I'm sure their must be a nicer way.
Client.php
protected $appends = ['client_projects_count'];
/**
* Create a relationship between this client and it's projects
*/
public function clientProjects() {
return $this->hasMany('App\Project');
}
public function clientProjectsCount()
{
return $this->clientProjects()->selectRaw('client_id, count(*) as aggregate')->groupBy('client_id')->get();
}
public function getClientProjectsCountAttribute()
{
return isset($this->clientProjectsCount()[0]) ? $this->clientProjectsCount()[0]->aggregate : 0;
}
http://www.yiiframework.com/doc-2.0/guide-security-authorization.html#role-based-access-control-rbac
In the documentation, it says that you can assign the role to the user in the advanced template by using this code:
public function signup()
{
if ($this->validate()) {
$user = new User();
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
$user->save(false);
// the following three lines were added:
$auth = Yii::$app->authManager;
$authorRole = $auth->getRole('author');
$auth->assign($authorRole, $user->getId());
return $user;
}
return null;
}
The problem is that I am using the basic template. Is there a way of doing this inside the basic template?
I thought about using the afterSave method; however, I am not sure how to do this.
public function afterSave($insert)
{
}
Any idea on how it can be done?
public function afterSave($insert)
{
$auth = Yii::$app->authManager;
$authorRole = $auth->getRole('author');
$auth->assign($authorRole, $this->Id());
}
I am thinking this could work, but I am not totally sure.
It does not depend on used template.
Your example is correct, except few things.
$this->Id() should be replaced with $this->id (assuming primary key of users table is named id).
Note that you need also call parent implementation of afterSave() method and you missed $changedAttributes parameter:
/**
* #inheritdoc
*/
public function afterSave($insert, $changedAttributes)
{
$auth = Yii::$app->authManager;
$authorRole = $auth->getRole('author');
$auth->assign($authorRole, $this->id);
parent::afterSave($insert, $changedAttributes);
}
For further improvements, you can wrap saving in transaction, so if something is failed in afterSave(), model is not saved (afterSave() event handler is executed after model is saved in database).
Also you can move assigning role logic to separate method.
Note that with this logic every registered user will have that role. You can wrap it with some condition, however it's better to assign role through admin interface.
You can see how it's implemented for example in this extension. For example you can create separate form, action and extend GridView ActionColumn with additional icon for assigning role.
I need to use multiple table in a single form, on form submitted the data will save in multiple tables in the data base, also wants to perform validation and update.
I suggested snippet of code, at beginning of controller class define
private $_rel = null;
controller action ,
public function actionSaveUser(){
if (!empty($_POST['Contact'])){
$model = new Contact;
$model->attributes = $_POST['Contact'];
if ($model->save()){
$this->_rel = new Address;
$this->_rel->attributes = $_POST['Contact'];
if ($this->_rel->save()){
$this->render('view_name');
} else{
throw new CHttpException(404, 'Something went wrong message..');
}
}
}
}
I hope this code help you.