I'm trying to access the same method twice without having to create the object twice. I made this code
<?php
class help{
public $cn;
public function __construct(){
require_once 'connection.php';
$this->cn = $c;// now $ cn brings the DB connection
}
public function executeQuery( $q ){
self::__construct(); /*I added it because according to I was trying to
invoke again the method without creating a
previous object, if I take it off, it marks me as
if there was no $ cn*/
header('Content-Type: application/json');
date_default_timezone_set('America/Mexico_City');
mysqli_set_charset($this->cn, "utf8");
return mysqli_query( $this->cn, $q );
}
}
$h = new help();
$q = "INSERT INTO FOOBAR (foo_id, bar_id) VALUES('foo','bar')";//new record
$r = $h->executeQuery( $q );//I will do something with $r
$q = "SELECT * FROM FOOBAR";//I retrive all records but the query fails
echo $h->executeQuery( json_encode( $q ) );;
?>
Now, the object does not have a constructor, and if it does not pass the self :: __ construct (); Send me that $ cn is not declared.
How do I solve it? Will I have to create two objects?
Thank you
EDIT
This is my connection.
<?php
global $c;
$c = mysqli_connect("localhost","foo","bar","myDB");
if (mysqli_connect_errno()){
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
?>
You're doing a require_once() call, which is your problem. You will not re-include the file the second time it's called, but being that you're not pulling a global variable, whatever was returned from the first include is not available to you the second time around.
If it's okay to include the file multiple times, you can make the require_once a plain require and that will set your variable as you are expecting.
Related
So I have the following php-script test.php:
<?php
class Database {
public $databaseConnection;
function __construct(){
$this->databaseConnection = new PDO('sqlite:test.sq3', 0, 0);
$this->databaseConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
self::query('CREATE TABLE...');
}
function query($sql, $params = NULL){
...
}
function insert($table, $data){
...
}
}
$database = new Database();
$database->insert(...);//insert something into Database
$userData = $database->query(...);//getting $userData after query
$username = $userData;
print_r($username);
$database = null;
unlink('test.sq3');
So everythings working fine until the last line.
Permission denied in F:\...\test.php on line 75
I already looked up following things in the documentation:
Instruction separation:
http://php.net/manual/en/language.basic-syntax.instruction-separation.php
Connections and Connection management (of PDO-objects):
http://php.net/manual/en/pdo.connections.php
So to end the connection of a PDO-ocject to the database it has to set = null.
After that I tried:
unset($database);
Permission denied. So I made an extern file delete.php:
<?php unlink('test.sq3'); ?>
This script is working. So I can delete the file in another script.
And the last thing I tried (with =null and unset()):
include('delete.php');
Which did not work neither. But the main thing about is that I don´t have a clue why I can´t delete the file in the same script.
So how can I delete the database-file in the same script?
So now I find out whats wrong. In the method query which looked like:
function query($sql, $params = NULL){
$s = $this->databaseConnection->prepare($sql);
if(is_array($params)){
$s->execute(array_values($params));
return $s;
}
$s->execute((array) $params);
return $s;
}
As you can see there is no fetch()-statement, because I wanted to try out whats happen without it. So you get an Output just like:
PDOStatement Object ( [queryString] => SELECT username FROM user WHERE numberoflogins = ? )
I skipped it because I thought it wasn´t really necessary when it works.
Well, atleast I don´t have a clue whats this PDO method has something todo with the end of my script because I unset every variable which has something todo with the PDO object but the point is that now he deletes the file.
I've hunted for an answer to this, but still can't explain the inconsistency i'm experiencing. Heregoes...
I'm writing a simple CMS in PHP and cannot understand how I can directly reference external variables from one require call but not another
1. Here's my Db_Conn.php script.
<?php
if(!class_exists('Db_Conn')){
class Db_Conn{
var $pdo;
public function __construct(){
$init_array = parse_ini_file('conf.ini');
try{
$this->pdo = new PDO('mysql:host=' . $init_array['host'] . ';dbname=' . $init_array['database'], $init_array['user'], $init_array['password']);
} catch(PDOException $ex){
exit('Database Error!');
}
}
}
$db_conn = new Db_Conn();
}
?>
2. Here's my simplified article_manager script, that requires the previous DB connection script.
<?php
require_once('class-db_conn.php');
if(!class_exists('Article_Manager')){
class Article_Manager{
public function fetch_article($article_id){
global $db_conn;
$query = $db_conn->pdo->prepare("SELECT * FROM articles WHERE article_id = ?");
$query->bindValue(1, $article_id);
$query->execute();
return $query->fetch();
}
}
$article_manager = new Article_Manager();
}
?>
In this script I can only reference the $db_conn variable is via the global keyword. This makes sense and there are plenty of threads about avoiding globals.
But here's my confusion. Here's a third script that requires the article_manager.
<?php
require_once('includes/class-article_manager.php');
if (!isset($_GET['id'])){
//no page set, back to index
header('Location: index.php');
exit();
} else {
$id = $_GET['id'];
$selected_article = $article_manager->fetch_article($id);
//...some code left out
?>
When I require the article_manager script I DONT have to use global. I can simply call the functions of the $article_manager variable without global referencing.
Could someone please tell me what is going on here? Why don't I have to use global in the second example. I realise the use of globals is discouraged, so I was hoping I could use an alternative method to keep my code encapsulated and.
Article_Manager needs to use global because it's calling $db_conn within the fetch_article function which has it's own scope.
In your second example you're just calling $article_manager within an if statement, presumably already in the global / main scope.
The general idea is that when you want to access variables from within a function they either need to be passed in as an argument or, in this case, a global variable.
This is code I saw for another question.
function oracleGetGata($query, $id="id") {
global $conn;
$results = array();
$sql = OCI_Parse($conn, $query);
OCI_Execute($sql);
while ( false!==($row=oci_fetch_assoc($sql)) ) {
$results[ $row[$id] ] = $row;
}
return $results;
}
My question is how does this make the connection to Oracle and then call it inside this function? Because I can see global $conn but I don't know where that is coming from.
My problem is that I have an onChange function on an input box. When the value is changed it needs to call a function which connects to Oracle and checks if value is valid, and echo VALID if it is.
The global $conn; imports into oracleGetGata() a global variable named $conn which is almost certainly the database connection, created somewhere outside the scope of the function.
I have a function that creates a course. I am trying to get the Last Insert ID but it doesn't work:
public function createCourse()
{
require "/mysqli_connect.php";
$course_q = "INSERT INTO course (....) VALUES (.....)";
$course_r = mysqli_query($mysqli, $course_q);
$course_n = mysqli_affected_rows($mysqli);
if($course_n == 1)
{
mysqli_close($mysqli);
return true;
}
mysqli_close($mysqli);
return false;
}
This is the function to retrieve the last insert ID that I created in the same class as the function createCourse:
public function getLastInsertID()
{
require "/../mysqli_connect.php";
$course_q= "SELECT LAST_INSERT_ID()";
$course_r = mysqli_query($mysqli, $course_q);
$course_n = mysqli_num_rows($course_r);
//var_dump($course_n);
if($course_n)
{
$c = mysqli_fetch_assoc($course_r);
mysqli_close($mysqli);
return $c;
}
mysqli_close($mysqli);
return NULL;
}
This is how I call the functions:
require "/mysqli_connect.php";
$course = new Course();
$c = $course->createCourse();
$id = $course->getLastInsertID();
var_dump($id);
"$id" is always "int(0)"
I've also tried:
require "/mysqli_connect.php";
$course = new Course();
$c = $course->createCourse();
**$id = mysqli_insert_id($mysqli);**
and I've also tried:
$course_q= "SELECT LAST_INSERT_ID() from course";
but that doesn't work as well. Can you guys see what the problem is? :( The function createCourse itself is fine. It creates what I need and it's there in the database but I can't get the last insert id.
Although the proper way to retrieve the insert id with MySQLi is to use mysqli_insert_id(), since you're doing an associative fetch, you would need a column alias for the LAST_INSERT_ID()
$course_q= "SELECT LAST_INSERT_ID() AS insert_id";
// Later...
$c = mysqli_fetch_assoc($course_r);
echo $c['insert_id'];
However, that isn't going to work because you have already closed the connection with mysqli_close() in your createCourse() function. Instead, get the insert id inside createCourse() and return it.
public function createCourse()
{
// Note: You should not establish the connection in each function call.
// it only needs to be done once per script, and you can pass the connection
// into the class constructor or into methods that use it.
require "/mysqli_connect.php";
$course_q = "INSERT INTO course (....) VALUES (.....)";
$course_r = mysqli_query($mysqli, $course_q);
$course_n = mysqli_affected_rows($mysqli);
if($course_n == 1)
{
// Get the insert id before closing the connection
$insert_id = mysqli_insert_id($mysqli);
// Note that there probably isn't a good reason to explicitly close the
// connection here. It will be closed when the script terminates.
mysqli_close($mysqli);
// And return it.
return $insert_id;
}
mysqli_close($mysqli);
return false;
}
require "/mysqli_connect.php";
$course = new Course();
$c = $course->createCourse();
echo $c;
// $c contains the id
Design classes to use one common connection:
The class receives a connection in its constructor.
// Make classes accept the connection as a param:
class MyClass
{
// property to hold the connection object
public $db;
// constructor receives the connection
public function __construct($connection) {
$this->db = $connection;
}
// Methods call it as $this->db
public function createCourse() {
$course_r = mysqli_query($this->db, $course_q);
}
}
Include the connection only once on the controlling script
require_once("/mysqli_connect.php");
// $mysqli is now defined...
// Pass it into the constructor
$course = new MyClass($mysqli);
The issue is you have multiple connections to the database, and last inserted ID is tracked on a per-connection basis.
Note: You should not connect to the same database every time you run a query. Simply connect at the beginning of the script, and close at the end. Connecting and disconnecting constantly will cause your script to run extremely slowly, especially with more queries.
Also, the last inserted ID is available via MySQLi's mysqli_insert_id() function.
Most likely because you're closing the mysqli connection at the end of createCourse().
Either don't make createCourse() responsible for closing the connection (move it elsewhere) or have createCourse() return the insert ID on success (or false on failure)
I have a html page that calls a php object to get some data back from the database. It works fine, but the script was getting unwieldy so I decided to break some of it out into a bunch of functions.
So I have the following files:
// htdocs/map.php
<?php
include("config.php");
include("rmap.php");
$id = 1;
$gamenumber = getGameNumber($id);
echo $gamenumber;
?>
// htdocs/config.php
<?php
$_PATHS["base"] = dirname(dirname(__FILE__)) . "\\";
$_PATHS["includes"] = $_PATHS["base"] . "includes\\";
ini_set("include_path", "$_PATHS[includes]");
ini_set("display_errors", "1");
error_reporting(E_ALL);
include("prepend.php");
?>
// includes/prepend.php
<?php
include("session.php");
?>
// includes/session.php
<?php
includes("database.php");
class Session {
function Session() {
}
};
$session = new Session;
?>
// includes/database.php
<?php
include("constants.php");
class Database {
var $connection;
function Database() {
$this->connection = mysql_connect(DB_SERVER, DB_USER, DB_PASS) or die(mysql_error());
mysql_select_db(DB_NAME, $this->connection) or die(mysql_error());
}
function query($query) {
return mysql_query($query, $this->connection);
}
};
/* Create database connection */
$database = new Database;
?>
// includes/rmap.php
<?php
function getGameNumber($id) {
$query = "SELECT gamenumber FROM account_data WHERE usernum=$id";
$result = $database->query($query); // line 5
return mysql_result($result, 0);
}
?>
And constants has a bunch of defines in it (DB_USER, etc).
So, map.php includes config.php. That in turn includes prepend.php which includes session.php and that includes database.php. map.php also includes rmap.php which tries to use the database object.
The problem is I get a
Fatal error: Call to a member function on a non-object in
C:\Develop\map\includes\rmap.php on line 5
The usual cause of this is that the $database object isn't created/initialised, but if I add code to show which gets called when (via echo "DB connection created"; and echo "using DB connection";) they are called (or at least displayed) in the correct order.
If I add include("database.php") to rmap.php I get errors about redefining the stuff in constants.php. If I use require_once I get the same errors as before.
What am I doing wrong here?
$database is not in the scope of function GetGameNumber.
The easiest, though not necessarily best, solution is
<?php
function getGameNumber($id) {
global $database; // added this
$query = "SELECT gamenumber FROM account_data WHERE usernum=$id";
$result = $database->query($query); // line 5
return mysql_result($result, 0);
}
?>
global is deemed not perfect because it violates the principles of OOP, and is said to have some impact on performance because a global variable and all its members are added to the function's scope. I don't know how much that really affects performance, though.
If you want to get into the issue, I asked a question on how to organize such things a while back and got some good answers and links.
You need to include
global $database;
at the top of getGameNumber(), since $database is defined outside of getGameNumber itself
Your $database varibleis not accessible from the function's scope automatically. You might need to declare it as global $database; in the function.
Scopes in PHP are explained in the documentation: http://de3.php.net/manual/en/language.variables.scope.php
Please also mind that PHP 4and MySQL3 are out of support for a looooong time and might contain security problems and other unfixed issues.