I just started to use the PHP ActiveRecord class and get along with it quiet well but now I'm stuck by trying to associate a user with a group, and a group with many users.
This is what I've got:
The SQL-Part:
CREATE TABLE `users` (
`id` INT(255) NOT NULL AUTO_INCREMENT,
`group_id` INT(255) NOT NULL ,
`name` VARCHAR(150) NOT NULL ,
`email` VARCHAR (150) NOT NULL ,
`passwd` VARCHAR (512) NOT NULL ,
`salt` VARCHAR (16) NOT NULL ,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
CREATE TABLE `groups` (
`id` INT(255) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(150) NOT NULL ,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
The PHP-Class:
#Class User.php
class User extends ActiveRecord\Model{
static $belongs_to = array(
array('group')
);
static $validates_presence_of = array(
array('name'),
array('email'),
array('passwd'),
array('salt')
);
static $validates_uniqueness_of = array(
array('name'),
array('email')
);
}
#Class Group.php
class Group extends ActiveRecord\Model{
static $has_many = array(
array('users')
);
static $validates_presence_of = array(
array('name')
);
static $validates_uniqueness_of = array(
array('name')
);
}
VAR DUMP User:
<?php
var_dump(User::find(1));
?>
Now if I search for an user no group is being attached... Does someone know how to solve this or can tell me what I'm doin wrong? I just can't find my mistake... :)
var_dump output:
object(User)[32]
public 'errors' => null
private 'attributes' (ActiveRecord\Model) =>
array (size=6)
'id' => int 1
'group_id' => int 1
'name' => string 'admin' (length=5)
'email' => string 'user#email.com' (length=17)
'passwd' => string 'f22b07f3b0f2d93a696336f040a6d08b8c36fe53fc5f080b5a3ad1db3387b4553f16ed2c7c4196900f3ff9b8aa516b115e8250be6c0a60f6e22cf768fe43c291' (length=128)
'salt' => string '6976e5b5410415bd' (length=16)
private '__dirty' (ActiveRecord\Model) =>
array (size=0)
empty
private '__readonly' (ActiveRecord\Model) => boolean false
private '__relationships' (ActiveRecord\Model) =>
array (size=0)
empty
private '__new_record' (ActiveRecord\Model) => boolean false
Thanks anyway for having a look at it :)
Made a workaround:
<?php
class Model extends ActiveRecord\Model{
public $Extensions = array();
protected $relations = array('has_one' => array(), 'belongs_to' => array());
static $after_construct = array('set_relations');
public function set_relations(){
foreach($this->relations['has_one'] as $relation){
$upper = ucfirst($relation);
$lower = strtolower($relation);
$id_table = $lower.'_id';
$this->Extensions[$upper] = $upper::find($this->$id_table);
}
foreach($this->relations['belongs_to'] as $relation){
$model = ucfirst($relation[0]);
$id_table = $relation[1];
$this->Extensions[$model] = $model::find(array('conditions' => array($id_table.' = ?', $this->id)));
}
}
}
And this is how you use it...
protected $relations = array('has_one' => array('group'), 'belongs_to' => array(array('publisher', 'user_id')));
static $validates_presence_of = array(
array('name'),
array('email'),
array('passwd'),
array('salt'),
array('group_id')
);
static $validates_uniqueness_of = array(
array('name'),
array('email')
);
}
?>
Related
Can you tell me why my code isn't working ? In my username table I have two columns, user_id and username. user_id is auto increment so I don't have that in my Sql statement, which I believe is the correct thing to do.
<?php
require('dbConnect.php');
$Number = $_POST['phonenumber'];
// The ? below are parameter markers used for variable binding
// auto increment does not need prepared statements
$query = "INSERT INTO user (username) VALUES (?)";
$stmt = mysqli_prepare($con,$query) or die(mysqli_error($con));
//bind variables
mysqli_stmt_bind_param($stmt,"s",$u);
//$stmt->bind_param("s",$u);
mysqli_stmt_execute($stmt);
if(mysqli_query($con,$query))
{
echo 'Inserted correctly';
}
else
{
echo 'Error';
echo var_dump($stmt);
}
mysqli_stmt_close($stmt);
mysqli_close($con);
?>
I keep getting 'Error', and in my var_dump I get :
C:\wamp64\www\phpproject\php-project\insert.php:28:
object(mysqli_stmt)[2]
public 'affected_rows' => int -1
public 'insert_id' => int 0
public 'num_rows' => int 0
public 'param_count' => int 1
public 'field_count' => int 0
public 'errno' => int 1048
public 'error' => string 'Column 'username' cannot be null' (length=32)
public 'error_list' =>
array (size=1)
0 =>
array (size=3)
'errno' => int 1048
'sqlstate' => string '23000' (length=5)
'error' => string 'Column 'username' cannot be null' (length=32)
public 'sqlstate' => string '23000' (length=5)
public 'id' => int 1
use null for autoincrement like this
$query = "INSERT INTO user (user_id,username) VALUES (null,$username)";
I encountered a very strange bug today. I am getting sideblinded by this so bad as it's breaking my entire application.
So, I have this little framework that I've built where I have a standard modell, so snippeting this will be a little long and descriptive.
<?php include('inc/inc.php'); ?>
<?php
if(!empty($_POST['answer']) && !empty($_POST['levelstart'])){
if($stmt = $site->answerQuestion($_POST['levelstart'], $_POST['answer'])){
if($stmt[0]){
echo json_encode(array('success' => true, 'correct' => $stmt[1], 'correctanswer' => $stmt[2], 'round_end' => $stmt[3]));
}else{
echo json_encode(array('success' => false, 'error' => 'error occurred'.$stmt[1]));
}
}else{
echo json_encode(array('sucess' => false, 'error' => 'Unknown error'));
}
}else{
echo json_encode(array('success' => false, 'error' => 'Provide all necessary parameters.'));
}
?>
this piece of code outputs the following.
INSERT INTO quiz_level_starts (`user_id`, `question_id`, `time`, `round_id`, `type`, `success`, `ref_id`) VALUES ('4', '10', '1471887809', '', '1', '1', '905'){"success":false,"error":"error occurred23000"}
The generated query above is only a dummy one that i simple put together so I don't need the parameterization for simply testing. The "error" key in the json array contains error data, and the errorcode is dumped there.
23000 is the mysql error code for there being a duplicate unique column, but there is no unique column that I'm using in the query(see table struct below.)
Since the function answerQuestion is a very long one, I'll only paste the related lines next. In $site->answerQuestion it calls a function called "insertLevelStarts" which is supposed to insert an entry to the db.
This is how i call it:
if($stmtss = $this->db->insertLevelStarts($_SESSION['user']['id'], $stmts['return'][0]['id'], time(), $roundid, 1, 1, $levelstart)){
And this is how it's declared, also the rest of the related and unknown code:
public function insertLevelStarts($user_id, $question_id, $time, $round_id, $type = 0, $success = 0, $refid = 0){
/*
Type=0 start 1 stop
success=0 for start 1 if successfull on stop
*/
$query = 'INSERT INTO quiz_level_starts (`user_id`, `question_id`, `time`, `round_id`, `type`, `success`, `ref_id`) VALUES (:user_id, :question_id, :time, :round_id, :type, :success, :refid)';
echo $this->genFakeQuery($query, array(
':user_id' => $user_id,
':question_id' => $question_id,
':time' => $time,
':type' => $type,
':success' => $success,
':refid' => $refid,
':round_id' => $round_id
));
return $this->execInsert($query, array(
':user_id' => $user_id,
':question_id' => $question_id,
':time' => $time,
':type' => $type,
':success' => $success,
':refid' => $refid,
':round_id' => $round_id
)
);
}
public function genFakeQuery($query, $array){
foreach($array as $key => $val){
$query = str_replace($key, "'$val'", $query);
}
return $query;
}
public function execUpdate($query, $preparray, $updatearr){
try {
$stmt = $this->db->prepare($query);
$stmt->execute(array_merge($preparray, $updatearr));
$rows = $stmt->rowCount();
if($rows > 0){
return array('type' => 'rowsaffected', 'return' => $rows);
}else{
return array('type' => 'noreturn', 'return' => 'none');
}
} catch(PDOException $ex) {
return array('type' => 'error', 'return' => $ex);
}
}
public function updateClause($query, $update, $updatearr){
if(count($update) > 0){
$count = 0;
foreach($update as $k => $v){
if($count > 0){
$query .= ',';
}
$query .= " `$k` = :$k";
$updatearr[":$k"] = $v;
$count++;
}
}
return array('query' => $query, 'updatearr' => $updatearr);
}
The aforementioned query
INSERT INTO quiz_level_starts (`user_id`, `question_id`, `time`, `round_id`, `type`, `success`, `ref_id`) VALUES ('4', '10', '1471887809', '', '1', '1', '905')
inserts into a table looking like this:
CREATE TABLE IF NOT EXISTS `quiz_level_starts` (
`id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`question_id` int(11) NOT NULL,
`time` int(11) NOT NULL,
`type` int(11) NOT NULL,
`success` int(11) NOT NULL,
`ref_id` int(11) NOT NULL,
`round_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `quiz_level_starts`
ADD PRIMARY KEY (`id`);
ALTER TABLE `quiz_level_starts`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
Will greatly appriciate any help recieved.
I assume that the error occurs because round_id is an integer field that can not be NULL and has no default value and you pass it an empty value.
Try if this query works:
INSERT INTO quiz_level_starts (`user_id`, `question_id`, `time`, `round_id`, `type`, `success`, `ref_id`) VALUES ('4', '10', '1471887809', '0', '1', '1', '905')
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.
I'm trying to get some data from table and print or use only the data.
Failing to do both ...
$con=mysqli_connect($MySQL_Host,$MySQL_User,$MySQL_Password,$MySQL_DB);
function echo_func_test ($db_con,$INPUT_IndustryName){
$result = mysqli_query($db_con,"SELECT ID FROM Industries where IndustryName = '$INPUT_IndustryName'");
//$Data = mysql_fetch_row($result);
var_dump ($result);
}
$IndustryName = Utilities;
echo_func_test($con,$IndustryName);
=================
the output is:
mysqli_result::__set_state(array(
'current_field' => NULL,
'field_count' => NULL,
'lengths' => NULL,
'num_rows' => NULL,
'type' => NULL,
)) root#virtual-dev:/home/ftpadmin/FirstPHP2# php Scripts/main.php
What am I doing wrong?
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]);
}