I have two tables: (Table A & TableB).
Table A = id(primary), name, email
Table B = user_id(foreign(id)), column1, column2
What I need to do is:
Insert a row in Table A.
Verify the insertion.
Insert row in Table B & store Table A (id) in Table B (user_id).
Currently, I'm handling it like the following.
// Create a row in Table A
$createUser = UserModel::create($userData);
// Verifying insertion of the by checking if id is set
if (isset($createUser['id'])) {
$adminData = [
'name' => $info['adminName'],
'user_id' => $createUser['id'], // insert into user_id
'email_address' => $info['adminEmail'],
'contact_number' => $info['adminNumber'],
];
$createAdmin = AdminsModel::create($adminData);
}
I'm looking for a better way for multiple chained tables to avoid an if-else ladder.
There is nothing wrong with what you are doing. But you can also use eloquent relationships.
First define this method in the UserModel.
/**
* Get the admin associated with the user.
*/
public function admin()
{
return $this->hasOne(AdminsModel::class);
}
And use it like so
$createUser = UserModel::create($userData);
$createUser->admin->create([
'name' => $info['adminName'],
'email_address' => $info['adminEmail'],
'contact_number' => $info['adminNumber'],
]);
Related
Table One:
ar_codes
----------
ar_id (primary key),
act_id,
ar_code,
status
Table Two:
act_req_recv
----------
rcv_id (primary key),
act_id,
rcv_person,
status
Now I need to find the ar_codefield value from ar_codes table for the rcv_person field of act_req_recv table. Both of the table has one common field which is act_id and is not a primary key for both of the table.
Now I can find it by normal mysql scriptlike bellow command, where $actId is carrying the value. How can I find this value in Yii?
SELECT ar_code FROM ar_codes WHERE act_id=$actId
I tried to find that with a function call from model. But as the field is not PK so the result is not coming.
public static function getAR_code($actId) {
$ActCode = Yii::app()->db->createCommand()
->select('ar_code')
->from('{{ar_codes}}')
->where('act_id=' . (int) $actId)
->queryAll();
return $ActCode;
}
Getting this error when the function run:
[error] [php] Array to string conversion
(D:\Xampp\htdocs\framework\yii1.1.19\zii\widgets\CDetailView.php:240)
The cDetail View Code is:
array(
'name' => 'actId',
'type'=> 'raw',
'value' => ActivityRecord::getAR_code($model->actId),
'htmlOptions' => array('style' => "text-align:left;"),
),
queryAll() returns array of rows, so it is actually array of arrays. Something like:
[
['ar_code' => 123],
]
If you want to query single value (for example 123), you should use queryScalar() - it will return value from first column of first row:
public static function getAR_code($actId) {
return Yii::app()->db->createCommand()
->select('ar_code')
->from('{{ar_codes}}')
->where('act_id=' . (int) $actId)
->queryScalar();
}
I have two related tables. For example,
tbl_one
id
name
tbl_second
id
id_tblone(this is fk)
name
For example:
tbl_one
id: 1
name: input one
tbl_second
id: 1
id_tblone: 1
name: data one
id: 2
id_tblone: 1
name: data two
Select will show:
input one
input two
I want to use Kartik's select in a form that will save new data in tbl_second. So I need Select2 to select id_tblone (or id from tbl_one) and his according name. User needs to select, let's say proper category (from first table - I have fk that relates those two tables) and add some new data under that category in second table.
What would be proper way to do this?
Edit: i have managed so far to show proper names under proper id_tblone, but it saves data with value null in id_tblone column in my second table
In controller:
$query = array();
$query = (new \yii\db\Query())
->select(['id', 'name'])
->from('tbl_one')
->leftJoin('tbl_second', 'tbl_second.id_tblone = tbl_one.id')
->all();
in view:
$data = ArrayHelper::map($query,'name', 'id');
echo Select2::widget([
'name' => 'newname',
'data' => $data,
'pluginOptions' => [
'allowClear' => true
],
]);
I am trying to do a check against 3 table that I join together. I do not want to use the real table name hard coded as my project is highly under develop and table prefix may be changed. What is the best way in Yii2 to select from 3 table where I have where statement on the joined table?
I can get what I want from the code below. But as I said, I do not want to use the table alias hard coded. Any idea how to fix this or suggestion of other ideas would be very appreciated.
$userId = Yii::$app->user->id;
$result = \app\models\UserPermission::find()->joinWith([
'permission',
'permission.service'
])->where([
'prefix_user_permission.user_id' => $userId,
'prefix_permission.flag' => Permission::LOGIN,
'prefix_service.login_available' => Service::LOGIN_AVAIABLE,
])->all();
I would like to end up with this query:
SELECT *
FROM `prefix_user_permission` `up`
INNER JOIN `prefix_permission` `p` ON `up`.`permission_id` = `p`.`id`
INNER JOIN `prefix_service` `s` ON `p`.`service_id` = `s`.`id`
WHERE (`up`.`user_id`=43)
AND (`p`.`flag`='LOGIN')
AND (`s`.`login_available`=1);
The table prefix can be configured using the 'tablePrefix' param along with the main db config as follows:
'components' => [
'db' => [
//other db config params
'tablePrefix' => 'pre_'
]
This prefix can be used as follows:
There's a special variant on this syntax specific to tablenames: {{%Y}} automatically appends the application's table prefix to the provided value, if a table prefix has been set:
$sql = "SELECT COUNT([[$column]]) FROM {{%table}}";
$rowCount = $connection->createCommand($sql)->queryScalar();
Or if you are using active record for models then you can also use the tableName() function to replace the hard-coded table names.
I created a php function to fetch records from a sql table subscriptions, and I want to add a condition to mysql_query to ignore the records in table subscriptions that exists in table removed_items, here is my code;
function subscriptions_func($user_id, $limit){
$subs = array();
$sub_query = mysql_query("
SELECT `subscriptions`.`fo_id`, `subscriptions`.`for_id`, `picture`.`since`, `picture`.`user_id`, `picture`.`pic_id`
FROM `subscriptions`
LEFT JOIN `picture`
ON `subscriptions`.`fo_id` = `picture`.`user_id`
WHERE `subscriptions`.`for_id` = $user_id
AND `picture`.`since` > `subscriptions`.`timmp`
GROUP BY `subscriptions`.`fo_id`
ORDER BY MAX(`picture`.`since_id`) DESC
$limit
");
while ($sub_row = mysql_fetch_assoc($sub_query)) {
$subs [] = array(
'fo_id' => $sub_row['fo_id'],
'for_id' => $sub_row['for_id'],
'user_id' => $sub_row['user_id'],
'pic_id' => $sub_row['pic_id'],
'since' => $sub_row['since']
);
}
return $subs ;
}
My solution is to create another function to fetch the records from table removed_items and set a php condition where I call subscriptions_func() to skip/unset the records that resemble the records in subscriptions_func(), as the following
$sub = subscriptions_func($user_id);
foreach($sub as $sub){
$rmv_sub = rmv_items_func($sub[‘pic_id’]);
If($rmv_sub[‘pic_id’] != $sub[‘pic_id’]){
echo $sub[‘pic_id’];
}
}
This solution succeeded to skip the items in the table removed_items however this solution makes gaps in the array stored in the variable $sub which makes plank spots in the echoed items.
Is there a condition I can add to the function subscriptions_func() to cut all the additional conditions and checks?
Assuming id is the primary key of subscriptions and subs_id is the foreign key in removed_items, then you just have to add a condition to the WHERE clause. Something like this should work :
...
AND `subscriptions`.id NOT IN (SELECT `removed_items`.subs_id FROM `removed_items`)
...
Not related to your problem :
Your code seems vulnerable to SQL injection : use prepared statement to prevent this.
The original Mysql API is deprecated, it is highly recommended to switch to Mysqli instead.
i'm thinking about this for days now and don't come to grasps (since i'm relativley new to MVC and CI). I'm not even sure whether this is an issue with MVC, MySQL or arrays.
Situation: 2 MySQL tables
Table data: id, title, list
Table values: id, name
Querying the data table results in an array like the following (excerpt):
[4] => Array
(
[id] => 3
[title] => Foo
[list] => 1,2,3,4,6,14
)
[5] => Array
(
[id] => 4
[title] => Bar
[list] => 2,6,9,12
)
The field list contains comma separated values that correspond to some IDs of the values table like
[3] => Array
(
[id] => 12
[name] => 'value12'
)
What I try to do for each row is:
take the list-values & explode it into an array
check with the result set from the values-table (via in_array() method)
return the name values of the IDs if
include it somehow into the main result set (e.g. as a 2-dimensional array):
[5] => Array (
[id] => 4
[title] => Bar
[list] => Array (
[0] => value6
[1] => value12
...
)
)
My naive approach so far was to
run a query on each of the 2 tables
compare the 2 result sets via in_array
My main problem (while trying to strictly separate model, controller and view): How can I include the name field from the values-table in the "main loop" of the data table result set?
if($q->num_rows() > 0)
{
$data[] = $q->result_array();
foreach ($q->result() as $row)
{
$data[] = $row;
}
return $data;
}
If I use the following (cumbersome) approach i naturally get a new item each time:
foreach ($q->result_array() as $row)
{
$data[]['id'] = $row['id'];
$data[]['title'] = $row['title'];
$data[]['list'] = $row['year'];
}
Since this is a MySQL database I see no way to do the explode and the comparison in SQL (with LIKE or something else).
Any hint, even a simple link to an info bit, is highly appreciated.
Thanks a trillion!
fab
There is a many-to-many relationship between lists and list values. The conventional way to model this in a relational database is to create a joining table. So I'd structure your schema like this.
lists : list_id, title
values : value_id, name
list_values : list_id, value_id
list_values is the joining table. It links lists with values.
To build a list you could have the following functions in your model
function build_list($list_id)
{
$list = $this->get_list($list_id);
$list->values = $this->get_list_values($list_id);
return $list;
}
function get_list($list_id)
{
$sql = 'select * from lists where list_id=?';
return $this->db->query($sql, array($list_id))->row();
}
function get_list_values($list_id)
{
$sql = 'select v.value_id, v.name
from list_values lv
join values v on v.value_id=lv.value_id
where lv.list_id=?';
return $this->db->query($sql, array($list_id))->result();
}