The below code shows the error (on the line if ($response) {):
Undefined variable: response
I am checking the if condition inside the foreach because I wanted to check whether each id in the UserEnabledNotifications table exists in notifications table. Also dump($response); inside the if condition of foreach shows data.
Can I get the data in $response outside the foreach loop? What shall I try?
$notificationData = UserEnabledNotifications::all();
foreach ($notificationData->where('status', 'true') as $user => $value) {
if (Notifications::where('userEnabledNotificationsId', $value['id'])->exists() == false) {
$notificationTypeName = NotificationTypes::where('id', $value['notificationTypesId'])
->value('notificationTypeName');
$userData = User::where('id', $value['userId'])
->get()
->toArray();
$data = [];
$data['notificationTypesId'] = $value['notificationTypesId'];
$data['notificationTypeName'] = $notificationTypeName;
$data['userId'] = $value['userId'];
$data['email'] = $userData[0]['email'];
$data['recipientName'] = $userData[0]['FullName'];
$data['userEnabledNotificationsId'] = $value['id'];
$response = Notifications::create($data);
//dump($response);
$tags[] = $response;
}
}
if ($response) {
return response()->json([
'message' => 'success',
'data' => $tags,
'statusCode' => 200,
'status' => 'success'
], 200);
}
You define $response in first if body but you need $response = null above that.
You might create a private or protected variable, and put it outside, and then access it directly or via functions
$notificationData = UserEnabledNotifications::all();
private $reponse = null;
foreach ($notificationData->where('status', 'true') as $user => $value) {
if(Notifications::where('userEnabledNotificationsId',$value['id'])->exists()==false){
$notificationTypeName = NotificationTypes::where('id', $value['notificationTypesId'])->value('notificationTypeName');
$userData = User::where('id', $value['userId'])->get()->toArray();
$data = [];
$data['notificationTypesId'] = $value['notificationTypesId'];
$data['notificationTypeName'] = $notificationTypeName;
$data['userId'] = $value['userId'];
$data['email'] = $userData[0]['email'];
$data['recipientName'] = $userData[0]['FullName'];
$data['userEnabledNotificationsId'] = $value['id'];
$response = Notifications::create($data);
$tags[] = $response;
}
}
if ($response) {
return response()->json([
'message' => 'success',
'data' => $tags,
'statusCode' => 200,
'status' => 'success'
], 200);
}
But now each place you would need to check whether responses are null or not.
Why private or protected or public?
Check this answer : What is the difference between public, private, and protected?
I quote
public scope to make that property/method available from anywhere, other classes, and instances of the object.
private scope when you want your property/method to be visible in its own class only.
protected scope when you want to make your property/method visible in all classes that extend current class including the parent class.
Simply declare a null or an empty array in a $response variable and you will be able to get the data out of the loop!
Related
I am new at PHP. We are creating REST API in Phalcon and I've created a put request. It already works, but I would like to check if update has really happened before sending a success response. So I've created a conditional for that ( if (!$product->update()) ), but it always returns 'true'. How can I check if any field has changed in a record?
public function put()
{
$id = $this->getParam('id');
$input = $this->getRawData();
$product = Product::findFirst([
'conditions' => 'id = :id:',
'bind' => ['id' => $id]
]);
if ($product === null){
throw new NotFoundException();
}
$product->assign($input);
$product->update();
if (!$product->update()) {
$this->errorResponse($product->getMessages());
} else {
$this->successResponse($product->toArray($product->update()));
}
}
You can use Model Events, i.e. afterUpdate and notSaved, like:
use Phalcon\Mvc\Model;
use Phalcon\Http\Response;
class ModelBase extends Model
{
public function afterUpdate()
{
$response = new Response();
$response->setJsonContent([
'success' => true,
'message' => "Record updated"
])->send();
}
public function notSaved()
{
$response = new Response();
$response->setJsonContent([
'success' => false,
'message' => 'Record not saved'
])->send();
}
}
The Product and all other models will extend ModelBase. Then your code could be:
public function put()
{
$id = $this->getParam('id');
$input = $this->getRawData();
$product = Product::findFirst([
'conditions' => 'id = :id:',
'bind' => ['id' => $id]
]);
if ($product === null){
throw new NotFoundException();
}
$product->assign($input);
$product->update();
}
And Phalcon event will respond if the model was updated or not. If you prefer, you can also use custom http response codes for update or notSaved. More information about Model Events in the documentation
You are calling $product->update() three times. You do it once after the assign, then again for your if test, which is why it's always returning TRUE there I believe, and once inside the toArray() which may not actually return anything since the second and third updates don't have any data to update (not sure about that though).
I would code this as follows:
$product->assign($input);
$results = $product->update();
if (!results) {
$this->errorResponse($product->getMessages());
} else {
$this->successResponse($results->toArray());
}
I am assuming that the $product->assign($input); statement is working as expected to update the $product data for you. I don't use that. I prefer to do direct assignments for updates so nothing is left to chance, ie. $product->whatever = $input['whatever'];.
Give this a try and hopefully it will work as expected for you.
I've got object variables that I want to update inside promises guzzle with closure:
foreach ($urls as $i => $url) {
$this->facebook[$url] = 0;
$this->googlePlus[$url] = 0;
$this->pinterest[$url] = 0;
$this->twitter[$url] = 0;
$this->metaResults[$url] = [
'url' => false,
'title' => false,
'desc' => false,
'h1' => false,
'word_count' => 0,
'keyword_count' => 0
];
$that = $this;
$promise = $client->getAsync($url)->then(function ($content) {
return $content->getBody()->getContents();
})->then(function($html) use (&$url, &$that) {
$that->metaResults[$url] = $this->parseMeta($html);
});
$promeses['meta'][$url] = $promise;
}
$responses = Promise\Utils::settle($promises)->wait();
The problem as you can see above $that->metaResults[$url] = $this->parseMeta($html); this is never saved on that object var. Is there a way to do this?
It seems to me like there are few errors. If you want to use $url and $that shouldn't you pass it in to callbacks registered with the promises's then method for first one. Also I think that $this will not be accessible inside the callback registered with the then(). Though you will need to check for $this.
$promise = $client->getAsync($url)
->then(function (ResponseInterface $content) use ($url, $that) {
return $content->getBody()->getContents();
})
->then(function($html) use ($url, $that) {
$that->metaResults[$url] = $this->parseMeta($html);
});
$promeses['meta'][$url] = $promise;
reference
Using sessions we can achieve this, but need this without sessions or cookies.
<?php
class Employees extends CI_Controller
{
public function __construct()
{
parent::__construct();
}
public function auth() {
$adminEmail = $this->input->post('adminEmail');
$adminPassword = $this->input->post('adminPassword');
if ($adminEmail != "" && $adminPassword != "") {
$query = $this->db->query("select * from admin_tbl where email= '$adminEmail' and password = '$adminPassword'");
//if user exist
if ($query->num_rows() <= 0) {
$response = array();
$jwtoken = "";
$this->session->set_flashdata("invalid", "Wrong email or password");
$response = array(
'status' => 'invalid',
'message' => $_SESSION['invalid'],
'token' => $jwtoken,
);
//used to send finalized values
$this->output
->set_content_type('application/json')
->set_output(json_encode($response));
return $jwtoken; //return value
} else {
// $this->session->set_userdata('adminEmail', $adminEmail);
$response = array();
$jwt = new JWT();
$data = array(
'adminEmail' => $adminEmail,
'iat' => time()
);
$jwtoken = $jwt->encode($data, jwtSecretKey, 'HS256');
// I want to pass $jwtoken's variable to all the functions in a controller
$this->session->set_flashdata("login", "Scucessfully login!");
// if (isset($_SESSION['adminEmail'])) {
if ($jwtoken != "") {
$response = array(
'status' => 'valid',
'message' => $_SESSION['login'],
'token' => $jwtoken
);
}
$abc = $jwtoken;
//used to send finalized values
$this->output
->set_content_type('application/json')
->set_output(json_encode($response));
return $jwtoken; //return value
}
}
}
public function addNew()
{
$response = array();
$this->auth(); // this value is always null returned by auth() method
}
}
?>
This is more of a OOP programming basics question. If you want to re-use a variable in another function of the same controller object, you have to set the variable globally for the Employees class and then set/get its value in your functions by using $this->yourVariableName. But the set value of the object instance can only be reused in that instance only. Which means that after the auth() function, another function should be called subsequently to "access" the $this->yourVariableName.
Another way is to pass the $jwtoken as a parameter to a function.
But the following code answers your question "How to pass calculated/final value of one function to other functions in a controller of Codeigniter application", if it doesn't, then your question should be corrected I guess.
Edit:
Ow ok, first the auth() function is being called, then you would like to pass the $jwtoken value to another function, am I right? Well once a function is finished executing, the variable "disappears" if not passed to another function. If you would like to process the $jwtoken value immediately within the auth() function, then the answer is to pass the $jwtoken value to another function from within the auth() function:
<?php
class Employees extends CI_Controller
{
public function __construct() {
parent::__construct();
}
public function auth() {
$adminEmail = $this->input->post('adminEmail');
$adminPassword = $this->input->post('adminPassword');
if ($adminEmail != "" && $adminPassword != "") {
$query = $this->db->query("select * from admin_tbl where email= '$adminEmail' and password = '$adminPassword'");
//if user exist
if ($query->num_rows() <= 0) {
$response = array();
$jwtoken = "";
$this->session->set_flashdata("invalid", "Wrong email or password");
$response = array(
'status' => 'invalid',
'message' => $_SESSION['invalid'],
'token' => $jwtoken,
);
//used to send finalized values
$this->output
->set_content_type('application/json')
->set_output(json_encode($response));
return $jwtoken; //return value
} else {
// $this->session->set_userdata('adminEmail', $adminEmail);
$response = array();
$jwt = new JWT();
$data = array(
'adminEmail' => $adminEmail,
'iat' => time()
);
$jwtoken = $jwt->encode($data, jwtSecretKey, 'HS256');
// I want to pass $jwtoken's variable to all the functions in a controller
// this is one way you can pass the value to another function, depending on what you want to do, you can also place a condition and continue only if the return value of the following function is respected:
$this->addNew($jwtoken);
// What is the addNew() supposed to do?
$this->session->set_flashdata("login", "Scucessfully login!");
// if (isset($_SESSION['adminEmail'])) {
if ($jwtoken != "") {
$response = array(
'status' => 'valid',
'message' => $_SESSION['login'],
'token' => $jwtoken
);
}
$abc = $jwtoken;
//used to send finalized values
$this->output
->set_content_type('application/json')
->set_output(json_encode($response));
return $jwtoken; //return value
}
}
}
public function addNew($jwtoken = "default_value_if_not_set") {
echo $jwtoken;
}
}
Since you are creating an API, I assume the API is a REST api and stateless, so there is no interference of sessions and cookies.
I assume your process works like this:
User does a login request from the app to the api and the api returns a token when the credentials check is valid
The token is stored in the app (in a local database for example) and used for other requests
So the only thing you need to do is (I assume you have a route to addNew):
public function addNew() {
$token = $this->input->get('token');
$loginData = $this->validateToken($token);
//... add new process
}
And from your app you need to pass the token with the request to the api.
How do you validate the token?
To obtain the data you have set in the token, you have to decode the token:
/**
* throws SignatureInvalidException
*/
function validateToken($token)
{
$jwt = new JWT();
return $jwt->decode($token, jwtSecretKey, 'HS256');
}
Code improvement
Avoid using sessions and cookies
Since your api is stateless, you have to avoid settings cookies or sessions. So in your controller you can remove the flash data helper:
public function auth() {
$adminEmail = $this->input->post('adminEmail');
$adminPassword = $this->input->post('adminPassword');
if ($adminEmail != "" && $adminPassword != "") {
$query = $this->db->query("select * from admin_tbl where email= '$adminEmail' and password = '$adminPassword'");
//if user exist
if ($query->num_rows() <= 0) {
$response = array();
$jwtoken = "";
# REMOVE THIS LINE
# $this->session->set_flashdata("invalid", "Wrong email or password");
$response = array(
'status' => 'invalid',
'message' => "Wrong email or password", //CHANGE THIS LINE
'token' => $jwtoken,
);
//used to send finalized values
$this->output
->set_content_type('application/json')
->set_output(json_encode($response));
return $jwtoken; //return value
} else {
// $this->session->set_userdata('adminEmail', $adminEmail);
$response = array();
$jwt = new JWT();
$data = array(
'adminEmail' => $adminEmail,
'iat' => time()
);
$jwtoken = $jwt->encode($data, jwtSecretKey, 'HS256');
// I want to pass $jwtoken's variable to all the functions in a controller
# REMOVE THIS LINE
# $this->session->set_flashdata("login", "Scucessfully login!");
// if (isset($_SESSION['adminEmail'])) {
if ($jwtoken != "") {
$response = array(
'status' => 'valid',
'message' => "Scucessfully login!", //CHANGE THIS LINE
'token' => $jwtoken
);
}
$abc = $jwtoken;
//used to send finalized values
$this->output
->set_content_type('application/json')
->set_output(json_encode($response));
return $jwtoken; //return value
}
}
}
Return the output response instead of $jwtoken
In your response you have already set the the token, so you can simply return the response:
return $this->output
->set_content_type('application/json')
->set_output(json_encode($response));
Your query is vulnerable to sql injections
Use escape method around you variables or bind the params:
$sql = "select * from admin_tbl where email=? and password = ?";
$query = $this->db->query($sql, array($adminEmail, $adminPassword));
I'm beginner in PHP and phalcon, I want to use custom validation and creating default value.
My controller is:
use Phalcon\Mvc\Controller;
class OspoController extends Controller
{
public function indexAction()
{
}
public function createAction()
{
$ospo = new Ospos();
// Store and check for errors
$success = $ospo->save(
$this->request->getPost(),
array('isEmailConfirmed', 'email', 'password', 'salt' ,'phoneNum', 'verifiedPhoneStatus', 'languageId', 'firstName', 'lastName', 'address', 'cityId', 'provId', 'countryId', 'postCode')
);
$data = array();
if ($success) {
$data[] = array(
'status' => 'success'
);
echo json_encode($data);
} else {
foreach ($ospo->getMessages() as $message) {
$msg = $message->getMessage();
$data[] = array(
'message' => $msg
);
}
echo json_encode($data);
}
$this->view->disable();
}
I want if isEmailConfirmed is null - I want to create value that isEmailConfirmed = 0;
How to change array value of getPost()?
(can I do this) Should i change the code with
$isEmailConfirmed = $_POST['isEmailConfirmed'];
and
$ospo->save($isEmailConfirmed, $etc, $etc)?
Thank you.
First of all, you can just store POST data in a variable. Then just check for null and assign default value if needed before saving.
$data = $this->request->getPost();
if (!isset($data['isEmailConfirmed']) {
$data['isEmailConfirmed'] = 0;
}
Another way is to save null value, but in that case you should set up DEFAULT for that column in your database table.
I'm trying to add a array to a json file using php.
How I want it to look (formatting does not matter):
{
// Already stored in json file
"swagg_ma_blue":{
"user":"swagg_ma_blue",
"admin":true,
"user_id":"000"
},
// Should be added using php
"dnl":{
"user":"dnl",
"admin":"true",
"user_id":"000"
}
}
How my outcome actually looks like:
{"swagg_ma_blue":{"user":"swagg_ma_blue","admin":true,"user_id":"000"},"0":{"user":"d4ne","admin":true,"user_id":"000"}}
As you see the array index/key of the second element is called "0" but I need it to have the user value.
My code:
<?php
class add_mod_class {
function __construct($username, $status){
$this->username = $username;
$this->status = $status;
$this->user_id = '000';
$this->json_file = 'includes/json/mods.json';
}
function get_json(){
$json_content = file_get_contents($this->json_file);
$json = json_decode($json_content, true);
return $json;
}
function mod_handler(){
if($this->status == 'admin'){
return true;
}else{
return false;
}
}
function add_mod(){
$mods = $this->get_json();
$data = array(
'user' => $this->username,
'admin' => $this->mod_handler(),
'user_id' => $this->user_id
);
array_push($mods, $data);
$new_json_string = json_encode($mods);
return $new_json_string;
}
}
?>
First idea was to use was:
$data[$this->username] = array(
'user' => $this->username,
'admin' => $this->mod_handler(),
'user_id' => $this->user_id
);
But this would still return "0": in it. I Would appreciate every kind of help.
Your first approach was fine, except you should assign to $mods array instead of $data. Here is the corrected function:
function add_mod(){
$mods = $this->get_json();
$mods[$this->username] = array(
'user' => $this->username,
'admin' => $this->mod_handler(),
'user_id' => $this->user_id
);
$new_json_string = json_encode($mods);
return $new_json_string;
}