I am using slim framework together with FluentPDO query builder and this is what I'm currently doing:
$app->get('/song/remove/:songID', function($songID) use($app) {
$pdo = new PDO("mysql:dbname=songs", "root");
$fpdo = new FluentPDO($pdo);
$query = $fpdo->deleteFrom('songlist')->where('songID', $songID)->execute();
$app->flash('msg', 'Song ID '.$songID.' removed.');
$app->redirect('/');
});
$app->get('/song/view/:songID', function($songID) use($app) {
$pdo = new PDO("mysql:dbname=songs", "root");
$fpdo = new FluentPDO($pdo);
$song = $fpdo->from('songlist')->where('songID', $songID);
$app->render('view-song.html', [
'song' => $song //pass variable to template
]);
});
As you can see, I am calling this code in every function:
$pdo = new PDO("mysql:dbname=songs", "root");
$fpdo = new FluentPDO($pdo);
What I wanted to do is to just call it once, so that if I will change something in my database, I'll only change a single line. How can I accomplish that? THank you.
It depends on your project structure, the logic is to create a bootstrap or configuration file that will contains all your project constants (database connection, paths ...) that will be loaded by default in your entire application.
this video by codeschool may help setting up one:
https://www.youtube.com/watch?v=NFeWo1cqxnM
here is a project skeleton that you may consider:
https://github.com/slimphp/Slim-Skeleton
Hope it helps
Related
I am using Slim Framework to create REST API.
There is also table in my mysql db where I store information about each request to server.
I have separate file called functions.php where I have log_request() function
require_once('dbconnect.php');
function log_request() {
global $mysqli;
$query = "INSERT INTO log_table (....) VALUES (...) ";
$mysqli->query($query);
}
If I run this script - new record is added to my table. But when I run it using Slim
$app->get('/api/something', function($request, $response) {
require_once('dbconnect.php');
include_once('functions.php');
log_request();
});
I am receiving this error
Call to a member function query() on null
So $mysqli inside log_request() is null - why does it happen?
Because $mysqli; is not in global scoped. You are employing bad practices all across. Refactor your code to take advantage of the advanced Slim PHP features such as Dependency Container or Dependency Injection.
By including the dbconnect file inside another function you have effectively scoped its variables to that block scope. You could simply remove the global keyword and the code should work.
As mentioned by Scriptonomy - in order to use MySQL or to prepare, manage, and inject application dependencies we should use dependency container.
https://www.slimframework.com/docs/v3/concepts/di.html
Step 1
create dependencies.php file
// DIC configuration
$container = $app->getContainer();
$container['db'] = function ($c) {
$host = "localhost";
$user = "user";
$pass = "password";
$db_name = "database_name";
$mysqli = new mysqli($host, $user, $pass, $db_name);
return $mysqli;
};
Step 2
add this code before $app->run();
// Set up dependencies
require __DIR__ . '/../app/dependencies.php';
Step 3
Now you can use mysql (or any other injection)
$app->post('foo', function ($request, $response, $args) {
$res = $this->db->query("SELECT * FROM `app_jobs`");
.......
});
How can use variable model several time, something like this code:
$Db = Model::where(['user_id'=>1]);
$Db->first();
$Db->get();
$Db->delete();
I dont want using repeat $Db for get,first,delete or etc
for example I dont prefer using bad code something like this:
$Db = Model::where(['user_id'=>1])->first();
$Db = Model::where(['user_id'=>1])->get();
$Db = Model::where(['user_id'=>1])->delete();
or ...
I want separate class object for any first() or get() or ...
I haven't tested this but try using query builder https://laravel.com/docs/5.4/queries#introduction
$qb = DB::table('users')->where('votes', '>', 100);
$qb->get();
$qb->first();
$qb->delete();
Another option is to use a closure
$model = function() {
return Model::where(['user_id'=>1]);
};
$model()->get();
$model()->first();
$model()->delete();
Again, not tested :)
You can use:
$Db = Model::where(['user_id'=>1]);
with(clone($Db))->first();
with(clone($Db))->get();
with(clone($Db))->delete();
The best way you can do is to create a helper or class.
// create
public static function user_info($user_id) {
return Model::where(['user_id' => $user_id]);
}
// call
Helpers:user_info(1)->first();
Helpers:user_info(1)->get();
Helpers:user_info(1)->delete();
I'm trying to use flight PHP framework for routing and medoo framework for database usage.
//connect database
$database = new medoo([
'database_type' => 'sqlite',
'database_file' => 'db.sqlite'
]);
//my function
function database($database){
$database->insert("ppl", [
"fn" => "joe","ln"=>"doe"]);
}
//
Flight::route('/add/', array(database($database)));
How to invoke my function with argument from this place:
Flight::route('/add/','database')
Tried different variants but getting errors.
I don't know medoo or flight, but you might be able to use an anonymous function with use:
Flight::route('/add/',
function() use($database) {
$database->insert("ppl", ["fn"=>"joe","ln"=>"doe"])
});
I think you need to re-architect this into an OOP style that will make it much easier and modular, but in a crunch if $database is defined in the global scope:
function database() {
$GLOBALS['database']->insert("ppl", ["fn"=>"joe","ln"=>"doe"]);
}
Flight::route('/add/', 'database');
I'm new to Angular JS. I'm able to call a php file and get the data. But, now the scenario is that I need to call a particular method from a php and get the data using "$http.get". Take a look at my code, whether I'm calling the method in the correct way or not?
Angular Code
// Ajax call for listing countries.
var countryPromise = $http.get("ListData.php/getCountries()");
// Create global users array.
$scope.countriesArray = [];
countryPromise.success(function(data, status, headers, config) {
for(index in data) {
alert(data[index].name);
$scope.countriesArray.push({
id:data[index].id,
name:data[index].name
});
}
});
countryPromise.error(function(data, status, headers, config) {
alert("Loading countries failed!");
});
PHP
<?php
class ListData
{
function __construct() {
// credentials of MySql database.
$username = "root";
$password = "admin";
$hostname = "localhost";
$countryData = array();
//connection to the database
$dbhandle = mysql_connect($hostname, $username, $password)
or die("Unable to connect to MySQL");
$selected = mysql_select_db("Angular",$dbhandle)
or die("Could not select Angular");
}
public function getCountries() {
//execute the SQL query and return records
$result = mysql_query("SELECT id,name FROM Country");
//fetch tha data from the database
while ($row = mysql_fetch_array($result)) {
$id = $row{'id'};
$name = $row{'name'};
$countryData[] = array('id' => $id, 'name' => $name);
}
echo json_encode($countryData);
}
}
?>
You need to know what is the route of the php function getContries and then call this route from the $http.get function.
Do you hard coded your php server or are you using a framework ?
I think that you are misunderstanding the way that PHP works. Actually you are trying to call a method from a class with an HTTP Request. Thats is not possible atleast not without a routing class.
The routing class its just a class that intercepts all the HTTP Request to analyze the URI, and based on a pattern, it match to a preexisting class, instantiate (create) it and call the wanted method from that class.
For example, our routing class have a pattern like this:
Class/Method
an intercept a Http Request like this:
www.oursite.com/ListData/getCountries
Where ListData is our class, and getCountries is our method or action.
So, the routing class just do this:
$Class->Method();
Of course we can achieve to pass parameters, and intercept and routing specific http request type's like: post, get, update, delete, etc.
There's a lot of frameworks who make that for you, but if you only want to use the Routing, here's a couple
https://github.com/dannyvankooten/PHP-Router
http://www.php.net/manual/en/class.yaf-router.php
https://github.com/dannyvankooten/AltoRouter/blob/master/AltoRouter.php
PHP Frameworks that I recommend (because I worked with them):
http://laravel.com/
http://ellislab.com/codeigniter
In anycase, if you don't want nothing of that, you could just create a folder called ListData and inside it create a file called getCountries.php. On that file just put the code to instantiate your class and call your method.
<?php
include('../ListData.php');
$cIns = new ListData();
$cIns->getCountries();
?>
In that way, it gonna work in the way you are calling the url (don't forget to add the .php extension at the end (: )
As the title says there is a problem accessing variable (associative array) inside class from included file. Here is the source code both class and include file:
require("applications/cw_database.php");
require("config/dbConfig.php");
require("config/appConfig.php");
class APP_ASSESMENTS
{
private $dbObj;
private $DisplayOutput = "";
public function __construct($PageParams)
{
try
{
$dbObj = new CW_DB($dbConfig['hostname'],$dbConfig['username'],$dbConfig['password'],$dbConfig['name'],$dbConfig['port']);
} catch (Exception $e) {
throw new ErrorException($e);
}
}
...
The other part has nothing to do with $dbConfig.
Also this is the included file (config/dbConfig.php):
/*
Testing configuration for MySQL database
*/
$dbConfig['username'] = "phpcoursework"; // changed on demand
$dbConfig['password'] = "phpcoursework"; // changed on demand
$dbConfig['hostname'] = "localhost"; // changed on demand
$dbConfig['name'] = "students"; // changed on demand
$dbConfig['port'] = 3306; // default for MySQL
First, $dbObj will not automatically assume class member scope, it will create a local copy of CW_DB and discard it when __construct returns. You need to explicitly reference the property;
$this->dbObj = ...
Anyway, global state using global as suggested by others will "work", but if you're using OOP practices you're best not to do that. You can actually return from an include(), so an option would be to do the following:
// your config file dbConfig.php
return array(
'username' => "phpcoursework",
'password' => "phpcoursework",
'hostname' => "localhost",
'name' => "students",
'port' => 3306,
);
And inject it into the object, via constructor or method (here's constructor)
class APP_ASSESMENTS
{
private $dbObj;
public function __construct($dbConfig, $PageParams)
{
$dbObj = new CW_DB($dbConfig['hostname'], $dbConfig['username'],
$dbConfig['password'], $dbConfig['name'], $dbConfig['port']);
// ...
}
}
// include() here, will actually return the array from the config file
$appAssesments = new \APP_ASSESMENTS(include('dbConfig.php'), $PageParams);
It would be recommended that you go another level up: instead, inject the database object itself, taking the dependency out of your APP_ASSESSMENTS class.
(Also, PascalCase is the typical convention of class naming, such as AppAssessments and CwDb)
$dbObj = new CwDb(include('dbConfig.php'));
$appAssessments = new AppAssessments($dbObj, $etc, $etc);
This simple change allows you to remove the dependency from AppAssessments on CwDb. That way, if you extend CwDb for some reason, you can just pass in an instance of the extended class without having to change any code in AppAssessments
You can change the AppAssessments constructor like so:
public function __construct(CwDb $db, $etc, $etc){
$this->db = $db;
// ...
}
This takes advantage of PHPs (limited, albeit still useful) type-hinting, ensuring the first argument is always of the correct type.
This plays into part of the open/closed principle: classes should be open to extension but closed for modification.
Includes are used in the scope of access. So, to access the variables you need to include the files within your class. As earlier mentioned global will let you access variables from another scope too. But global should be used with caution! See the documentation.
See the manual for more information.
Edit: I need to make it clear that globals are never a good alternative for handling these kind of critical variables..
public function __construct($PageParams){
global $dbConfig;
try{
$dbObj = new CW_DB($dbConfig['hostname'],$dbConfig['username'],$dbConfig['password'],$dbConfig['name'],$dbC onfig['port']);
} catch (Exception $e) {
throw new ErrorException($e);
}
}
or you could use $GLOBALS['dbConfig'].