Delete on cascade in Model Laravel with eloquent - sql-server

I want to delete data through the api but it is showing an error because it is necessary to delete records in the properties table.
SQLSTATE[23000]: [Microsoft][ODBC Driver 17 for SQL Server][SQL Server] The DELETE statement conflicted with the REFERENCE constraint "FK_Interests_Properties_User". The conflict occurred in database "CADASTRO", table "dbo.Interests_Properties", column 'interests_user_id'. (SQL: delete from [Interests_User] where [user_id] = 1515626)
I created the model that performs actions on the Interests_Properts table, but when I try to delete the data that has the same interests_user_id, errors are occurring.
InterestsUser.php:
use App\Source\InterestsProperties;
class InterestsUser extends Model
{
protected $connection = 'sql_cadastro';
protected $table = 'Interests_User';
protected $primaryKey = 'id';
public $timestamps = false;
public function properties()
{
$this->belongsToMany(InterestsProperties::class, 'foreign_key');
}
public static function lgpdInterestsUser($id_user, $action)
{
if ($action == 'search') {
$data = InterestsUser::where('user_id', $id_user)->get();
if (count($data) > 0) {
return $data;
} else {
return false;
}
} elseif ($action == 'delete') {
$data = InterestsUser::with('properties')->where('user_id', $id_user)->get();
foreach ($data->properties as $p) $p->delete();
if ($data > 0) {
return 'Success Remove.';
} else {
return 'Not Found.';
}
} else {
return "Action Incorrect!";
}
}
}
InterestsProperties.php
class InterestsProperties extends Model
{
protected $table = 'Interests_Properties';
protected $primaryKey = 'id';
public $timestamps = false;
}
The error is occurring when trying to remove with cascade:
Call to undefined method Illuminate\Database\Eloquent\Builder::foreign()
Table Structure
Interests_User
id
interest_id
user_id
created_at
updated_at
Interests_Properties
id
interests_user_id
key
value
created_at
updated_at

At DB level, using onDelete: when migrating your InterestsProperties model you'll have a line like
$table->foreignId('foreign_key')
to that add ->onDelete('cascade')
after that update each time you delete a record from the main table it will do it in this one to.
At PHP level,
$data = InterestsUser::with('properties')->where('user_id', $id_user)->first();
foreach($data->properties as $p) $p->delete();
PD: Those will remove the property record too.

Related

Jessneggers / Laravel MongoDB whereRaw lookup not working

