I want to get the the id of the last inserted row in a database so I created a static field in my model:
public static $lastid;
and I try to override the create method:
public static function create($data){
parent::create($data);
$lastid = DB::getPdo()->lastInsertId();
}
now I have an Error exception saying:
Declaration of Actor::create() should be compatible with Illuminate\Database\Eloquent\Model::create(array $attributes)
how can I make this work?
Here, the keyword array before $data will print a fatal error if the data are not an array.
Like is said in the error, your class extends Illuminate\Database\Eloquent\Model and should be compatible with his parent.
public static function create(array $data = array()){
parent::create($data);
$lastid = DB::getPdo()->lastInsertId();
}
When you use the Model::create method you can grab the ID straight from the result.
$actor = Actor::create(array('name' => 'Jason'));
dd($actor->id);
You shouldn't need to use the lastInsertId method from the PDO object.
Related
I'm attempting to fetch, convert and save a value in a models' constructor in Laravel 5.2. The reason being that it's saved in the database as hex, and I need to convert it to binary pretty often, and would like to do it once and save the result in a class attribute. But I can't seem to be able to fetch the value from $this in the constructor.
Here's a excerpt of what I'm working with, guid is a field in my table.
class Person extends Model {
private $bGuid = null;
public function __construct(array $attributes = []) {
parent::__construct($attributes);
$this->ad = Adldap::getProvider('default');
$this->bGuid = hex2bin($this->guid);
}
public function getName(){
$query = $this->ad->search()->select('cn')->findBy('objectGUID', $this->bGuid);
return $query['attributes']['cn'][0];
}
}
The $this->ad attribute executes as expected, but $this->bGuid does not. Some debugging shows that $this->guid when referenced in the constructor returns null. While if referenced in the getName() method directly works just fine.
My intermediate solution is creating a new function and just call $this->getbGuid(), thus making me a bit more satisfied with the DRY-ness, but it still has to convert it each time it is called.
I would appreciate it if anyone could tell me what's going wrong, so I could improve the code :)
Try to override another method from Model: newFromBuilder().
This is the one that is executed once the data is retrieved from the DB, not the __construct() one:
class Person extends Model {
private $bGuid = null;
public function newFromBuilder($attributes = [], $connection = null)
{
$model = parent::newFromBuilder($attributes, $connection);
$model->bGuid = hex2bin($model->guid);
return $model;
}
}
Note, that inside the overridden method you refer to the object as $model (instead of $this), and it has to return the $model object at the end.
i am making a database abstraction class that binds objects like an ORM. I'm having issue with a particular case, fetching a single row and binding to a class. While the same is working well with fetchAll() i can't figure out why using fetch(PDO::FETCH_CLASS) the object returns null.
if i use PDO::FETCH_LAZY it works, but isn't a correct binding to the passed class.
Here the code.
The Database() class is connects to db using PDO. Products() is a class made of public attributes with same name of tables.
The controller:
public function editProducts($params) {
$products = new Products();
$db = new Database ();
$id = array_keys($params);
$products = $db->findById($products, $id[0]); // auto Bind object fetched=no and POST params?
$this->template = new Template();
$this->template->renderArgs("product", $products);
$this->template->renderArgs("page_title", "Edit product " . $products->title);
$this->template->render(get_class($this), "editProducts");
}
The DB class:
public function findById($object,$id) {
try {
$table = $this->objectInjector($object);
} catch (Exception $e) {
if (APP_DEBUG) {
d($e->getTrace());
}
return;
}
$statement = "SELECT * FROM $table WHERE id=:id";
$this->stm = $this->pdo->prepare($statement);
$this->bindValue(":id",$id);
return $this->fetchSingleObject($object);
}
the method that abstract fetch:
public function fetchSingleObject($object) {
$this->execute();
$this->stm->setFetchMode(PDO::FETCH_CLASS, get_class($object));
return $this->stm->fetch(PDO::FETCH_CLASS);
//return $this->stm->fetch(PDO::FETCH_LAZY); this works!
}
I missed something? the fetchAll() works nicely in this way:
public function fetchObjectSet($object) {
$this->execute();
$this->stm->setFetchMode(PDO::FETCH_CLASS, get_class($object));
return $this->stm->fetchAll(PDO::FETCH_CLASS);
}
Thank you so much.
PS: some methods like $this->execute() are just abastractions to pdo->statment method since pdo and stm are db class instance variables.
I found the answer to the question by myself, i post the answer for everyone.
Instead of using directly PDO::FETCH_CLASS, $Class, i switched using setFetchMode() passing PDO_FETCH_INTO, new $Object instance.
This return correctly new instance of given object (with object methods and fields). Works well with public attributes and overloaded constructors.
The previously statement "findAll() works" wasn't true, i was returning somehow like FETCH_OBJ, an object representation of the database table.
Here the solution:
public function fetchSingleObject($object) {
$this->stm->setFetchMode(PDO::FETCH_INTO, new $object());
$this->execute();
return $this->stm->fetch();
}
Return a new instance of passed in object.
Works also as fetchAll()
EDIT:
public function fetchObjectSet($object) {
$this->execute();
return $this->stm->fetchAll(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, get_class($object));
}
The manual states:
bool PDOStatement::setFetchMode ( int $PDO::FETCH_CLASS , string
$classname , array $ctorargs )
so perhaps try:
$this->stm->setFetchMode(PDO::FETCH_CLASS, 'get_class', $object );/* is $object an array ? */
or, without
$this->stm->setFetchMode(PDO::FETCH_CLASS, 'get_class' );
How exactly does CI custome object works ?
As per CI documentation You can also pass a string to result() which represents a class to instantiate for each result object (note: this class must be loaded)
$query = $this->db->query("SELECT * FROM users;");
foreach ($query->result('User') as $row)
{
echo $row->name; // call attributes
echo $row->reverse_name(); // or methods defined on the 'User' class
}
}
This is a very nice feature yet what Ci does is it will return an array of User objects and set attributes from row to it.
i have a problem with it that i want to have more control on what attributes to be publicly accessed and what to be modified before setting/getting.
how can i accomplish this ? can i tell CI to pass all attributes to constructor so that class can populate its own data ?
example class User
class User{
private $data=array();
protected $CI;
//public $id,$name,$dob,$gender,$role,$username,$password,$salt,$picture,$lastactive;
function __construct($data=null)
{
$this->data = $data; // i want to save data to a private var and allow attr. throu getters only
}
function set_password($p){
$this->generateSalt();
$this->data->password = $p.$this->data->salt;
}
}
In a nutshell::
I want to use custom_result_object but i dont want codeigniter to populate class attributes for me, instead i want the class to receive those attrs and populate it him self the way he this its appropriate.
I found your question while looking for a solution for myself.
After digging a bit in the documentation I managed to figure it out:
class user_item {
// you can declare all the attributes you want as private
private $id,$name,$dob,$gender,$role,$username,$password,$salt,$picture,$lastactive;
function __construct(){
// you can use the constructor to format data as needed
$this->username = strtouppper($this->username);
}
public function set_password($p){
$this->generateSalt();
$this->password = $p.$this->salt;
}
public function get_password(){
return $this->password;
}
}
Once set up, you can instantiate this class from $this->db->result()
class User_model extends CI_Model {
public function get_user($id){
return $this->db->get_where('users', array('id' => $id), 1)->result('user_item');
}
}
And call any public method or attribute of the class as needed
class Users extends CI_Controller {
function __construct(){
$this->load->model('user');
}
public function profile($user_id){
var $myUser = $this->user->get_user($user_id);
$myUser->set_password('myPassword');
echo $myUser->get_password();
}
}
I have simplified the code to make it clearer, but you get the idea.
this example controller using result array and object
if ($this->session->userdata('id_jurusan') ==1) {
$where=array('id_jurusan'=>$this->session->userdata('id_jurusan'));
$value = $this->session->userdata('id_jurusan');
$value2 = $this->session->userdata('username');
$data['rule']=$this->guru_mod->get_where($where,'forward_changing')->result();
$data['fuzzy']=$this->guru_mod->get_data_all('fuzzy')->result();
$data['artikel']=$this->guru_mod->get_data_all('artikel')->result();
$data['kondisi']=$this->guru_mod->get_where($where,'kondisi')->result();
$data['artikel2'] = $this->guru_mod->get_data_all2('artikel','id_jurusan',$value);
$data['riwayat_rule'] = $this->guru_mod->get_data_all2('forward_changing','username',$value2);
$data['kondisi_rule'] = $this->guru_mod->get_data_all2('kondisi','id_jurusan',$value);
$this->load->view('guru/daftar_rule',$data);
}
With the following code, PDO won't return my $parcel as an object, but as an array. There for when i try to call my objects function, it will fail. Every example i have found has done this, in a similar way to mine. What am i doing wrong?
$statement = $this->connection->query($query);
$statement->setFetchMode(PDO::FETCH_CLASS, 'Parcel');
while ($parcel = $statement->fetch()) {
echo $parcel->hello();
}
The Parcel class, if interested.
class Parcel {
public $id;
public $parcel_number;
public $registred_at;
public $shipped_by;
public $shipped_at;
function __construct($parcel_number)
{
$this->parcel_number = $parcel_number;
}
public function hello(){
return "World";
}
}
And im using folder structures to structure the code and an Autoloader, that can probaly affect the PDO's way of calling the object.
While this is the error code
Call to a member function info() on a non-object
This error means the object is null or not instantiated properly, you might need to specify full path to your class.
For example
$statement->setFetchMode(PDO::FETCH_CLASS, 'app\model\Parcel');
i try work with the a class of database, and connect it to wipe it I build using extends, but I get an error. Example:
class Admin extends Sdba{
// Var:
public $login = false;
public $users;
public $users_list;
// Function:
public function UserLogin($char) {
if($this->login) {
print "in";
}else{
$this->users = Sdba::table('users'); // creating table object
$this->users_list = $this->users->get();
print_r($this->user_list);
print "out";
}
}
}
and my DB class is:
http://foska.pp.ua/codecanyon/sdba/
my error is: Fatal error: Call to private Sdba::__construct() from invalid context
Tanks !!
You are inheriting from Sdba class, and when you do that, the actual method: Sdba::table can be referenced as self::table in your child class.
Therefore, the code for creating table object should use:
$this->users = self::table('users'); // creating table object
You can also use parent::table to reference your function. But, the benefit of using self over parent is that you can further modify your table method in this child class, if need arises.
it should use parent::table because you use table method from extended class
$this->users = parent::table('users'); // creating table object