I'm new to using SOAP and understanding the utmost basics of it.
I create a client resource/connection, I then run some queries in a loop and I'm done. The issue I am having is when I increase the iterations of the loop, ie: from 100 to 1000, it seems to run out of memory and drops an internal server error.
How could I possibly run either a) multiple simaltaneous connections or b) create a connection, 100 iterations, close connection, create connection.. etc.
"a)" looks to be the better option but I have no clue as to how to get it up and running whilst keeping memory (I assume opening and closing connections) at a minimum.
Thanks in advance!
index.php
<?php
// set loops to 0
$loops = 0;
// connection credentials and settings
$location = 'https://theconsole.com/';
$wsdl = $location.'?wsdl';
$username = 'user';
$password = 'pass';
// include the console and client classes
include "class_console.php";
include "class_client.php";
// create a client resource / connection
$client = new Client($location, $wsdl, $username, $password);
while ($loops <= 100)
{
$dostuff;
}
?>
class_console.php
<?php
class Console {
// the connection resource
private $connection = NULL;
/**
* When this object is instantiated a connection will be made to the console
*/
public function __construct($location, $wsdl, $username, $password, $proxyHost = NULL, $proxyPort = NULL) {
if(is_null($proxyHost) || is_null($proxyPort)) $connection = new SoapClient($wsdl, array('login' => $username, 'password' => $password));
else $connection = new SoapClient($wsdl, array('login' => $username, 'password' => $password, 'proxy_host' => $proxyHost, 'proxy_port' => $proxyPort));
$connection->__setLocation($location);
$this->connection = $connection;
return $this->connection;
}
/**
* Will print any type of data to screen, where supported by print_r
*
* #param $var - The data to print to screen
* #return $this->connection - The connection resource
**/
public function screen($var) {
print '<pre>';
print_r($var);
print '</pre>';
return $this->connection;
}
/**
* Returns a server / connection resource
*
* #return $this->connection - The connection resource
*/
public function srv() {
return $this->connection;
}
}
?>
Well, SOAP in PHP is a little problematic.
About your question: yes, SOAP accept simultaneous connections. You believe in a "out of memory". I believe that the major problem is around HTTP responses/per second.
Can you put here your apache error log ? - assuming that you uses PHP and Apache together in your environment.
Anyway, my advice for you is: use REST if you can !
Solved
It was a timeout issue.
Related
I have a php web site with a SQLite database. This code opens and queries the database without error:
use App\SQLiteConnection;
$pdo = (new SQLiteConnection())->connect();
$pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$stmt = $pdo->query("SELECT empid, fullname FROM employees ORDER BY fullname");
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
$employees[] = [
'empid' => $row['empid'],
'fullname' => $row['fullname']
];
}
This code here:
use App\SQLiteConnection;
$pdo = (new SQLiteConnection())->connect();
$pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$training_id = $_POST['id'];
$stmt = $pdo->prepare("SELECT description from training WHERE id = :training_id");
$stmt->bindParam(':training_id', $training_id);
$stmt->execute();
echo $stmt->fetchColumn();
gets an error of:
Fatal error: Uncaught PDOException: SQLSTATE[HY000] [14] unable to
open database file in
C:\Bitnami\wampstack-7.3.10-0\apache2\htdocs\arborcircle\app\SQLiteConnection.php:23
Stack trace: 0
C:\Bitnami\wampstack-7.3.10-0\apache2\htdocs\arborcircle\app\SQLiteConnection.php(23):
PDO->__construct('sqlite:db/EmpTr...') 1
C:\Bitnami\wampstack-7.3.10-0\apache2\htdocs\arborcircle\functions\get_training_description.php(10):
App\SQLiteConnection->connect() 2 {main} thrown in
C:\Bitnami\wampstack-7.3.10-0\apache2\htdocs\arborcircle\app\SQLiteConnection.php
on line 23
Here is my SQLiteConnection class:
class SQLiteConnection {
/**
* PDO instance
* #var type
*/
private $pdo;
/**
* return in instance of the PDO object that connects to the SQLite database
* #return \PDO
*/
public function connect() {
if ($this->pdo == null) {
$this->pdo = new \PDO("sqlite:" . Config::PATH_TO_DB_FILE);
}
return $this->pdo;
}
}
Both of the examples of how I am querying the database seems similar to me, but I cannot see why the 2nd example is throwing an error of opening the same database.
Any help appreciated.
Information to consider:
SQLite uses reader/writer locks on the entire database file. That means if any process is reading from any part of the database, all other processes are prevented from writing any other part of the database. Similarly, if any one process is writing to the database, all other processes are prevented from reading any other part of the database. For many situations, this is not a problem. Each application does its database work quickly and moves on, and no lock lasts for more than a few dozen milliseconds. But there are some applications that require more concurrency, and those applications may need to seek a different solution.
Also try to add PDO::ATTR_PERSISTENT => true in your SQLiteConnection class:
public function connect() {
if ($this->pdo == null) {
$this->pdo = new \PDO(
"sqlite:" . Config::PATH_TO_DB_FILE, '', '',
array(
PDO::ATTR_PERSISTENT => true
)
);
}
return $this->pdo;
}
I've been struggling with this for quite a while, and it's to the point where I need to ask for help because even with all the research I've done I can't get a handle on why this is happening.
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000] [1040] Too many connections'
This happens upon loading a single page (index.php), and I am the only user (dev). As you can see here, the MySQL connection limit is set # 50 but I am narrowly surpassing that. This is an improvement over the 100~ connections that were being created before I refactored the code.
Here are the stats after the page has loaded once.
I've narrowed the issue down to several causes:
I don't fully understand how PDO/MySQL connections work.
I am creating too many connections in my code even though I am trying to only create one that I can share.
I need to increase the connection limit (seems unlikely).
Most of the SO questions I've found, tell the OP to increase the connection limit without truly knowing if that's the best solution so I'm trying to avoid that here if it's not needed. 50 connections for one page load seems like way too many.
These are the classes I am instantiating on the page in question.
$DataAccess = new \App\Utility\DataAccess();
$DataCopyController = new App\Controllers\DataCopyController($DataAccess);
$DriveController = new App\Controllers\DriveController($DataAccess);
$Helper = new App\Utility\Helper();
$View = new App\Views\View();
I am creating the DAL object then injecting it into the classes that need it. By doing it this way I was hoping to only create one object and one connection, however this is not what's happening obviously. Inside the DAL class I've also added $this->DbConnect->close() to each and every query method.
Here is the constructor for the DataAccess() class.
public function __construct() {
$this->DbConnect = new \App\Services\DbConnect();
$this->db = $this->DbConnect->connect("read");
$this->dbmod = $this->DbConnect->connect("write");
$this->Helper = new Helper();
}
Here is the DbConnect() class.
class DbConnect {
private $db;
private $dbmod;
private function isConnected($connection) {
return ($connection) ? TRUE : FALSE;
}
public function connect($access) {
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
];
if ($access == "read") {
if ($this->isConnected($this->db)) {
return $this->db;
} else {
if (strpos($_SERVER['SERVER_NAME'], DBNAME_DEV) === false) {
$this->db = new PDO("mysql:host=127.0.0.1; dbname=".DBNAME,
DBUSER,
DBPASS,
$options
);
} else {
$this->db = new PDO("mysql:host=" . DBHOST_DEV ."; dbname=".DBNAME_DEV,
DBUSER,
DBPASS,
$options
);
}
return $this->db;
}
} elseif ($access == "write") {
if ($this->isConnected($this->dbmod)) {
return $this->dbmod;
} else {
if (strpos($_SERVER['SERVER_NAME'], DBNAME_DEV) === false) {
$this->dbmod = new PDO("mysql:host=127.0.0.1; dbname=".DBNAME,
DBUSER_MOD,
DBPASS,
$options
);
} else {
$this->dbmod = new PDO("mysql:host=" . DBHOST_DEV . "; dbname=".DBNAME_DEV,
DBUSER_MOD,
DBPASS,
$options
);
}
}
return $this->dbmod;
}
}
public function close() {
$this->db = null;
$this->dbmod = null;
}
}
I've also tried instantiating the DbConnect() class on index.php and injecting that rather than DataAccess() but the result was the same.
EDIT:
I also want to add that this MySQL server has two databases, prod and dev. I suppose the connection limit is shared between both. However, the prod database gets very little traffic and I am not seeing this error there. When I refreshed the stats, there were no connections to the prod database.
From the PHP manual ~ http://php.net/manual/en/pdo.connections.php
Many web applications will benefit from making persistent connections to database servers. Persistent connections are not closed at the end of the script, but are cached and re-used when another script requests a connection using the same credentials.
So I would advise removing the DbConnection#close() method as you would not want to ever call this.
Also from the manual...
Note:
If you wish to use persistent connections, you must set PDO::ATTR_PERSISTENT in the array of driver options passed to the PDO constructor. If setting this attribute with PDO::setAttribute() after instantiation of the object, the driver will not use persistent connections.
So you'll want (at least)
new \PDO("mysql:host=127.0.0.1;dbname=" . DBNAME, DBUSER, DBPASS, [
PDO::ATTR_PERSISTENT => true
]);
You can also set your other connection attributes in the constructor.
I'm a .Net developer that have taken over a PHP project. This project has a database layer that looks like this:
<?php
class DatabaseManager {
private static $connection;
const host = "projectname.mysql.hostname.se";
const database = "databaseName";
const username = "userName";
const password = "password";
public function __construct()
{
}
public function instance($_host = null, $_username = null, $_password = null)
{
if(!self::$connection)
{
if(!$_host || !$_username || !$_password)
{
$host = self::host;
$username = self::username;
$password = self::password;
}else{
$host = $_host;
$username = $_username;
$password = $_password;
}
self::$connection = mysql_connect($host, $username, $password);
$this->setDatabase();
}
return self::$connection;
}
public function setDatabase($_database = null)
{
if(!$_database)
{
$database = self::database;
}else{
$database = $_database;
}
$connection = $this->instance();
mysql_select_db($database, $connection) or die(mysql_error());
}
} ?>
I have written a php file that uses this layer but after a while i got these mysql errors implying i didn't close my connections which i hadn't. I try to close them but know i get other weird errors like system error: 111. Very simplyfied my php file looks like this:
<?php
$return = new stdClass();
$uid = '9999999999999';
$return->{"myUid"} = $uid;
$dm = new DatabaseManager();
$dmInstance = $dm->instance();
/* MY CLICKS */
$sql = sprintf("SELECT count(*) as myClicks FROM clicks2011, users2011 WHERE clicks2011.uid = users2011.uid AND users2011.uid = %s AND DATEDIFF(DATE(at), '%s') = 0 AND exclude = 0", mysql_real_escape_string($uid), mysql_real_escape_string($selectedDay));
$result = mysql_query($sql, $dmInstance) or die (mysql_error());
$dbResult = mysql_fetch_row($result);
$return->{"myClicks"} = $dbResult[0];
mysql_close($dmInstance);
echo json_encode($return); ?>
Okay, I'm going to post this as an answer because I think one (possibly both) of these things will help you.
First: You don't need to manually close your MySQL connections. Unless you have set them up so that they persist, they will close automatically. I would avoid doing that unless you determine that every other problem is NOT the solution.
In addition, I would switch to using prepared statements. It's more secure, and pretty future-proof. I prefer PHP's PDO over mysqli, but that's up to you.
If you'd like to look over an example of a simple PDO object to take the many lines out of creating prepared statements and connections and getting results, you can look at my homebrew solution.
Second: "System Error 111" is a MySQL error. From what I've read, it appears that this error typically occurs when you are using PHP and MySQL on the same server, but telling PHP to connect to MySQL via an IP address. Switch your $host variable to 'localhost'. It is likely that this will solve that error.
The problem here is you're calling mysql_close and not specifying a valid mysql connection resource object. You're, instead, trying to close an instance of the DatabaseManager object.
You'll probably want to run mysql_close(DatabaseManager::connection); which is where the DatabaseManager is storing the resource object.
Additionally, I'd personally recommend you learn PDO or use the mysqli drivers. In future releases of PHP the built in mysql functions will be moved into E_DEPRECATED
Try implement __destrcut
public function __destruct()
{
mysql_close(self::$connection)
}
Then simply use unset($dm);
Hey guys I have a connection class I found for pdo. I am calling the connection method on the page that the file is included on. The problem is that within functions the $conn variable is not defined even though I stated the method was public, and I was wondering if anyone had an elegant solution other then using global in every function. Any suggestions are greatly appreciated.
CONNECTION
class PDOConnectionFactory{
// receives the connection
public $con = null;
// swich database?
public $dbType = "mysql";
// connection parameters
// when it will not be necessary leaves blank only with the double quotations marks ""
public $host = "localhost";
public $user = "user";
public $senha = "password";
public $db = "database";
// arrow the persistence of the connection
public $persistent = false;
// new PDOConnectionFactory( true ) <--- persistent connection
// new PDOConnectionFactory() <--- no persistent connection
public function PDOConnectionFactory( $persistent=false ){
// it verifies the persistence of the connection
if( $persistent != false){ $this->persistent = true; }
}
public function getConnection(){
try{
// it carries through the connection
$this->con = new PDO($this->dbType.":host=".$this->host.";dbname=".$this->db, $this->user, $this->senha,
array( PDO::ATTR_PERSISTENT => $this->persistent ) );
// carried through successfully, it returns connected
return $this->con;
// in case that an error occurs, it returns the error;
}catch ( PDOException $ex ){ echo "We are currently experiencing technical difficulties. We have a bunch of monkies working really hard to fix the problem. Check back soon: ".$ex->getMessage(); }
}
// close connection
public function Close(){
if( $this->con != null )
$this->con = null;
}
}
PAGE USED ON
include("includes/connection.php");
$db = new PDOConnectionFactory();
$conn = $db->getConnection();
function test(){
try{
$sql = 'SELECT * FROM topic';
$stmt = $conn->prepare($sql);
$result=$stmt->execute();
}
catch(PDOException $e){ echo $e->getMessage(); }
}
test();
You can declarate database class where you carrying conn pdo class, then you don't must duplicates instaces of this. And all database operations you can doing by this class. I mean my answer is what you searching.
But i see, you using only PDO hadle class in Product Factory pattern. You can use normal full database support class under PDO (includes queryies execution from one function) and without this design pattern when you don't want to use many database connectors engines.
I have an application in which I want to authenticate a user from a first database & manage other activities from another database.
I have created two classes. An object of the classes is defined in a file:
$objdb1=new db1(),$objdb2=new db2();
But when I try to call $objdb1->fn(). It searches from the $objdb2 & is showing table1 doesnot exists?
My first file database.php
class database
{
private $hostname;
private $database;
private $username;
private $password;
private $dblinkid;
function __construct()
{
if($_SERVER['SERVER_NAME'] == 'localhost')
{
$this->hostname = "localhost";
$this->database = "aaaa";
$this->username = "xxx";
$this->password = "";
}
else
{
$this->hostname = "localhost";
$this->database = "xxx";
$this->username = "xxx";
$this->password = "xxx";
}
$this->dblinkid = $this->connect();
}
protected function connect()
{
$linkid = mysql_connect($this->hostname, $this->username, $this->password) or die("Could not Connect ".mysql_errno($linkid));
mysql_select_db($this->database, $linkid) or die("Could not select database ".mysql_errno($linkid)) ;
return $linkid;
}
Similarly second file
class database2
{
private $vhostname;
private $vdatabase;
private $vusername;
private $vpassword;
private $vdblinkid;
function __construct()
{
if($_SERVER['SERVER_NAME'] == 'localhost')
{
$this->vhostname = "xxx";
$this->vdatabase = "bbbb";
$this->vusername = "xxx";
$this->vpassword = "";
}
else
{
$this->vhostname = "localhost";
$this->vdatabase = "xxxx";
$this->vusername = "xxxx";
$this->vpassword = "xxxx";
}
$this->vdblinkid = $this->vconnect();
}
protected function vconnect()
{
$vlinkid = mysql_connect($this->vhostname, $this->vusername, $this->vpassword) or die("Could not Connect ".mysql_errno($vlinkid));
mysql_select_db($this->vdatabase, $vlinkid) or die("Could not select database ".mysql_errno($vlinkid)) ;
return $vlinkid;
}
Third file
$objdb1 = new database();
$objdb2 = new database2();
Can you help me on this?
Regards,
Pankaj
Without knowing your classes, it is difficult to help. If you are using PDO, I can guarantee you that you can create multiple instances connected to different databases without any problem. If you are using the mysql_ family of functions you probably just forgot to set the link_identifier parameter (see here).
However, having a class db1 and a class db2 sounds like a code smell to me. You probably want to have two instances of the same class with different attributes.
Each time you call mysql_connect() or the equivalent mysqli functions, if a connection already exists using those same credentials it gets reused - so anything you do to modify the state of the connection, including changing database, charsets, or other mysql session variables affects "both" connections.
Since you are using the mysql_connect() function you have the option to force a new connection each time but this is not supported on all the extensions (IIRC mysqli and PDO don't alow for this).
However IMHO this is the wrong way to solve the problem. It just becomes messy trying to keep track of what's connected where.
The right way would be to specify the database in every query:
SELECT stuff FROM aaaa.first f, aaaa.second s
WHERE f.something=s.something;
Most likely your class does not pass the appropriate connection resource to the database functions. The second argument to e.g. mysql_query() is the connection resource. Simply store this resource in an instance variable on connection, and use it every time you do something with the database.
Your problem may be in checking if the SERVER_NAME is "localhost". Seems like you may be using the same connection strings in both classes. What is $_SERVER['SERVER_NAME'] resolving to?
You're looking for the fourth parameter of mysql_connect(), which states that it shouldn't reuse existing connections:
$dbLink1 = mysql_connect($server, $user, $pass, true);
mysql_select_db($db1, $dbLink1);
$dbLink2 = mysql_connect($server, $user, $pass, true);
mysql_select_db($db2, $dbLink2);
mysql_query("SELECT * FROM table1", $dbLink1); // <-- Will work
mysql_query("SELECT * FROM table1", $dbLink2); // <-- Will fail, because table1 doesn't exists in $db2
Passing the fourth parameter as true to mysql_connect resolves the issue.
$linkid = mysql_connect($this->hostname, $this->username, $this->password,true) or die("Could not Connect ".mysql_errno($linkid));