Cascade updates on tables and pivot tables with laravel and Eloquent - eloquent

I created a model nammed sector. For this model i created methods to make links between the database table :
A sector has many valuechain with many segments, which have many
keyneeds
A valuechain has many segments
A segment has many keyneeds ...
It has been translated this way :
public function valuechains()
{
return $this->hasMany('App\Valuechain');
}
public function segments()
{
return $this->hasManyThrough('App\Segment', 'App\Valuechain');
}
public function keyneeds()
{
return $this->hasManyThrough('App\Keyneed', 'App\Segment', 'App\Valuechain');
}
When i soft delete a sector I want to create a cascade on other tables and make updates.
My destroy method is :
public function destroy($id)
{
$sector = Sector::findOrFail($id);
// on update lang_sector pour chaque id
$sector_ids = $sector->langs()->allRelatedIds();
foreach ($sector_ids as $id){
$sector->langs()->updateExistingPivot($id, ['lang_sector.deleted_at' => Carbon::now()]);
}
$sector->valuechains()->update(
[
'valuechains.deleted_at' => Carbon::now(),
'valuechains.updated_at' => Carbon::now(),
]
);
$sector->segments()->update(
[
'segments.deleted_at' => Carbon::now(),
'segments.updated_at' => Carbon::now(),
]
);
$sector->keyneeds()->update(
[
'keyneeds.deleted_at' => Carbon::now(),
'keyneeds.updated_at' => Carbon::now()
]
);
Sector::where('id', $id)->delete();
return redirect()->route('sectors.index')->with('success', 'Sector deleted');
}
I have pivot table for valuechains, segments and keyneeds and i also want to update the updated_at and deleted_at columns on those tables...
For those 3 tables i added to the model the lang method for defining the pivot relation and defining the fields i have inside the pivot table:
public function langs() {
return $this->belongsToMany('App\Lang')
->withPivot(
'vcname',
'vcshortname',
'vcdescription',
'vcshortdescription',
'created_at',
'updated_at',
'deleted_at'
);
}
I have an error message :
SQLSTATE[23000]: Integrity constraint violation: 1052 Champ: 'updated_at' dans field list est ambigu (SQL: update segments inner join valuechains on valuechains.id = segments.valuechain_id set valuechains.deleted_at = 2018-05-09 07:34:30, valuechains.updated_at = 2018-05-09 07:34:30, segments.deleted_at = 2018-05-09 07:34:30, segments.updated_at = 2018-05-09 07:34:30, **updated_at** = 2018-05-09 07:34:30 where valuechains.sector_id = 2)

Related

How do I edit a cart order by adding more items and updating existing data in mysql with codeigniter..?

This code gets the existing cart content, add more items and try to update the data or insert new data
if ($cart = $this->cart->contents()) {
foreach ($cart as $key => $value) {
$order_details = array(
'oid' => $id,
'p_id' => $value['id'],
'qty' => $value['qty'],
'price' => $value['price'],
'total_amnt' => $value['qty'] * $value['price'],
'created_at' => date('Y-m-d h:i:s')
);
$q = $this->db->where('oid',$id)->get('order_details')->num_rows(); // oid is a foreign Key inside order_details table
if ( $q > 0 ){
$this->db->where('oid',$id); // oid is a foreign Key inside order_details table
$this->db->update('order_details',$order_details);
} else {
$this->db->set('oid', $id); // oid is a foreign Key inside order_details table
$this->db->insert('order_details',$order_details);
}
}
}
I simple load the existing data into cart and clear update the data in the database when saving. Another method was to delete the existing data and save the new one as current data..

Doctrine Entity values are all null except for id

I'm trying to fetch an Object from the database with the repository method findOneBy (id).
Basically, the line looks like this:
public function findAssignedTickets(User $user)
{
$userId = $user->getId();
$ticketMapping = new ResultSetMapping;
$ticketMapping->addEntityResult(Ticket::class, 't');
$ticketMapping->addFieldResult('t', 'id', 'id');
// Postgresql Native query, select all tickets where participants array includes the userId
$query = "SELECT *
FROM (
SELECT id, array_agg(e::text::int) arr
FROM ticket, json_array_elements(participants) e
GROUP BY 1
) s
WHERE
$userId = ANY(arr);
";
$results = $this->getEntityManager()->createNativeQuery($query, $ticketMapping)->getResult();
$results = array_map(function($item) {
return $item->getId();
}, $results); // Transform to array in integers
dump($results); // array:2 [0 => 83, 1 => 84] -> It's correct
$tickets = [];
foreach ($results as $ticketId) {
dump($this->findOneById($ticketId));
// $ticket = $this->findOneById($ticketId);
// $tickets[] = [
// 'identifier' => $ticket->getIdentifier(),
// 'title' => $ticket->getTitle(),
// 'author' => $ticket->getAuthor()->getUsername(),
// 'status' => $ticket->getStatus(),
// 'created' => $ticket->getCreatedAt()->format('c'),
// 'updated' => $ticket->getUpdatedAt()->format('c'),
// ]; // Ticket formatting to send in json
}
return $tickets;
}
which will output :
And I'm sure that the received id matches a row in the database, and that the database contains data, and all fields belong directly to the entity, except for author which represents a ManyToOne and I heard about the lazy displaying of Doctrine, but it shouldn't happen on other fields.
Why can't I retrieve data from the Object even with getters, and why are all the values set to null Except for id ?
EDIT : I was wondering if that had a connexion to the ResultSetMapping I used to fetch the tickets IDs in a totally separate request earlier, and when I added a addFieldResult('t', 'title', 'title'); it did the work, but not on the other fields, another mystery.

