Laravel - artisan - cannot insert with null column - php

I have this table structure which I created partly with laravel builder:
public function up() {
DB::statement('
CREATE TABLE `tbl_permission` (
`permission_id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
`id_module` smallint(5) unsigned NOT NULL,
`name` varchar(50) NOT NULL,
`create` TINYINT NOT NULL DEFAULT 0,
`view` TINYINT NOT NULL DEFAULT 0,
`is_composition` tinyint(1) NOT NULL DEFAULT "0",
`suffix_czech_name` VARCHAR(100),
`permission_table` VARCHAR(50),
FOREIGN KEY (`id_module`) REFERENCES `tbl_modules` (`id_module`)
) COLLATE utf8_czech_ci;
');
}
then I have another migration with insert:
public function up() {
DB::table('tbl_permission')->insert([
['name' => 'account_bad_rooms', 'id_module' => 1, 'create' => 0, 'view' => 1, 'is_composition' => 0, 'suffix_czech_name' => 'name'],
['name' => 'account', 'id_module' => 1, 'create' => 1, 'view' => 1, 'is_composition' => 0, 'suffix_czech_name' => 'name'],
['name' => 'accountRoomIdConfig', 'id_module' => 1, 'create' => 1, 'view' => 1, 'is_composition' => 0, 'suffix_czech_name' => 'name', 'permission_table' => 'accountRoomIdConfig']
]);
}
When I use migration then everything works without any error except I don't have any inserted data. I figured out that is because in two inserts I don't have column permission_table which can be null. When I add this column, then all inserts have same structure, migration is fine. Problem is that I have more than 70 inserts and some have column permission_table and some does not have it. Is somehow possible to insert all data without same structure?

If you do an insert without setting permission_table value you will get a sql error value list does not match column list.
Even if default value is null. you still have to pass the column in all rows with a value of '' even if it does not have a value.
public function up() {
DB::table('tbl_permission')->insert([
[
'name' => 'account_bad_rooms',
'id_module' => 1,
'create' => 0,
'view' => 1,
'is_composition' => 0,
'suffix_czech_name' => 'name'
'permission_table' => ''
],
[
.... next record
]
]);
}
Hope this help.

Related

array filter of PDO result

I get PDO rows array which contains the result:
parent_id , item_id
NULL 2
NULL 3
1 5
1 8
I want a new array where parent_id is not NULl
Means
new arr=[5,8]
You need to set new array from exits or to duplicate request with IS NULL condition. With array method, your code will show like this:
$arr = [
[
'parent_id' => null,
'item_id' => 2,
],
[
'parent_id' => null,
'item_id' => 4
],
[
'parent_id' => 2,
'item_id' => 20,
],
];
$new_arr = array_filter($arr,function ($item) {
return !$item['parent_id'];
});
print_r($new_arr);

Do not change mysql column value if request variable is null in laravel eloquent

I need to check if $request->link_description is null then don't change anything or better to say don't touch the database column value.
is it possible to do so without doing an extra select query?
for example :
/** update ad Seat info */
$Update_Seat = AdSeat::where('id', $id)->where('owner_id', $owner_id)
->update(['seat_name' => $seat_name,
'seat_url' => $seat_url,
'logo_src' => ($logo_src) ? $logo_src : null,
'category_id' => $category_id,
'plan' => $plan,
'price_sale' => $price_sale,
'link_description' => ($link_description) ? $link_description : null,
'description' => ($description) ? $description : null,
'income_percentage' => $income_percentage,
'status' => STATUS_TO_APPROVE]);
I mean this part :
'link_description' => ($link_description) ? $link_description : null,
instead of null I want to put something like :
'link_description' => ($link_description) ? $link_description : AdSeat::whereId(5)->value('link_description),
But as I said before I'm looking for a way to not to run extra select query like above.
It would be easier to build your data array before hand. Example:
// Do not add $link_description here
$data = [
'seat_url' => $seat_url,
...
];
// But add it if $link_description is not null
if (!is_null($link_description)) {
$data['link_description'] = $link_description;
}
$Update_Seat = AdSeat::...->update($data);

SQL to ActiveRecord criteria

I am trying to reproduce the following SQL in an ActiveRecord Criteria:
SELECT COALESCE(price, standardprice) AS price
FROM table1
LEFT JOIN table2
ON (pkTable1= fkTable1)
WHERE pkTable1= 1
So far I have the following:
$price = Table1::model()->find(array(
"select" => "COALESCE(price, standardprice) AS price",
'with' => array(
'table2' => array(
'joinType' => 'LEFT JOIN',
'on' => 'pkTable1= fkTable1',
)
),
'condition' => 'pkTable1=:item_id',
'params' => array(':item_id' => 1)
));
But this results into the following error: 'Active record "Table1" is trying to select an invalid column "COALESCE(price". Note, the column must exist in the table or be an expression with alias.
The column should exist though, here are the 2 table structures:
Table1
pkTable1 int(11) - Primary key
standardprice decimal(11,2)
name varchar(255) //not important here
category varchar(255) //not important here
Table2
pkTable2 int(11) - Primary key //not important here
fkType int(11) - Foreign key //not important here
fkTable1 int(11) - Foreign key, linking to Table1
price decimal(11,2)
What exactly am I doing wrong?
You will need to use a CDbExpression for the COALESCE() expression:
$price=Table1::model()->find(array(
'select'=>array(
new CDbExpression('COALESCE(price, standardprice) AS price'),
),
'with' => array(
'table2' => array(
'joinType'=>'LEFT JOIN',
'on'=>'pkTable1=fkTable1',
),
),
'condition'=>'pkTable1=:item_id',
'params'=>array(':item_id'=>1)
));
I further believe if table2 has been linked in the relations() method in your Table1 model, the following line should be sufficient:
'with'=>array('table2'),
I've managed to solve the issue as following: Wrap the COALESCE expression in an array, and change the alias to an existing columnname in the table.
$price = Table1::model()->find(array(
"select" => array("COALESCE(price, standardprice) AS standardprice"),
'with' => array(
'table2' => array(
'joinType' => 'LEFT JOIN',
'on' => 'pkTable1= fkTable1',
)
),
'condition' => 'pkTable1=:item_id',
'params' => array(':item_id' => 1)
));
Thank you to Willemn Renzema for helping me with the array part. I'm still not entirely sure why the alias needs to be an existing column name (in this case the error was that price doesn't exist in Table1).

drupal schema type int length 3 but get int(10)

want to have a int(3) field.
In drupal schema, define as:
'response_code' => array(
'description' => 'The API response code',
'type' => 'int',
'length' => 3,
'unsigned' => TRUE,
'not null' => FALSE,
),
But it creates int(10) field in mysql database.
CREATE TABLE `log` (
`response_code` int(10) unsigned DEFAULT NULL,
)
length is for (var)chars, it is ignored for other types. You can use size to change the size of the int.
See https://api.drupal.org/api/drupal/includes%21database.inc/group/schemaapi/6 for more details.
Note: The number in int(3) specifies the size in bits, so you will be able to have a maximum of 2^2 -1 saved in there (int is signed in database). You'd need at least 11 bits to save http status codes.

Cakephp 2.0: complex find query

I'm trying to pull some info out of two tables linked by the hasMany and belongsTo associations.
requisitions hasMany locations and locations belongsTo requisitions
TABLE `requisitions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`fecha_generacion` date NOT NULL,
`solicitado_a` varchar(60) NOT NULL,
`proyecto` varchar(150) NOT NULL,
`obra_no` varchar(11) NOT NULL,
`observaciones` text NOT NULL,
PRIMARY KEY (`id`)
)
and
TABLE `locations` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`requisition_id` int(11) NOT NULL,
`fecha` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`name` enum('pendiente','tecnico','existencia','cotizando','generar_o','archivada')
NOT NULL DEFAULT 'pendiente',
`image_path` varchar(150) NOT NULL DEFAULT 'estado0.png',
`note` text NOT NULL,
PRIMARY KEY (`id`)
)
Requisition goes from one Location to another and I need to keep track of its current Location looking by a given Location as 'pendiente','tecnico'...
So I need to generate a list with the last Location for each Requisition and then filter that list by the Location.name
I believe the only way to do this is with a query around another query, so I'm trying to understand cakephp syntax with more simple queries first.
I was trying to search for the last 'pendiente' Location with the next code from my RequisitionsController.
$lastPendiente = $this->Requisition->Location->find('all', array(
'conditions' => array('Location.name' => 'pendiente'),
'fields' => array('MAX(Location.id) AS olderLocation', 'Location.requisition_id'),
'group' => 'Requisition.id',
));
I have the query
SELECT MAX(`Location`.`id`) AS olderLocation, `Location`.`requisition_id` FROM `petrofil_demo`.`locations` AS `Location` LEFT JOIN `petrofil_demo`.`requisitions` AS `Requisition` ON (`Location`.`requisition_id` = `Requisition`.`id`) WHERE `Location`.`name` = 'pendiente' GROUP BY `Requisition`.`id`
output...
array(
(int) 0 => array(
(int) 0 => array(
'olderLocation' => '22'
),
'Location' => array(
'requisition_id' => '29'
)
),
(int) 1 => array(
(int) 0 => array(
'olderLocation' => '5'
),
'Location' => array(
'requisition_id' => '30'
)
),
(int) 2 => array(
(int) 0 => array(
'olderLocation' => '13'
),
'Location' => array(
'requisition_id' => '31'
)
)
)
...which is great because those are exactly the last requisitions with a 'pendiente' location but here comes the second query or the condition where I'm clueless. I need to be sure my requisition last state was 'pendiente' and not another possible locations. For example my requisition_id =>30 last location is really 'tecnico' so I need to find a way to exclude it from showing on my results.
You could quit the condition from the query, put the 'name' column in the 'fields' and add an order by sentence:
$lastPendiente = $this->Requisition->Location->find('all', array(
'fields' => array('MAX(Location.id) AS olderLocation', 'Location.requisition_id', 'name'),
'group' => 'Requisition.id',
'order' => 'fecha DESC'
));
This way you only get the last status from the Location table. Then, you could iterate the results, filtering by the 'name' column and deleting those whit a 'name' diferent from 'pendiente':
foreach($lastPendiente as $k => $location){
if($location['Location']['name'] != 'pendiente'){
unset($lastPendiente[$k]);
}

Categories