I'm super new to PHP mysql database, can someone help me out how can I make my input appear on the database. This is just a sample I'm testing. I don't know what I'm doing wrong I have all the information from the server inputed it at the right place. I'm getting a messages that it was successful but nothing is going to my database. I have one file called connect.php where the php is and the index.php for the html, table is name cultivar_db. Thanks in advance.
NOTE: Im connecting to my real server.
Structure
1 cultivar_idPrimary int(11) No None AUTO_INCREMENT
2 cultivar_name varchar(20) latin1_swedish_ci No None
Heres the complete details in the database
<?php
$servername = "localhost";
$username = "myusername";
$password = "*****";
$dbname = "mydbname";
$cultivar_name = $_POST['cultivar_name'];
//Database Connection
$conn = new mysqli($servername, $username, $password, $dbname);
if($conn->connect_error){
die('Connection Failed : ' . $conn->connect_error);
}else{
$stmt = $conn->prepare("INSERT INTO cultivar_db(cultivar_name)
values(?)");
$stmt->bind_param("s", $cultivar_name);
$stmt->execute();
echo "successfully input datas..";
$stmt->close();
$conn->close();
}
?>
<div class="box">
<form action="connect.php" method="post">
<label>Cultivar Name:</label>
<input class="inputstyle" type="text" name="cultivar_name"><br />
<input class="button inputstyle" type="submit" value="import" >
</form>
</div>
Three possible issues within
$stmt = $conn->prepare("INSERT INTO cultivar_db(cuttivar_id, cultivar_name) values(?,?,)");
The second , within the values might causes some trouble
Your ID field is set to AUTO INCREMENT, therefor no reason to insert it
You typed cuttivar_id in your SQL, instead of cultivar_id
If you created your table like this
CREATE TABLE cultivar_db (
cultivar_id NOT NULL AUTO_INCREMENT,
cultivar_name VARCHAR(20),
PRIMARY KEY (cultivar_id)
);
Then all you need for the insert is
$stmt = $conn->prepare("INSERT INTO cultivar_db(cultivar_name)
values(?)");
$stmt->bind_param('s', $cultivar_name);
$stmt->execute();
If your "cultivar_id" is auto-increment, you do not need to add that id from the HTML. You can simply pass the "cultivar_name" from HTML using $_POST.
$stmt = $conn->prepare("INSERT INTO cultivar_db(cultivar_name) values(?)");
$stmt->bind_param('s', $_POST['cultivar_name']);
$stmt->execute();
ok I'm a little late; but I hope to be still opportune; I won't add anything regarding syntax errors that other users have already told you to fix;
In my case I will leave you a working example of a database connection system and insert, each property and method has its PHPDOCS where a detailed explanation of the purpose or responsibility of the method is added; You will also notice that I have implemented the getter and setter of each private property:
db.php (file class)
<?php
class HandlerDataBase
{
/**
* #var string
* store the host server point
*/
private string $host;
/**
* #var string
* store database name
*/
private string $db;
/**
* #var string
* store the port connection point
*/
private string $port;
/**
* #var string
* store de username to implement in the connection to db server
*/
private string $user;
/**
* #var string
* password
*/
private string $password;
/**
* #param array $config
* #return void
* this method is implement to set the configuration to the database connection
*/
public function setConfigConnection(array $config)
{
foreach ($config as $key => $value) {
switch ($key) {
case 'host':
$this->setHost($value);
break;
case 'db':
$this->setDb($value);
break;
case 'port':
$this->setPort($value);
break;
case 'user':
$this->setUser($value);
break;
case 'password':
$this->setPassword($value);
break;
}
}
}
/**
* #return string
*/
public function getHost(): string
{
return $this->host;
}
/**
* #param string $host
*/
public function setHost(string $host): void
{
$this->host = $host;
}
/**
* #return string
*/
public function getDb(): string
{
return $this->db;
}
/**
* #param string $db
*/
public function setDb(string $db): void
{
$this->db = $db;
}
/**
* #return string
*/
public function getPort(): string
{
return $this->port;
}
/**
* #param string $port
*/
public function setPort(string $port): void
{
$this->port = $port;
}
/**
* #return string
*/
public function getUser(): string
{
return $this->user;
}
/**
* #param string $user
*/
public function setUser(string $user): void
{
$this->user = $user;
}
/**
* #return string
*/
public function getPassword(): string
{
return $this->password;
}
/**
* #param string $password
*/
public function setPassword(string $password): void
{
$this->password = $password;
}
/**
* #param string $query
* #param $value
* #return void
* this method implements a connection and executes the query script and the value passed.
* if there is an error it will be displayed, and execution will be stopped.
*/
public function setData(string $query, $value)
{
try {
$conn = $this->getConnection();
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->beginTransaction();
$conn->exec("set names utf8");
$stmt = $conn->prepare($query);
$stmt->bindValue(1, $value);
$stmt->execute();
$conn->commit();
$conn->close();
} catch (PDOException|Exception $e) {
var_dump($e);
}
}
/**
* #return PDO
* this method create a connection to the db
*/
private function getConnection(): PDO
{
return new PDO("mysql:host=".$this->getDb().";port=".$this->getPort()." dbname=".$this->getDb(), $this->getUser(), $this->getPassword());
}
}
implementation:
<?php
require_once 'db.php';
$config = [
'host' => 'localhost',
'db' => 'my_db_name',
'port' => '3306',
'user' => 'my_username',
'pass' => '********',
];
if (!isset($_POST['cultivar_name']) || '' != $_POST['cultivar_name']) {
echo 'Error: not received cultivar name data';
exit();
}
$cultivar_name = $_POST['cultivar_name'];
$query = "INSERT INTO cultivar_db(cultivar_name) values(?)";
$handler_database = new HandlerDataBase();
$handler_database->setConfigConnection($config);
$handler_database->setData($query, $cultivar_name);
another way to handle the configuration to the connection to the database, can be with a specific external file, see this:
config.php
<?php
$config = [
'host' => 'localhost',
'db' => 'my_db_name',
'port' => '3306',
'user' => 'my_username',
'pass' => '********',
];
then your implementation would look like this:
<?php
require_once 'config.php';
require_once 'db.php';
if (!isset($_POST['cultivar_name']) || '' != $_POST['cultivar_name']) {
echo 'Error: not received cultivar name data';
exit();
}
$cultivar_name = $_POST['cultivar_name'];
$query = "INSERT INTO cultivar_db(cultivar_name) values(?)";
$handler_database = new HandlerDataBase();
$handler_database->setConfigConnection($config);
$handler_database->setData($query, $cultivar_name);
Related
I created this code where I create an instance of the database and work with it. Now I'm trying to convert the code to a static form, but I can't.
$pdo = new PDO('sqlite:src/chinook.db');
$sql = "CREATE TABLE IF NOT EXISTS uzivatele(
uzivatelId INTEGER PRIMARY KEY,
jmeno TEXT,
prijmeni TEXT,
body INTEGER
);";
$statement = $pdo->prepare($sql);
$statement->execute();
function dropTable($pdo,$name)
{
$sql = "DROP TABLE $name";
$statement = $pdo->prepare($sql);
$statement->execute();
}
...
static
This is how I have a class implemented for pdo (according to the manual) and I would like to implement static methods, such as createTable, but I can't redo it
class Db
{
protected static $pdo = null;
public static function get(): \PDO
{
return self::$pdo ?? (self::$pdo = new \PDO(
'sqlite:hw-06.db',
null,
null,
[
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
]
));
}
}
use App\Db;
class Account
{
...
public static function createTable(): void
{
$db = Db::get();
$sql = "CREATE TABLE IF NOT EXISTS uzivatele(
uzivatelId INTEGER PRIMARY KEY,
jmeno TEXT,
prijmeni TEXT,
body INTEGER
);";
$statement = $db->prepare($sql);
$statement->execute();
}
index.php
Account::createTable();
If u want to implement a simple singleton, u can use the "getInstance()" concept and combine with "__callStatic" and "call_user_func_array" to make a PDO functions to be static too, all PDO and Database class functions will become static:
<?php
declare(strict_types = 1);
/*
* PDO database class - only one connection alowed
*/
final class Database
{
/**
* #var PDO $connection The connection
*/
private $connection;
/**
* #var Database $instance The single instance
*/
private static $instance;
/**
* #var string $engine The engine of connection
*/
private $engine = 'sqlite:persistence.db'; // sqlite::memory:
/**
* #var array $options Default option to PDO connection
*/
private $options = [
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false
];
/**
* Private constructor to prevent instance
*
* #throws \Throwable
* #return void
*/
private function __construct()
{
try {
$this->connection = new PDO($this->engine, null, null, $this->options);
}
catch (\Throwable $error) {
error_log("{$error->getMessage()}");
}
}
/**
* Get an instance of the Database
*
* #return PDO
*/
private static function getInstance(): PDO
{
// If no instance then make one
if (!self::$instance) {
self::$instance = new self;
}
return self::$instance->connection;
}
/**
* Transpiler of static methods for PDOStatements
*
* #var string $method The PDO static method
* #var array $args
* #return string|PDOStatement
*/
public static function __callStatic(string $method, array $args)
{
return call_user_func_array(array(self::getInstance(), $method), $args);
}
/**
* Destroying PDO connection
*
* #return void
*/
public function __destruct()
{
if (!empty($this->connection)) {
unset($this->connection);
}
}
/**
* Magic method clone is empty to prevent duplication of connection
*/
public function __clone() { }
public function __wakeup() { }
public function __toString() { }
}
to use there:
<?php
require_once __DIR__ . '/Database.php';
Database::exec('CREATE TABLE IF NOT EXISTS uzivatele (
uzivatelId INTEGER PRIMARY KEY,
jmeno TEXT,
prijmeni TEXT,
body INTEGER
);');
Database::exec("INSERT INTO uzivatele (jmeno, prijmeni, body) VALUES ('test', 'test', 1);");
var_dump(Database::lastInsertId());
$stmt = Database::prepare("SELECT * FROM uzivatele;");
$stmt->execute();
$data = $stmt->fetchAll();
var_dump($data);
note that "prepared statments objects" are still like objects!
i dont see any problem in using database connections as static, if they are not used in parallel, there is no problem, it even reduces the overhead of creating many connections with the database. but be careful, in some cases it may not be beneficial, as in cases where the code is not being executed by a CGI or FastCGI but by a wrapper, it can cause slowdowns and even give a problem!
I’m creating an authentication / login system using Slim 3 PHP on the back-end and Angular on the front-end and I’m trying to understand the ‘domain object’ and ‘data mapper’ part of a model layer within an MVC structure. I’ve read a lot of useful answers on various questions such as this, from which I understand the model should be comprised of ‘domain objects’, ‘data mappers’ and ‘services’.
However I’m not exactly sure what how this should be structured in the context of a user being able to register and log in to a website.
From my understanding I could have a user 'domain object' that has properties such as username and password. It could also have methods such as register or log in to represent business logic.
Would I then have a service class that creates a new instance of a user object, in which I would pass the form data into the object? So now my user object instance would have set username and password values?
Now i'm not sure how this objects property data would be inserted into the database. Would I use the user objects register method to insert the data into the database by passing in the username and password as parameters?
Apparently the service should be where the domain object and the data mapper interact, but i'm not sure how this would work if the register method is in the user domain object.
I was hoping someone could show me some code examples of what should be in the service class and how the interaction between the domain object and data mapper might work in the context of a user registering and logging in.
Note I don't want to use any frameworks, I want to try and implement a proper MVC structure manually as I feel i'd learn more.
So far I have this structure for registering a user:
I have an AuthenticationController with the method registerUser to allow a user to create an account:
class AuthenticationController
{
protected $authenticationService;
public function __construct(AuthenticationService $authenticationService)
{
$this->authenticationService = $authenticationService;
}
public function registerUser($request, $response)
{
$this->authenticationService->registerUser($request, $response);
}
}
I then have the AuthenticationService class with the registerUser method:
class AuthenticationService
{
protected $database;
public function __construct(PDO $database)
{
$this->database = $database;
}
public function registerUser ($request, $response)
{
$strings = $request→getParsedBody(); // will be sanitised / validated later
$username = $strings['username'];
$password = $strings['password'];
$email = "temp random email";
$stmt = $this->database->prepare("INSERT INTO users (email, username, password) values (:email, :username, :password)");
$stmt->bindParam(':email', $email);
$stmt->bindParam(':username', $username);
$stmt->bindParam(':password', $password);
$stmt->execute();
}
}
Later on I intend to put the SQL into an AuthenticationRepository and the PDO logic into it’s own class. This AuthenticationService method will also make sure the user details are sanitised using PHP’s built in functions.
I’m not sure if the proposed PDO database class or AuthenticationRepository would count as a data mapper or not.
The registration would be performed by the service.
The service could "directly" use a data mapper, in order to "transfer" the entity to/from the database. Though, additionally, a repository can be implemented. The service would see it and communicate with it as with a collection of one or more entities.
Since a service is part of the model layer (domain model), it should know nothing about any request or response objects. The controller should extract the needed values from the request and pass them as arguments to the service methods. A response can be sent back by the controller, or the view, depending on which MVC variation you are trying to implement.
You say "I intend to put the [...] PDO logic into it's own class". You really don't need to implement a wrapper for the PDO extension.
Here a registration example. I didn't test it at all. For more details see the resources list at the end of this answer. Maybe begin with the last one, which - I just realized - is the answer to a question of yours.
Used file system structure:
a) Extended "MyApp/UI":
b) Extended "MyApp/Domain":
The controller:
<?php
namespace MyApp\UI\Web\Controller\Users;
use Psr\Http\Message\ServerRequestInterface;
use MyApp\Domain\Model\Users\Exception\InvalidData;
use MyApp\Domain\Service\Users\Exception\FailedRegistration;
use MyApp\Domain\Service\Users\Registration as RegistrationService;
class Registration {
private $registration;
public function __construct(RegistrationService $registration) {
$this->registration = $registration;
}
public function register(ServerRequestInterface $request) {
$username = $request->getParsedBody()['username'];
$password = $request->getParsedBody()['password'];
$email = $request->getParsedBody()['email'];
try {
$user = $this->registration->register($username, $password, $email);
} catch (InvalidData $exc) {
// Write the exception message to a flash messenger, for example,
// in order to be read and displayed by the specific view component.
var_dump($exc->getMessage());
} catch (FailedRegistration $exc) {
// Write the exception message to the flash messenger.
var_dump($exc->getMessage());
}
// In the view component, if no exception messages are found in the flash messenger, display a success message.
var_dump('Successfully registered.');
}
}
The service:
<?php
namespace MyApp\Domain\Service\Users;
use MyApp\Domain\Model\Users\User;
use MyApp\Domain\Model\Users\Email;
use MyApp\Domain\Model\Users\Password;
use MyApp\Domain\Service\Users\Exception\UserExists;
use MyApp\Domain\Model\Users\UserCollection as UserCollectionInterface;
class Registration {
/**
* User collection, e.g. user repository.
*
* #var UserCollectionInterface
*/
private $userCollection;
public function __construct(UserCollectionInterface $userCollection) {
$this->userCollection = $userCollection;
}
/**
* Register user.
*
* #param string $username Username.
* #param string $password Password.
* #param string $email Email.
* #return User User.
*/
public function register(string $username, string $password, string $email) {
$user = $this->createUser($username, $password, $email);
return $this->storeUser($user);
}
/**
* Create user.
*
* #param string $username Username.
* #param string $password Password.
* #param string $email Email.
* #return User User.
*/
private function createUser(string $username, string $password, string $email) {
// Create the object values (containing specific validation).
$email = new Email($email);
$password = new Password($password);
// Create the entity (e.g. the domain object).
$user = new User();
$user->setUsername($username);
$user->setEmail($email);
$user->setPassword($password);
return $user;
}
/**
* Store user.
*
* #param User $user User.
* #return User User.
*/
private function storeUser(User $user) {
// Check if user already exists.
if ($this->userCollection->exists($user)) {
throw new UserExists();
}
return $this->userCollection->store($user);
}
}
The exception thrown when trying to register an already existing user:
<?php
namespace MyApp\Domain\Service\Users\Exception;
use MyApp\Domain\Service\Users\Exception\FailedRegistration;
class UserExists extends FailedRegistration {
public function __construct(\Exception $previous = null) {
$message = 'User already exists.';
$code = 123;
parent::__construct($message, $code, $previous);
}
}
<?php
namespace MyApp\Domain\Service\Users\Exception;
abstract class FailedRegistration extends \Exception {
public function __construct(string $message, int $code = 0, \Exception $previous = null) {
$message = 'Registration failed: ' . $message;
parent::__construct($message, $code, $previous);
}
}
The domain object (entity):
<?php
namespace MyApp\Domain\Model\Users;
use MyApp\Domain\Model\Users\Email;
use MyApp\Domain\Model\Users\Password;
/**
* User entity (e.g. domain object).
*/
class User {
private $id;
private $username;
private $email;
private $password;
public function getId() {
return $this->id;
}
public function setId(int id) {
$this->id = $id;
return $this;
}
public function getUsername() {
return $this->username;
}
public function setUsername(string $username) {
$this->username = $username;
return $this;
}
public function getEmail() {
return $this->email;
}
public function setEmail(Email $email) {
$this->email = $email;
return $this;
}
public function getPassword() {
return $this->password;
}
public function setPassword(Password $password) {
$this->password = $password;
return $this;
}
}
The value objects used by the entity:
<?php
namespace MyApp\Domain\Model\Users;
use MyApp\Domain\Model\Users\Exception\InvalidEmail;
/**
* Email object value.
*/
class Email {
private $email;
public function __construct(string $email) {
if (!$this->isValid($email)) {
throw new InvalidEmail();
}
$this->email = $email;
}
private function isValid(string $email) {
return (isEmpty($email) || !isWellFormed($email)) ? false : true;
}
private function isEmpty(string $email) {
return empty($email) ? true : false;
}
private function isWellFormed(string $email) {
return !filter_var($email, FILTER_VALIDATE_EMAIL) ? false : true;
}
public function __toString() {
return $this->email;
}
}
<?php
namespace MyApp\Domain\Model\Users;
use MyApp\Domain\Model\Users\Exception\InvalidPassword;
/**
* Password object value.
*/
class Password {
private const MIN_LENGTH = 8;
private $password;
public function __construct(string $password) {
if (!$this->isValid($password)) {
throw new InvalidPassword();
}
$this->password = $password;
}
private function isValid(string $password) {
return (isEmpty($password) || isTooShort($password)) ? false : true;
}
private function isEmpty(string $password) {
return empty($password) ? true : false;
}
private function isTooShort(string $password) {
return strlen($password) < self::MIN_LENGTH ? true : false;
}
public function __toString() {
return $this->password;
}
}
The exceptions thrown by the value objects:
<?php
namespace MyApp\Domain\Model\Users\Exception;
use MyApp\Domain\Model\Users\Exception\InvalidData;
class InvalidEmail extends InvalidData {
public function __construct(\Exception $previous = null) {
$message = 'The email address is not valid.';
$code = 123402;
parent::__construct($message, $code, $previous);
}
}
<?php
namespace MyApp\Domain\Model\Users\Exception;
use MyApp\Domain\Model\Users\Exception\InvalidData;
class InvalidPassword extends InvalidData {
public function __construct(\Exception $previous = null) {
$message = 'The password is not valid.';
$code = 123401;
parent::__construct($message, $code, $previous);
}
}
<?php
namespace MyApp\Domain\Model\Users\Exception;
abstract class InvalidData extends \LogicException {
public function __construct(string $message, int $code = 0, \Exception $previous = null) {
$message = 'Invalid data: ' . $message;
parent::__construct($message, $code, $previous);
}
}
The repository interface:
<?php
namespace MyApp\Domain\Model\Users;
use MyApp\Domain\Model\Users\User;
/**
* User collection, e.g. user repository.
*/
interface UserCollection {
/**
* Find a user by id.
*
* #param int $id User id.
* #return User|null User.
*/
public function findById(int $id);
/**
* Find all users.
*
* #return User[] User list.
*/
public function findAll();
/**
* Check if the given user exists.
*
* #param User $user User
* #return bool True if user exists, false otherwise.
*/
public function exists(User $user);
/**
* Store a user.
*
* #param User $user User
* #return User User.
*/
public function store(User $user);
}
The repository:
<?php
namespace MyApp\Domain\Infrastructure\Repository\Users;
use MyApp\Domain\Model\Users\User;
use MyApp\Domain\Infrastructure\Mapper\Users\UserMapper;
use MyApp\Domain\Model\Users\UserCollection as UserCollectionInterface;
/**
* User collection, e.g. user repository.
*/
class UserCollection implements UserCollectionInterface {
private $userMapper;
public function __construct(UserMapper $userMapper) {
$this->userMapper = $userMapper;
}
/**
* Find a user by id.
*
* #param int $id User id.
* #return User|null User.
*/
public function findById(int $id) {
return $this->userMapper->fetchUserById($id);
}
/**
* Find all users.
*
* #return User[] User list.
*/
public function findAll() {
return $this->userMapper->fetchAllUsers();
}
/**
* Check if the given user exists.
*
* #param User $user User
* #return bool True if user exists, false otherwise.
*/
public function exists(User $user) {
return $this->userMapper->userExists($user);
}
/**
* Store a user.
*
* #param User $user User
* #return User User.
*/
public function store(User $user) {
return $this->userMapper->saveUser($user);
}
}
The data mapper interface:
<?php
namespace MyApp\Domain\Infrastructure\Mapper\Users;
use MyApp\Domain\Model\Users\User;
/**
* User mapper.
*/
interface UserMapper {
/**
* Fetch a user by id.
*
* #param int $id User id.
* #return User|null User.
*/
public function fetchUserById(int $id);
/**
* Fetch all users.
*
* #return User[] User list.
*/
public function fetchAllUsers();
/**
* Check if the given user exists.
*
* #param User $user User.
* #return bool True if the user exists, false otherwise.
*/
public function userExists(User $user);
/**
* Save a user.
*
* #param User $user User.
* #return User User.
*/
public function saveUser(User $user);
}
The data mapper:
<?php
namespace MyApp\Domain\Infrastructure\Mapper\Users;
use PDO;
use MyApp\Domain\Model\Users\User;
use MyApp\Domain\Model\Users\Email;
use MyApp\Domain\Model\Users\Password;
use MyApp\Domain\Infrastructure\Mapper\Users\UserMapper;
/**
* PDO user mapper.
*/
class PdoUserMapper implements UserMapper {
/**
* Database connection.
*
* #var PDO
*/
private $connection;
public function __construct(PDO $connection) {
$this->connection = $connection;
}
/**
* Fetch a user by id.
*
* Note: PDOStatement::fetch returns FALSE if no record is found.
*
* #param int $id User id.
* #return User|null User.
*/
public function fetchUserById(int $id) {
$sql = 'SELECT * FROM users WHERE id = :id LIMIT 1';
$statement = $this->connection->prepare($sql);
$statement->execute([
'id' => $id,
]);
$record = $statement->fetch(PDO::FETCH_ASSOC);
return ($record === false) ? null : $this->convertRecordToUser($record);
}
/**
* Fetch all users.
*
* #return User[] User list.
*/
public function fetchAllUsers() {
$sql = 'SELECT * FROM users';
$statement = $this->connection->prepare($sql);
$statement->execute();
$recordset = $statement->fetchAll(PDO::FETCH_ASSOC);
return $this->convertRecordsetToUserList($recordset);
}
/**
* Check if the given user exists.
*
* Note: PDOStatement::fetch returns FALSE if no record is found.
*
* #param User $user User.
* #return bool True if the user exists, false otherwise.
*/
public function userExists(User $user) {
$sql = 'SELECT COUNT(*) as cnt FROM users WHERE username = :username';
$statement = $this->connection->prepare($sql);
$statement->execute([
':username' => $user->getUsername(),
]);
$record = $statement->fetch(PDO::FETCH_ASSOC);
return ($record['cnt'] > 0) ? true : false;
}
/**
* Save a user.
*
* #param User $user User.
* #return User User.
*/
public function saveUser(User $user) {
$id = $user->getId();
if (!isset($id)) {
return $this->insertUser($user);
}
return $this->updateUser($user);
}
/**
* Insert a user.
*
* #param User $user User.
* #return User User.
*/
private function insertUser(User $user) {
$sql = 'INSERT INTO users (
username,
password,
email
) VALUES (
:username,
:password,
:email
)';
$statement = $this->connection->prepare($sql);
$statement->execute([
':username' => $user->getUsername(),
':password' => (string) $user->getPassword(),
':email' => (string) $user->getEmail(),
]);
$user->setId($this->connection->lastInsertId());
return $user;
}
/**
* Update a user.
*
* #param User $user User.
* #return User User.
*/
private function updateUser(User $user) {
$sql = 'UPDATE users
SET
username = :username,
password = :password,
email = :email
WHERE id = :id';
$statement = $this->connection->prepare($sql);
$statement->execute([
':id' => $user->getId(),
':username' => $user->getUsername(),
':password' => (string) $user->getPassword(),
':email' => (string) $user->getEmail(),
]);
return $user;
}
/**
* Convert a record to a user.
*
* #param array $record Record data.
* #return User User.
*/
private function convertRecordToUser(array $record) {
$user = $this->createUser(
$record['id'],
$record['username'],
$record['password'],
$record['email']
);
return $user;
}
/**
* Convert a recordset to a list of users.
*
* #param array $recordset Recordset data.
* #return User[] User list.
*/
private function convertRecordsetToUserList(array $recordset) {
$users = [];
foreach ($recordset as $record) {
$users[] = $this->convertRecordToUser($record);
}
return $users;
}
/**
* Create user.
*
* #param int $id User id.
* #param string $username Username.
* #param string $password Password.
* #param string $email Email.
* #return User User.
*/
private function createUser(int $id, string $username, string $password, string $email) {
$user = new User();
$user
->setId($id)
->setUsername($username)
->setPassword(new Password($password))
->setEmail(new Email($email))
;
return $user;
}
}
Resources:
Keynote: Architecture the Lost Years
Sandro Mancuso : An introduction to interaction-driven design
Unbreakable Domain Models
An older answer of mine, for some explanations.
I have created a timeclock system for a website admin area I am working on. But I want to use a class to handle the code in a better way so I am starting over. So far I have 2 classes. One to handle the database connection and the queries to the database through PDO.
When starting the class for the timeclock (Which I am having to build from scratch) I am getting close because I am no longer receiving errors when I load the page. But the results of the query are not right as I should be returning "true" instead of NULL for a record coming from the database. Can someone please help me understand what I am doing wrong.
My Database class is like so(From GitHub)...
/**
* DB - A simple database class
*
* #author Author: Vivek Wicky Aswal. (https://twitter.com/#!/VivekWickyAswal)
* #git https://github.com/indieteq/PHP-MySQL-PDO-Database-Class
* #version 0.2ab
*
*/
require("Log.class.php");
class DB
{
# #object, The PDO object
private $pdo;
# #object, PDO statement object
private $sQuery;
# #array, The database settings
private $settings;
# #bool , Connected to the database
private $bConnected = false;
# #object, Object for logging exceptions
private $log;
# #array, The parameters of the SQL query
private $parameters;
/**
* Default Constructor
*
* 1. Instantiate Log class.
* 2. Connect to database.
* 3. Creates the parameter array.
*/
public function __construct()
{
$this->log = new Log();
$this->Connect();
$this->parameters = array();
}
/**
* This method makes connection to the database.
*
* 1. Reads the database settings from a ini file.
* 2. Puts the ini content into the settings array.
* 3. Tries to connect to the database.
* 4. If connection failed, exception is displayed and a log file gets created.
*/
private function Connect()
{
$host = 'localhost';
$username = 'root';
$password = '';
$dbname = 'acro_1986';
//$this->settings = parse_ini_file("settings.ini.php");
$dsn = 'mysql:dbname='.$dbname.';host='.$host.'';
try
{
# Read settings from INI file, set UTF8
$this->pdo = new PDO($dsn, $username, $password, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
# We can now log any exceptions on Fatal error.
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
# Disable emulation of prepared statements, use REAL prepared statements instead.
$this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
# Connection succeeded, set the boolean to true.
$this->bConnected = true;
}
catch (PDOException $e)
{
# Write into log
echo $this->ExceptionLog($e->getMessage());
die();
}
}
/*
* You can use this little method if you want to close the PDO connection
*
*/
public function CloseConnection()
{
# Set the PDO object to null to close the connection
# http://www.php.net/manual/en/pdo.connections.php
$this->pdo = null;
}
/**
* Every method which needs to execute a SQL query uses this method.
*
* 1. If not connected, connect to the database.
* 2. Prepare Query.
* 3. Parameterize Query.
* 4. Execute Query.
* 5. On exception : Write Exception into the log + SQL query.
* 6. Reset the Parameters.
*/
private function Init($query,$parameters = "")
{
# Connect to database
if(!$this->bConnected) { $this->Connect(); }
try {
# Prepare query
$this->sQuery = $this->pdo->prepare($query);
# Add parameters to the parameter array
$this->bindMore($parameters);
# Bind parameters
if(!empty($this->parameters)) {
foreach($this->parameters as $param)
{
$parameters = explode("\x7F",$param);
$this->sQuery->bindParam($parameters[0],$parameters[1]);
}
}
# Execute SQL
$this->succes = $this->sQuery->execute();
}
catch(PDOException $e)
{
# Write into log and display Exception
echo $this->ExceptionLog($e->getMessage(), $query );
die();
}
# Reset the parameters
$this->parameters = array();
}
/**
* #void
*
* Add the parameter to the parameter array
* #param string $para
* #param string $value
*/
public function bind($para, $value)
{
$this->parameters[sizeof($this->parameters)] = ":" . $para . "\x7F" . utf8_encode($value);
}
/**
* #void
*
* Add more parameters to the parameter array
* #param array $parray
*/
public function bindMore($parray)
{
if(empty($this->parameters) && is_array($parray)) {
$columns = array_keys($parray);
foreach($columns as $i => &$column) {
$this->bind($column, $parray[$column]);
}
}
}
/**
* If the SQL query contains a SELECT or SHOW statement it returns an array containing all of the result set row
* If the SQL statement is a DELETE, INSERT, or UPDATE statement it returns the number of affected rows
*
* #param string $query
* #param array $params
* #param int $fetchmode
* #return mixed
*/
public function query($query,$params = null, $fetchmode = PDO::FETCH_ASSOC)
{
$query = trim($query);
$this->Init($query,$params);
$rawStatement = explode(" ", $query);
# Which SQL statement is used
$statement = strtolower($rawStatement[0]);
if ($statement === 'select' || $statement === 'show') {
return $this->sQuery->fetchAll($fetchmode);
}
elseif ( $statement === 'insert' || $statement === 'update' || $statement === 'delete' ) {
return $this->sQuery->rowCount();
}
else {
return NULL;
}
}
/**
* Returns the last inserted id.
* #return string
*/
public function lastInsertId() {
return $this->pdo->lastInsertId();
}
/**
* Returns an array which represents a column from the result set
*
* #param string $query
* #param array $params
* #return array
*/
public function column($query,$params = null)
{
$this->Init($query,$params);
$Columns = $this->sQuery->fetchAll(PDO::FETCH_NUM);
$column = null;
foreach($Columns as $cells) {
$column[] = $cells[0];
}
return $column;
}
/**
* Returns an array which represents a row from the result set
*
* #param string $query
* #param array $params
* #param int $fetchmode
* #return array
*/
public function row($query,$params = null,$fetchmode = PDO::FETCH_ASSOC)
{
$this->Init($query,$params);
return $this->sQuery->fetch($fetchmode);
}
/**
* Returns the value of one single field/column
*
* #param string $query
* #param array $params
* #return string
*/
public function single($query,$params = null)
{
$this->Init($query,$params);
return $this->sQuery->fetchColumn();
}
/**
* Writes the log and returns the exception
*
* #param string $message
* #param string $sql
* #return string
*/
private function ExceptionLog($message , $sql = "")
{
$exception = 'Unhandled Exception. <br />';
$exception .= $message;
$exception .= "<br /> You can find the error back in the log.";
if(!empty($sql)) {
# Add the Raw SQL to the Log
$message .= "\r\nRaw SQL : " . $sql;
}
# Write into log
$this->log->write($message);
return $exception;
}
}
My Timeclock class...
class Timeclock {
public $user_id;
public function __construct($user_id) {
$this->user_id = $user_id ;
$this->db = new Db();
//$this->clocked_in = is_user_clocked_in($user_id);
}
public function is_user_clocked_in(){
$result = $this->db->query("SELECT * FROM timeclock WHERE user_id = :user_id AND time_out IS NULL", array("user_id"=>$this->user_id));
if ( count ( $result ) > 0 ){
return $result[0];
}else{
return null;
}
}
}
And I am calling it like so...
if (isset($_SESSION['admin'])) {
$_user_id = $_SESSION['admin'][0]['user_id'];
// calls action and determines case
if (isset($_POST['action'])) {
$action = $_POST['action'];
} else if (isset($_GET['action'])) {
$action = $_GET['action'];
} else {
$action = 'home';
}
$action = strtolower($action);
switch ($action) {
case 'home':
$timeclock = new Timeclock($_user_id);
$user = new Timeclock($timeclock->user_id);
$clocked_in = $user->is_user_clocked_in();
include ('dashboard.php');
break;
}
}
Also, is it possible to have every function in the class (Once its done) run one after the other and fill in the declared variables at the top (Once I have added them of course) so I can just call the class and have it run through once? Or will I have to call each function individually on demand?
Thanks for the attempt to help #Ohgodwhy. $clocked_in was returning an array because I asked it to select all columns in the table. So when there was a result, it was an array. I changed the return of the function to return true instead of $result[0] because I only need to know if the user is logged in. I could have probably just changed the query to select that column as well. After doing that, it worked great until I provided a value for the table field (Making the user clocked_in). I then got a Undefined offset:0 error because I was trying to call the value of $result[0] when there was no array indexed because the query obviously returns array(0); I just changed the count to check to see if $result exists.
updated code is as follows in case someone comes across this
Timeclock Class
class Timeclock {
public $user_id;
public function __construct($user_id) {
$this->user_id = $user_id ;
$this->db = new Db();
//$this->clocked_in = is_user_clocked_in($user_id);
}
public function is_user_clocked_in(){
$result = $this->db->query("SELECT * FROM timeclock WHERE user_id = :user_id AND time_out IS NULL", array("user_id"=>$this->user_id));
if ( count ($result) > 0 ){
return true;
}else{
return null;
}
}
}
I installed open cart on my local server, but it is displaying a message at top.
Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in D:\new\htdocs\business\system\database\mysql.php on line 6
How can I fix it ?
This error is because you're using PHP 5.5 or above. The best solution to this is to not suppress errors as others have said (since that prevents you seeing errors from other issues) but to install a mysqli extension/PDO extension for OpenCart. This one is free and works well - it's the one I use
I am using opencart-1.5.6.1.zip on ApacheFriends XAMPP Version 1.8.3 and I see this error message on every page too.
Open opencart/config.php and opencart/admin/config.php.
Edit 'mysql' -> 'mysqli'
e.g.
//define('DB_DRIVER', 'mysql');
define('DB_DRIVER', 'mysqli');
Save the files and no need to restart anything. The error message is gone.
below is the code for PDO in opencart 1.5.6 or <
<?php
/**
* Class for working with database (PDO)
*
* #property \PDO $dbh
*
* #author WebImperia Dev
* #since 0.0.1
*/
final class OC_PDO
{
/**
* Link to the database connection
*
* #var \PDO
*/
private $dbh;
/**
* List of connection settings
*
* #var array
*/
private $options = array(
'PDO::ATTR_ERRMODE' => PDO::ERRMODE_SILENT
);
/**
* The number of rows affected by the last operation
*
* #var int
*/
private $affectedRows = 0;
/**
* The data for the database connection
*
* #var \stdClass
*/
private $params = array();
/**
* Sets the connection and connects to the database
*
* #param string $host server Address
* #param string $user Username
* #param string $pass Password
* #param string $name The database name
* #param string $charset Encoding connection
*/
public function __construct($host, $user, $pass, $name, $charset = 'utf8')
{
$this->params = new stdClass;
# keep connection data
$this->params->host = $host;
$this->params->user = $user;
$this->params->pass = $pass;
$this->params->name = $name;
$this->params->charset = $charset;
$this->params->connstr = "mysql:host={$host};dbname={$name};charset={$charset}";
# add the connection parameters
$this->options['PDO::MYSQL_ATTR_INIT_COMMAND'] = "SET NAMES '{$charset}'";
$this->connect();
}
/**
* Connect to database
*/
public function connect()
{
try {
$this->dbh = new PDO($this->params->connstr, $this->params->user, $this->params->pass, $this->options);
if (version_compare(PHP_VERSION, '5.3.6', '<=')) {
$this->dbh->exec($this->options['PDO::MYSQL_ATTR_INIT_COMMAND']);
}
} catch (PDOException $exception) {
trigger_error($exception->getMessage());
}
}
/**
* Query the database
*
* #param string $sql
* #return \stdClass
*/
public function query($sql = null)
{
if ($this->dbh) {
$data = new stdClass;
$sth=$this->dbh->prepare($sql);
$sth->execute();
//$sth= $this->dbh->query($sql);
$this->affectedRows = $sth->rowCount();
$data->rows = $sth ? $sth->fetchAll() : array();
$data->row = isset($data->rows[0]) ? $data->rows[0] : null;
$data->num_rows = $this->affectedRows;
return $data;
}
return null;
}
/**
* Concludes the string in quotation marks to be used in the query
*
* #param mixed $string shielded line
* #return string Returns shielded line or to FALSE , if the driver does not support screening
*/
public function escape($string = null)
{
return $this->dbh ? $this->dbh->quote($string) : null;
}
/**
* Gets the number of rows affected by the last operation
*
* #return int
*/
public function countAffected()
{
return $this->affectedRows;
}
/**
* Gets the ID of the last inserted row or sequence of values
*
* #return int
*/
public function getLastId()
{
return $this->dbh ? $this->dbh->lastInsertId() : 0;
}
/**
* Gets the name of the driver
*
* #return string|null
*/
public function getDriverName()
{
return $this->dbh ? $this->dbh->getAttribute(PDO::ATTR_DRIVER_NAME) : null;
}
/**
* Get information about the version of the client libraries that are used by the PDO driver
*
* #return string|null
*/
public function getVersion()
{
return $this->dbh ? $this->dbh->getAttribute(PDO::ATTR_CLIENT_VERSION) : null;
}
/**
* Closing a database connection
*/
public function close()
{
$this->dbh = null;
}
public function __destruct()
{
$this->close();
}
}
How can I make a singleton of the PDO extention? Extending doesn't work, because I get a fatal error when I try it ...
You don't need a Singleton.
But to answer this nevertheless:
You cannot turn a public visibility to a stricter visibility. So PDO cannot have the constructor's visibility changed to anything but public. So you need to wrap the PDO instance into a Singleton:
class MyPdo
{
/**
* #var MyPdo
*/
protected static $_instance;
/**
* #var Pdo
*/
protected $_pdo;
/**
* Creates instance and returns it on subsequent calls
*
* #throws InvalidArgumentException
* #param array $options PDO connection data
* #returns MyPdo
*/
public static function getInstance(array $options = NULL)
{
if(self::$_instance === NULL) {
if($options === NULL) {
throw new InvalidArgumentException(
'You must supply connection options on first run');
}
// call constructor with given options and assign instance
self::$_instance = new self(
$options['dsn'],
$options['user'],
$options['password'],
$options['driver_options']
);
}
return self::$_instance;
}
/**
* Creates new MyPdo wrapping a PDO instance
*
* #throws PDOException
* #param String $dsn
* #param String $user
* #param String $password
* #param Array $driver_options
* #return void
*/
private function __construct($dsn, $user, $password, $driver_options)
{
try {
$this->_pdo = new PDO($dsn, $user, $password, $driver_options);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
}
/**
* Singletons may not be cloned
*/
private function __clone() {}
/**
* Delegate every get to PDO instance
*
* #param String $name
* #return Mixed
*/
public function __get($name)
{
return $this->_pdo->$name;
}
/**
* Delegate every set to PDO instance
*
* #param String $name
* #param Mixed $val
* #return Mixed
*/
public function __set($name, $val)
{
return $this->_pdo->$name = $val;
}
/**
* Delegate every method call to PDO instance
*
* #param String $method
* #param Array $args
* #return Mixed
*/
public function __call($method, $args) {
return call_user_func_array(array($this->_pdo, $method), $args);
}
}
You'd use it like this:
$db = MyPdo::getInstance(array(
'dsn'=>'mysql:dbname=mysql;host=127.0.0.1',
'user' => 'root',
'password' => 'minnymickydaisydonaldplutogoofysanfrancisco',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"
)));
$version = $db->query( 'SELECT version();' );
echo $version->fetchColumn();
// remove reference to instance
unset($db);
// doesn't require connection data now as it returns same instance again
$db = MyPdo::getInstance();
$version = $db->query( 'SELECT version();' );
echo $version->fetch();