My question is how should i be inserting php class objects into the database?
If i have
Cat.php
class Cat{
private $name;
public function setName($name){
$this->name = $name
}
public function database(){
....$this->name;
//Insert stuff into db
}
}
Somefile.php
if($_POST['catname']){
//This way?
$obj1 = new Cat();
$obj1->setName($_POST['catname']);
$obj1->database();
//Or this way
//Insert Cat directly into the db without creating an object of Cat
}
And i want to insert this cat into the database. Would it be best to create a function within cat that gets $this->name or before i create the object should i just insert it into the database?
The easiest way of doing it would be to serialize your class to string.
$string = serialize($cat);
http://php.net/manual/en/language.oop5.serialization.php
But this way you will create lots of overhead in your database.
The best way to do it would be to have the relevant fields in your table and just save the corresponding values. You can easily create a function which reads / saves your class to a table. This would make your data much more portable and exchangeable.
You can use serialize, and if you have a good autoloader, you will not have to worry about the class not existing when you unserialize.
Also note the 2 magic functions that you can use:
__sleep() - custom code to use when serializing an object
__wakeup() - custom code when unserializing an object
PS:
Replace:
$obj1->setName = $_POST['catname'];
with
$obj1->setName($_POST['catname']);
References:
http://php.net/manual/en/oop4.magic-functions.php
http://php.net/manual/en/function.serialize.php
http://php.net/manual/en/language.oop5.serialization.php
Ideally, the object itself should deal with saving itself to the database. This way, your logic doesn't need to know what cat is, or where it is saving itself. The cat class should be self-contained, and this means if you want to change DB types or anything else in the future, you can make it in the class without affecting your logic.
You should have a separate object that takes an instance of cat and puts the data into the database. You may want to have a method of getVitalData which provides all the data that should go into the database (you may eventually have more than just name).
Each class should have one responsibility
Normally there are several layers in your project and one of this layer is the DAO (Data Access Object). In this class you link your application to a database. this layer has to save your object into the database via a save method for example...
The day you wanna change the database you just rewrite this layer
To be really ideal, the object that is present in the DAO layer is different from the model object (CAT) : it is a persistent Object that looks like the table in the database
Take a look at serialize and unserialize, you can store the serialised string in your database if required - here's a quick example.
<?php
class Cat {
protected
$name;
public function getName() {
return $this->name;
}
public function setName($name) {
$this->name = $name;
return $this;
}
}
$cat = new Cat;
$cat->setName('Tiddles');
$string = serialize($cat);
$cat = unserialize($string);
var_dump($cat);
/*
object(Cat)#2 (1) {
["name":protected]=>
string(7) "Tiddles"
}
*/
Anthony.
Related
Recently I have starting trying to do more OOP based programming as I know it's way better than procedural programming but I have a probably simple question. If I want to implement a "tasks" class where each tasks has a title, description, how far completed it is and who submitted it. I have the following code to create the class:
class Tasks
{
public $title;
public $description;
public $completionPercent;
public $contact;
public function __construct($title, $description, $completionPercent, $contact)
{
$this->title = $title;
$this->description = $description;
$this->completionPercent = $completionPercent;
$this->contact = $contact;
}
public function getTitle()
{
return $this->title;
}
public function getDescription()
{
return $this->description;
}
public function getCompletionPercent()
{
return $this->completionPercent;
}
public function getContact()
{
return $this->contact;
}
public function setTitle($title)
{
$this->title = $title;
}
public function setDescription($description)
{
$this->description = $description;
}
public function setCompletionPercent($completionPercent)
{
$this->completionPercent = $completionPercent;
}
public function setContact($contact)
{
$this->contact =$contact;
}
}
My question is if I create a tasks and then access it later as in close the browser and then come back to it a few days later when I have an update to it how do I store it and re-access it. I understand databases and use them very often in my current sites I am using to learn but I don't see how storing the information from the class in the database would be logical when I assume you could just skip the class and utilize the database. I read that you could serialize or store XML/json in a file and access the class that way but again I don't see why you would need the class if you could just read a file into an array and use it that way. I know OOP is important but I am still just trying to get it down to where I can start using classes regularly so that I can get familiar with them and progress as a programmer. I am sure there is plenty of reading out on the net about his but I just keep finding stuff on storing class variables in session variables which is not exactly what I want. Let me know if there is something I can clarify, I know when I first make the class I would do something like $task1 = new Task(...); but after closing my browser and logging back in I am not able to still access $task1 correct? I cannot just do $task1->getTitle(); so how do I re-initialize the class?
Classes and objects help you organise your code and logic into self contained units. That is all. And that is very important. It does not address the issue of storage or anything else.
Yes, you would still store the data of the object in the database, and then read again from the database and create an object instance again.
input → new Task(..) → store object data in database
read data from database → new Task(..) → display on website
Why is this better than working with arrays from the database directly? Because it allows you to organise your code better. Even if the object's lifetime is just a fraction of a second, within that fraction all the code that uses the object can be written much more elegantly and most of all type safe, because it is clearly defined what that object looks like. An array is an untyped grab bag of stuff which is hard to work with the more complex your application becomes. Especially refactoring code which uses only arrays is very very hard.
You are right, you need to store such information somewhere, and right place for that is db. So, question is: why you need to use and create class "Task" if you can directly save it in db. Because you want to build application based on "classes and objects", so not to use procedural programming, as you said. Therefore, you need to use objects and create classes for everything in order to have fully OO application.
So, your application should be based on classes/objects and this is what you and some other developers will work with. Now you just need to save this data from that object into the database. That means, you need introduce some additional layer for this. One very nice is Doctrine ORM. It does mapping and translate your object into db. Usually each class has its own table in db and each field in the class has its own column in db (this is only for classes which need to be saved in db)
The point is, that you can easily use objects in your application like any other objects without knowing how they should be saved in db (or somewhere else). Only what you need to do is:
$task->save();
and that's it. That task will be saved in db.
Sorry if I am not using the best jargon, but I have run into an issue I want to solve early before I write too much code. Which of these options below is "better"? And is there a better way of doing this? Someone mentioned to me abstracting my code but another class seems to be the last thing I need. Also I feel like there's something I can do by potentially making my "get" function seen below into a public static function so that I can use it differently. (its not static right now)
Here is my situation:
I have 2 (relevant to this question) classes, DB (database) and Page (for getting my content to display on my website)
the DB class has a query method that prepares and execute my queries
the DB class also has methods for inserting, getting, deleting things from the database.
I now feel that I may not even need my page class because right on the webpage I can just use those DB methods to call my content. (I store all images, content, page title, description in mysql). Is this not a legitimate way to do this? Won't I need to create a new object each time? such as:
$pg_ID = 2;
$title = new DB($pgID);
$title->get('pages', $pgID, $lang); // 3 tables to pull from for each page
$images = new DB($pgID);
$images->get('images', $pgID, $lang);
$structure = new DB($pgID); // I need these tables mostly because my site is in two languages
$images->get('pages_list', $pgID);
I do not like this potential solution just because to me its counter intuitive. Why should I have to create new objects just to reuse a function? However, what I do right now is something I feel is going to get me some hate mail.
$page = new Page();
$page->find('pages', $pgID, $lang);
$page->lookup($pgID);
$page->retrieve('images', $pgID, $lang);
These are 3 separate functions in my Page class that perform very similar things. Find gets my pages content out of the database and returns it as an object. Lookup does basically the same thing but only needs to pass one variable because its only to do with the html structure of each page regardless of which language is being accessed. retrieve gets all images from a table that get shown in a slider with different language descriptions. But as you can see, all three functions do basically the same thing! They query the database. Thanks for the help with this I am literally just getting into this OOP and its driving me insane. Stack has been very helpful and I think I just didn't know how to search for this to find the answer. Feel free to point me to other questions/answers that I may have missed. It was hard for me to think of the keywords to search for.
we may create other classes indeed, but efficiently so. Maybe we can render DB a public state function. I like the idea of creating a database object, pass it as parameter to an other object, which could then format data with the link he just received:
$pg_ID = 2;
$db = new DB($pg_id);
$page = new Page($db,$pg_ID);
// make sure you assign the parameters a private properties in `Page()` ctor.
then, from inside your function, you can call images, titles and structures at will from $this
$title = $this->DB->get('pages', $this->pgID, $lang);
$images = $this->DB->get('images', $this->pgID, $lang);
$structure = $this->DB->get('pages_list', $this->pgID);
and you can those other method as well
$page->find('pages', $this->pgID, $lang);
$page->lookup($this->pgID);
$page->retrieve('images', $this->pgID, $lang);
Now we do not need to create a new object each time we want information from the database.
Now...
the way I access member functions here $this->pgID is better used by defining a getter: $this->pgID(). I like my getter to have the same name as the property. This might not be a very good idea though.
private function pgID() {
return $this->pgID;
}
As for abstract classes..
I did in fact come very lately into thinking abstract classes were quite cool indeed. I've some problem with wording it, having a constant constructor with custom mandatory functions and possible different implementation of classes seems awesome:
abstract class Page {
function __construct($db,$pgID,$lang,$params='') {
$this->db = $db;
$this->pgID = $pgID;
$this->lang = $lang;
$this->init($params);
}
function pgID() {
return $this->pgID;
}
function lang() {
return $this->lang;
}
abstract function init();
abstract function retrieve();
}
class Structure extends Page {
function init($params) {
// some specific to Structure foo here
}
function retrieve($what='pages_list') {
return $this->db->get($what,$this->pgID,$this->lang);
}
}
class Image extends Page {
function init($params) {
// some specific to Image foo here
}
function retrieve($what='images') {
$images = $this->db->get($what,$this->pgID,$this->lang);
// plus some foo to resize each images
return $images;
}
}
ok, hope you're still there! Now we have a Structure and Image class with requisites constructor arguments, generic functions and a custom retrieve function. We could use them that way:
$db = new DB(2);
$template = new Structure($db,2,'fr');
$template->retrieve();
$slideshow = new Image($db,4,'en');
$slideshow->retrieve();
I do hope you do not have to create a new instance of DB if you use a different page id :-)
jokes appart this helps me using classes in a better structured way, as I might have many different classes to represent different parts of a site, but when called from an index all of them will have the same function names, like retrieve() or print(), list()...
I don't want to get into the weeds on a SPECIFIC implementation for you situation, rather I am going to offer some generic guidance.
First off, you shouldn't have to create a separate database object (dbo) for title, images, or structure. Chances are the DSN used for each dbo you are initializing are the exact same, so I would create a singleton dbo which can be shared across multiple objects. For reference take a look at Doctrine's connection manager.
Secondly, I think your objectification could be implemented better. Following most ORMS implementation, you have a Record class and a Table class. The Record class is a specific instance of a Record in your schema, whereas the Table class executes queries against your store which may result in multiple records. These results are then hydrated into an array (of records).
So what I would suggest is something like this (code has not been tested and some of it has been stubbed for brevity):
class PageTable
{
public static function getById($id)
{
// Validate id, if invalid throw exception
$dbo = Database::getConnection();
$stmt = $dbo->prepare('SELECT * FROM page WHERE id = :id');
$stmt->bindParam(array('id' => $id));
$stmt->execute();
$result = $stmt->fetch();
$page = new Page;
// Hydration
$page->setId($result['id']);
$page->setImages($result['images']);
return $page;
}
}
class Page
{
protected $id;
protected $title;
public function setId($id){}
public function getId(){}
}
Hopefully this separation of Record and methods affecting a single, or multiple records makes sense. You should take a look at a DBAL, like Doctrine.
The other day, while developing my PHP project and implementing the User class, i started to wonder how this class should interact with the MySQL database the project is using.
Let me start with an example: let's say I have a getName() method, inside the User class, that returns the user's real name. What's the more fitting way to implement that method?
I came up with 2 solutions:
I put the DB query inside the getName() and only get what I need like this:
public function getName() {
// MySQL query code here
}
I create a load() method inside the User class that load all the user data inside the class structure and then the getName() is something like this:
private $name;
// Load all user data inside the class' structure
public function load() {
$this->name = // MySQL query here
}
public function getName() {
return $this->name;
}
I thought, not sure if mistakenly or not, that the first way is more efficient because i only get the data I need, while the second way is more OOP but less efficient.
So, here's the question: what is the better way? Why? Are there better ways?
Either way, consider storing/caching the results of that so you do not make a query every time you use getName on that object.
Also, consider not wrrying about all that by using a ORM/DBAL Solution like propel or doctrine.
Also check out Lazy Loading and the Active Record Pattern
Run your query just in time and only run it once (unless you know the value might change), try something like the following:
class User {
protected $data;
function getName()
{
if (!isset($data['name'])) {
// if you can load more than just $this->data['name'] in one query
// you probably should.
$this->data['name'] = // query here
}
return $this->data['name'];
}
}
Aside from the question being kinda broad (as there are countless patterns), the second way you mentioned is better IMO, and to add to it I would also suggest supplying ID as a parameter which you could then use to build a single query to fetch the user by ID and then manually assign all properties (from the fetched row).
I'm in the process of re factoring a lot of code to make it more testable and I have a bunch of useful functions that rely on an instantiated database object.
Things like this:
function id_from_name($table, $name)
{
$db = get_database();
//code that returns an id
}
function username_from_user_id($id)
{
$db = get_database();
//code that returns a username
}
There are a bunch more like id_exists, id_active etc.
Now I'm thinking that this isn't the right thing to do as the object should probably be passed through as an argument? But then that means creating and sending in a new object into each of these functions every time i want to use one.
So really, my questions are: Should I be moving these functions into their own class/library that has access to the database object? and are the examples that I've shown above generally a bad way of doing things?
A better approach would be indeed to make classes. And you would be passing the database object to the constructor and make it an instance variable. That way every function would have access to the database object.
Now the reason why it is considered bad to instantiate e.g. your database object in every function, is because if you decide for example one day to change your datasource, you might need a huge refactor. If you pass your database object into the constructor, you can just pass/inject the right object into the class without any refactor.
...a bit more about DI below...
By passing your objects into the constructors, you also create a more clear API => you know which object depends on the other, you know exactly which class uses your DB object. If you start instantiating it or accessing it in a static way inside the functions like you did, I would have to look through all your classes to see where your DB object is used. One more point, dependency injection forces SRP (single responsibility principle) => if you start injecting too many objects (constructor gets many arguments), you should suspect your class is doing too much than what it should, and start refactoring.
You can create a class Table_Adapter and instantiate database object inside its constructor:
class Table_Adapter
{
protected $db;
public function __construct()
{
$db = get_database();
}
}
Then you create a child class Items_Table_Adapter' that extendsTable_Adapterand put their all methods related toItems` table.
class Items_Table_Adapter extends Table_Adapter
{
public function item_by_id($id)
{
}
}
Then you use it like:
$tableAdapter = new Items_Table_Adapter();
$item = $tableAdapter->item_by_id(1);
Try something like:
class YourClass{
public static function get_database(){
// your creation
return $db;
}
public function id_from_name($table, $name)
{
/* your code */
//code that returns an id
}
public function username_from_user_id($id)
{
/* your code */
}
}
so you could just use it this way:
$db = YourClass::get_database();
$result = $db->id_from_name($table, $name);
It is certainly recommended that you have the option to swap out your database connection.
Now, if your function get_database() looks like this:
function get_database() {
static $db;
if (!$db)
$db = new \mysqli(...);
return $db;
}
Then you really, really should change it to a wrapper around a class, looking like this:
function get_database_manager() {
static $dbmgr;
if (!$dbmgr)
$dbmgr = new DbManager;
return $dbmgr;
}
function get_database() {
return get_database_manager()->getCurrentConnection();
}
where DbManager has an instance attribute with the current connection that is returned with getCurrentConnection(). If you want to swapt out the connection, do something like get_database_manager()->setConnection($newConn). Problem solved :)
I'll leave the downsides of static programming here (it remains with many examples in this thread): http://kunststube.net/static/
as well as the common method to get rid of that (we have another approach here): http://en.wikipedia.org/wiki/Dependency_injection
I use a data class to feed templates my data, I want to calculate a unique id from the data in the data class so I can check if the template with that data is already in cache and then serve that version.
so a function to get an unique id from an array of a class would help me out.
something like this works but is rather costly md5(serialize($classdata))
I'm hoping there is some function to get the unique id without serializing all data, or at least not to have to in php.
edit:
I celebrated too soon, the unique id is only the same in the current instance
a restart of the same script makes another id, which then of course is not in cache.
testscript used:
<?php
class foo {}
$f = new foo;
print spl_object_hash($f);
I'll explain in some more depth
class template_data implements IteratorAggregate, ArrayAccess, Countable {
private $_data;
//some methods for the overloaded classes
//
//the getId function
public function getId() {
return hash('md5',serialize($this->_data));
}
}
$t = new template('file');
$d = new template_data('some data');
$t->addData($d);
$t->display();
Now if the data given to the template engine is in cache it uses that version
preventing to having to re-parse the template for the dataset.
This is a simplistic view of the template_data, it is actually lazy loading and uses memcached dataid's so the data isn't actually fetched till it is used in the template.
You could try spl_object_hash()
From the docs
This function returns a unique identifier for the object. This id can be used as a hash key for storing objects or for identifying an object.
PHP does not create unique IDs that persist between executions for objects, this means that you are going about producing the desired behavior correctly. So while there is no good answer for the asked question I can give some suggestions to reduce the cost of producing your IDs.
First you can use json_encode rather than serialize. Second, you can store the value, so that multiple calls to the function will not re-serialize the data every time.
The json_encode function is not only faster than serialize, but it also produces a shorter string as output.
http://cw-internetdienste.de/2015/05/04/serialize-vs-json_encode/
class template_data implements IteratorAggregate, ArrayAccess, Countable {
private $_data;
private $_id;
//
//some methods for the overloaded classes
//
//the getId function
public function getId() {
if(empty($this->_id))
$this->_id = hash('md5',json_encode($this->_data));
return $this->_id;
}
}
Lastly; the best solution will probably be to cache the output of the template using the route, or arguments as the basis for the unique cache keys rather than the individual data sets used.
Why not look into and overriding the __toString() method on the object to get and hash the relevant data in the object.
For example
class Object
{
// Some vars
public $name = "Jake";
public $age = 26;
public $dob = "1/1/10"
// the toString method
public function __toString()
{
return md5($this->name . $this->age . $this->dob);
}
}
// Create new object
$object = new Object();
// echo the object, this automatically calls your __toString method
echo $object
In this situation you don't use serialize, which is costly, instead just use __toString() to generate your own unique id based on variables stored with the object.