I migrated my database from Sql Server to MongoDB
I want to Join existing customer Table with contact Table .
Customer have multiple contacts . I tried whereRaw lookup
customer collection
{
"_id": 77,
"custid": 93
}
Contact Collection
{"_id":77,"contactid":77,"custid":93,"firstname":"Christy ","lastname":"Lambright" }
{"_id":79,"contactid":79, "custid":93,"firstname":"Marlys ","lastname":"Barry" }
Customer Modal
class custt extends Model
{
use Notifiable;
protected $primaryKey = 'id';
}
Contact Modal
class contact extends Model
{
use Notifiable;
protected $primaryKey = 'id';
In Controller
$cnt = DB::collection("custts")->raw(function($collection)
{
$more_where = [];
$more_where[]['$lookup'] = array(
'from' => 'contacts',
'localField' => 'custid',
'foreignField' => 'custid',
'as' => 'country',
);
return $collection->aggregate($more_where);
});
Error comes --
Empty Results
I tried Lots of options for hasMany and belongstoMany . Not working ...
please suggest
ok , finally found it working
source - https://github.com/jenssegers/laravel-mongodb/issues/841
$cnt = custt::raw(function($collection)
{
return $collection->aggregate(
[[
'$lookup' => [
'as'=>'info',
'from'=>'contacts',
'foreignField'=>'custid',
'localField'=>'custid'
]
]]
);
});

Laravel UUID from SQL Server Database Errors

I am having issues with a Laravel application using an existing database where MS SQL UUIDs are used. My application has a customer:
class Customer extends Model
{
protected $table = 'ERP.Customer';
public $timestamps = false;
protected $primaryKey = 'CustID';
protected $keyType = 'string';
protected $fillable = [
'CustID',
'SysRowID',
'CustNum',
'LegalName',
'ValidPayer',
'TerritoryID',
'Address1',
'Address2',
'Address3',
'City',
'State',
'Zip',
'Country',
'SalesRepCode',
'CurrencyCode',
'TermsCode',
'CreditHold',
'FaxNum',
'PhoneNum',
'CustomerType'
];
public function SalesTer()
{
return $this->belongsTo(SalesTer::class,'TerritoryID', 'TerritoryID');
}
public function Shipments()
{
return $this->hasMany(Shipment::class, 'CustNum', 'CustNum');
}
public function Equipments()
{
return $this->hasMany(Equipment::class,'CustNum', 'CustNum');
}
public function Customer_UD()
{
return $this->hasOne(Customer_UD::class,'ForeignSysRowID', 'SysRowID');
}
}
Which (in the native ERP application) has a UD table which end users can used to customise the Customer entity:
class Customer_UD extends Model
{
protected $table = 'ERP.Customer_UD';
protected $primaryKey = 'ForeignSysRowID';
public $timestamps = false;
public $incrementing = false;
protected $keyType = 'string';
protected $fillable = [
'ForeignSysRowID',
'MakesCans_c',
'MakesEnds_c',
'Industry_c'
];
public function Customer()
{
return $this->hasOne(Customer::class,'SysRowID', 'ForeignSysRowID');
}
}
CustomerController:
public function show($CustID)
{
if(Customer::find($CustID))
{
$Customer = Customer::find($CustID);
$Customer_UD = $Customer->Customer_UD()
->get();
$Shipments = $Customer->Shipments()
->where('Voided', '0')
->get();
$Equipments = $Customer->Equipments()
->with('Part') // load the Part too in a single query
->where('SNStatus', 'SHIPPED')
->get();
return view('Customer.show', ['NoCust' => '0'],
compact('Equipments', 'Customer','Shipments', 'Parts', 'Customer_UD'));
}
else
{
return view('Customer.show', ['NoCust' => '1']);
}
}
The Customer has (for whatever reason) a CustID (which people use to refer to the customer) a CustNum (which is not used outside of the database and a SysRowID. The SysRowID is used to link the Customer table with the Customer_UD table.
An example row from Customer_UD is:
My issue is that when trying to return the UD fields along with the Customer fields I get an error:
SQLSTATE[HY000]: General error: 20018 Incorrect syntax near ''.
[20018] (severity 15) [select * from [ERP].[Customer_UD] where [ERP].
[Customer_UD].[ForeignSysRowID] = '���_�X�O�Q׊3�^w' and [ERP].
[Customer_UD].[ForeignSysRowID] is not null]
I thought it was odd, so I commended out the Customer_UD lines in the CustomerController and simply tried to display the Customer UUID field in the show blade:
SysRowID: {{$Customer->SysRowID}}
I get nothing, no errors but no data. I created a controller and index blade for the Customer_UD model and can display all of the Customer_UD database fields apart from the UUID field.
I don't actually want to display the UUID fields - but do need to use them to build the relationships. Can anyone help point me in the right direction?
I found that adding:
'options' => [
PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER => true,
],
To the database configuration in config\database.php resolved the issue.

CakePHP 2.3.x database transaction

I need your help using transactions in CakePHP.
I have a Product model, with clause hasMany to Price and Property models (key product_id).
In my Product model, I add
function begin() {
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$db->begin($this);
}
function commit() {
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$db->commit($this);
}
function rollback()
{
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$db->rollback($this);
}
And in ProductController I use save() to save my Product, and then my Price and Property. (I use only save(), not saveAll() ).
My code is:
$this->Product->begin();
$error = false;
if($this->Product->save($data)
{
//my functions and calculations
if(!$this->Price->save($data_one)
{
$error = true;
}
//calculations
if(!$this>Property->save($my_data)
{
$error = true;
}
}
if($error) {
$this->Product->rollback();
}
else
{
$this->Product->commit();
}
The problem is that if I have an error inside the save Price or Property row, the Product is still added. I would have thought that when I have any errors, none of my rows would be added (i.e. a rollback would delete it).
I am using CakePHP 2.3.8
Tables must be in InnoDb format. MyISAM format of tables doesn't support transactions.
No need to insert additional code into model.
ProductController:
$datasource = $this->Product->getDataSource();
try {
$datasource->begin();
if(!$this->Product->save($data)
throw new Exception();
if(!$this->Price->save($data_one)
throw new Exception();
if(!$this->Property->save($my_data)
throw new Exception();
$datasource->commit();
} catch(Exception $e) {
$datasource->rollback();
}

A better way for using DB connection [PDO] using an class and further using it in other class?

I'm searching for a better PDO db connection which I could use in the different classes I have. For example my current code is like this:
core.php
//Connecting to Database
try {
$db = new PDO("mysql:host=localhost;dbname=mydb", "project", "project123");
}
catch(PDOException $e) {
echo $e->getMessage();
}
class Core {
protected $db;
public function __construct(PDO $db) {
$this->db = $db;
}
function redirectTo($page,$mode = 'response',$message = '') {
if($message != '') {
header('Location: '.SITEURL.'/'.$page.'?'.$mode.'='.urlencode($message));
} else {
header('Location: '.SITEURL.'/'.$page);
}
exit();
}
}
And apart from this I have 2 more class: wall.php and ticker.php
class Wall {
protected $db;
public function __construct(PDO $db) {
$this->db = $db;
}
function addComment($uid, $fid, $comment) {
$time = time();
$ip = $_SERVER['REMOTE_ADDR'];
$query = $this->db->prepare('INSERT INTO wall_comments (comment, uid_fk, msg_id_fk, ip, created) VALUES (:comment, :uid, :fid, :ip, :time)');
$query->execute(array(':comment' => $comment, ':uid' => $uid, ':fid' => $fid, ':ip' => $ip, ':time' => $time));
$nofity_msg = "User commented on the post";
$setTicker = Ticker::addTicker($uid,$nofity_msg,'comment');
if($setTicker) {
Core::redirectTo('wall/view-'.$fid.'/','error','Oops, You have already posted it!');
} else {
Core::redirectTo('wall/view-'.$fid.'/','error','Oops, Error Occured');
}
}
}
and ticker.php is:
class Ticker {
protected $db;
public function __construct(PDO $db) {
$this->db = $db;
}
function addTicker($uid,$msg,$type) {
$time = time();
$query = $this->db->prepare('INSERT INTO tickers (uid_fk, message, type, created) VALUES (:uid, :message, :type, :time)');
try {
$query->execute(array(':uid' => $uid, ':message' => $msg, ':type' => $type, ':time' => $time));
return $this->db->lastInsertId();
}
catch(PDOException $e) {
return 0;
}
}
}
Now my problem is that I need to call for the function addComment() and inside that function there is a further call for the function addTicker() present in the class Ticker. This is causing a Db connection problem as there is already an db instance created in the previous class or so.. I can't figure out how to sort this out.
This is the code I'm using in the main index file:
$core = new Core($db);
$ticker = new Ticker($db);
$wall = new Wall($db);
$wall->addComment($uid, $fid, $add_comment); // This statement is not working.. :(
My intention is to have a common main DB connection and further use that connection in other classes. Is there any better way to do it..?
there is already an db instance created in the previous class
this is actually single instance, but copied into 2 variables.
This is causing a Db connection problem
Can you please be a bit more certain about such a problem? What particular problem you have?

how to use a soap datasource with mysql

I've created a DataSource for connecting to a WSDL server and post/get data.
But, I don't know how to use it in a controller? with a MySQL database (I mean I need both of them, a soap and a database is needed.)
If I put this in my model, it will use my datasource; but I think it won't use its mysql table...:
public $useTable = false;
public $useDbConfig = 'mydatasource';
How?
You can use $this->Modelname->setDataSource('default') and setDataSource('mydatasource') to switch between the two sources on the fly.
But you also need to change between using a table, and not using a table, i use the following code to switch between a no-table source, and mysql:
public $oldSource = array();
public function setDbConfig($source = null, $useTable = null) {
$ds = $this->getDataSource();
if (method_exists($ds, 'flushMethodCache')) {
$ds->flushMethodCache();
}
if ($source) {
$this->oldSource = array('useTable' => $this->useTable, 'useDbConfig' => $this->useDbConfig);
$this->setDataSource($source);
if ($useTable !== null) {
$this->setSource($useTable);
}
} else {
if ($this->oldSource) {
$this->setDataSource($this->oldSource['useDbConfig']);
$this->setSource($this->oldSource['useTable']);
$this->oldSource = array();
}
}
}

Resources