Laravel 5.3 belongsTo relation on same table shows no result

I'd like to make a relationship on the same table but I'm not sure it's possible...
I have a table jobs with the fields id, name and parent_id. I want to get some jobs and their parent (and their own parent if they have one, etc.).
Here's my model :
class Job extends Model
{
public function jobParent()
{
return $this->belongsTo('App\Job', 'parent_id');
}
}
In my controller I do that :
$select = Job::take(10)
->with('jobParent')
->get();
I displayed the queries and I can see the one for the relationship :
select * from jobs where id in (?, ?, ?)
I have 3 parents for my 10 jobs so it seems right but it returns parent: null for each of my jobs...
Do you see what I'm missing ?
I added this to my request because I want also the parent of the parent :
->with(['jobParent' => function($query) {
$query->with('jobParent');
}]);
I can see the two queries so it does works, it just doesn't display !
select * from jobs where id in (?, ?, ?)
select * from jobs where id in (?, ?)
I output my results this way :
$return = [
'success' => 1,
'totalCount' => $totalCount,
'nextOffset' => $offset+$nb,
'jobs' => $jobs
];
$code = 200;
return response()->json($return, $code);
Wich gives me this :
{
"success": 1,
"totalCount": 10706,
"nextOffset": 10,
"jobs": [
{
"name": "xxx",
"parent_id": 15,
"job_parent": null
}, ...
I tried to do a foreach of my jobs and a var_dump($job->jobParent) but it says NULL as well...
I just don't get why it doesn't store the results...
I figured it out : job.id is a string, I casted it in my model and it works fine :
protected $casts = ['id' => 'string'];

missing FROM-clause entry for table "Grupo" cakephp

hi i have aproblem in my code, I want generate a list of user but this have a group and need just a group of user.
the error say:
Error: SQLSTATE[42P01]: Undefined table: 7 ERROR: missing FROM-clause entry for table "Grupo"
this is my code:
public function add()
{
$this->loadModel('SoyaProveedor');
$this->loadModel('Soya');
$this->set('oleaginosas', $this->Soya->find('list', array(
'fields'=> array('id','username'),
'conditions' => array('Grupo.categoria' => 'Soya' , 'Grupo.subcategoria' => 'Productor de Oleaginosas')
)));
if ($this->request->is('post')) {
$this->request->data['SoyaProveedor']['nombre'] = strtoupper($this->request->data['SoyaProveedor']['nombre']);
$this->request->data['SoyaProveedor']['codigo'] = strtoupper($this->request->data['SoyaProveedor']['codigo']);
if ($this->SoyaProveedor->save($this->request->data)) {
$this->Session->setFlash(__('La InformaciĆ³n fue Guardada.'));
return $this->redirect(array('action' => 'index'));
}
}
}
the sql query of the cake generate it:
SQL Query: SELECT "Soya"."id" AS "Soya__id", "Soya"."username" AS
"Soya__username" FROM "public"."users" AS "Soya" WHERE
"Grupo"."categoria" = 'Soya' AND "Grupo"."subcategoria" = 'Productor
de Oleaginosas'
You need the grupos table to be joined in the query, your query in the question has no joins. There are a number of simple solutions.
Define recursive.
Recursive is a very coarse control of what joins and queries are executed, by default find('list') has a recursive value of -1.
-1 means no joins, which is why there is no join in the resultant query. Setting it to a value of 0 adds a join to the main query for all hasOne and belongsTo associations.
Be wary of using/relying on recursive as it's very easy to generate queries with joins you don't need - and/or triggering many subsequent queries for related data (if set to a value larger than 0).
However this find call:
$data = $this->Soya->find('list', array(
'fields'=> array('Soya.id','Soya.username'),
'recursive' => 0, // added
'conditions' => array(
'Grupo.categoria' => 'Soya' ,
'Grupo.subcategoria' => 'Productor de Oleaginosas'
)
));
Should result in this query (If the Soya model has a belongsTo association to Grupo):
SELECT
"Soya"."id" AS "Soya__id",
"Soya"."username" AS "Soya__username"
FROM
"public"."users" as "Soya"
LEFT JOIN
"public"."Grupos" as "Grupo" on ("Soya"."grupo_id" = "Grupo"."id")
...
Possibly more joins
...
WHERE
"Grupo"."categoria" = 'Soya'
AND
"Grupo"."subcategoria" = 'Productor de Oleaginosas'
Or Use containable
The containable behavior allows better control of what queries are executed. Given the info in the question to use it that means:
<?php
class Soya extends AppModel {
// Assumed from information in the question
public $useTable = 'users';
public $belongsTo = array('Grupo');
// added
public $actsAs = array('Containable');
}
Will permit you to do the following in your controller:
$data = $this->Soya->find('list', array(
'fields'=> array('Soya.id','Soya.username'),
'contain' => array('Grupo'), // added
'conditions' => array(
'Grupo.categoria' => 'Soya' ,
'Grupo.subcategoria' => 'Productor de Oleaginosas'
)
));
Which will generate the following query (exactly one join):
SELECT
"Soya"."id" AS "Soya__id",
"Soya"."username" AS "Soya__username"
FROM
"public"."users" as "Soya"
LEFT JOIN
"public"."Grupos" as "Grupo" on ("Soya"."grupo_id" = "Grupo"."id")
WHERE
"Grupo"."categoria" = 'Soya'
AND
"Grupo"."subcategoria" = 'Productor de Oleaginosas'
Link your models together using associations: CakePHP Associations
Alternatively you can use custom sql-statemens using join e.g.:
$db = $this->getDataSource();
$result = $db->fetchAll(
"SELECT Soya.id AS Soya__id, Soya.username AS Soya__username FROM public.users AS Soya
join Grupo on Grupo.id = Soya.groupo_id
WHERE Grupo.categoria = ? AND Grupo.subcategoria = ?",
array('Soya', 'Productor de Oleaginosas')
);
$this->set('oleaginosas', $result);

CakePHP 2.2 with PostgreSQL Failed new row insert - Database Error: Undefined table: 7 ERROR: relation "table_id_seq" does not exist

My problem is as follows.
After deleting multiple rows from table, inserting new record into same table results in error.
Database Error
Error: SQLSTATE[42P01]:
Undefined table: 7 ERROR: relation "order_details_id_seq" does not exist
Table
CREATE TABLE schema.order_details (
id serial NOT NULL,
order_id integer NOT NULL,
field_1 integer,
field_2 real,
field_3 character varying(15),
CONSTRAINT order_details_pkey PRIMARY KEY (id )
)
WITH (
OIDS=FALSE
);
Insert is
INSERT INTO "schema"."order_details" ("order_id", "field_1", "field_2", "field_3")
VALUES (37, 1, 2, 'value');
Sequence "schema"."order_details_id_seq" in used schema exists.
CREATE SEQUENCE schema.order_details_id_seq
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 37
CACHE 1;
Models.
// Model
class Order extends AppModel {
public $useDbConfig = 'other_data';
public $hasMany = array(
'OrderDetail' => array(
'className' => 'OrderDetail',
'foreignKey' => 'order_id',
'dependent' => true,
'order' => array(
'OrderDetail.order_id',
'OrderDetail.field_1'
))
);
class OrderDetail extends AppModel {
public $useDbConfig = 'other_data';
public $belongsTo = array(
'Order' => array(
'className' => 'Order',
'foreignKey' => 'order_id',
'dependent' => true
),
// model Order save code on recreation of order
$this->OrderDetail->deleteAll(array('OrderDetail.order_id' => $this->id));
At this point tried to insert $this->OrderDetail->query('VACUUM FULL ANALYZE order_details'); with no effect
foreach ($details as $d) {
$this->OrderDetail->create();
$this->OrderDetail->save($d /*array(
'order_id' => $this->id,
'field_1' => 1,
'field_2' => 2,
'field_3' => 'value'
)*/);
}
I get error on first foreach loop.
Weirdest thing is that problem appears and disappears after some time randomly.
Any suggestions on what it could be and how to get rid of it?
Currently solved problem using code.
$this->Order->id = $id;
$this->Order->delete();
It fires 2 queries for each row (100 extra in my case!) of delete statements instead of two in case of
$this->OrderDetail->deleteAll(array('OrderDetail.order_id' => $id));
So for this time it has space for improvement.
EDIT: Currently code works as it should with tweaked DboSource.
It seems that cake was looking in public schema for sequence where it is not located.
Fixed it by tweaking to include schema name in last insert getter inf file Model/Datasource/DboSource.php create method with this diff
## -1006,7 +1006,7 ##
if ($this->execute($this->renderStatement('create', $query))) {
if (empty($id)) {
- $id = $this->lastInsertId($this->fullTableName($model, false, false), $model->primaryKey);
+ $id = $this->lastInsertId($this->fullTableName($model, false, true), $model->primaryKey);
}
$model->setInsertID($id);
$model->id = $id;
I know that modifying core is not the way to go, but as long as it is working it is fine with me.
This happened to me because I modified the name of the table, but PostgreSQL did not change the name of the sequences. Knowing this, I changed the name of the sequences that affected this table and it was resolved.
To prevent this error, use this convention to name your sequence when using cakephp: table_name_id_seq. For example:
table name: user
sequence name should be: user_id_seq
If you alredy have sequences, you can rename it in posgres like this
alter sequence user_seq rename to user_id_seq
I'm not a fun of this way to name sequence but it prenvent this kind of errors in my case