phpunit test methods that take data from db - mysql

in my app I have a special class to work with DB.
And I have methods that SELECT data from BD and return the result as an array. But when I try to cover this methods with PHPUnit, I always have NULL in return.
here is my piece of code
public function getData($id) {
$selectQuery = $dataBase->query('SELECT * FROM table WHERE id = :id');
$selectQery->bindInt(':id', $id);
$selectQuery->execute();
$result = $selectQuery->toArray();
return $result;
}
before getting result I can see with debuger that SQL query is ok, ID is binded and the method has to return an array. and it returns if to run the method in my app. But the test gives NULL result.
How can I cover this method with tests and make sure that it returns a correct array of data?

Related

SimpleJdbcCall for MySql Function yields "Can't set IN parameter for return value of stored function call"

Using the example from the Spring docs, I'm trying to return a value from a mySQL function. I keep getting the error Can't set IN parameter for return value of stored function call;.
I created a mySQL function that works fine (ran in MySQL Workbench). I've written a SimpleJdbcCall statement, set up the parameters as per Spring docs example but consistently get this error. If I turn the function into a procedure, the code works, I just have to retrieve the return value from the result set.
I used https://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch13s05.html, section 13.5.8 as reference.
CREATE FUNCTION `ScenarioRegistration`(
environment VARCHAR(45),
username VARCHAR(15),
scenario_name VARCHAR(45)) RETURNS int(11)
A couple of SELECT statements followed by an INSERT then
RETURN scenario_id; // The inserted id
Java code:
SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(getJdbcTemplate())
.withFunctionName("ScenarioRegistration")
.withoutProcedureColumnMetaDataAccess();
simpleJdbcCall.addDeclaredParameter(new SqlParameter("environment"
,Types.VARCHAR));
simpleJdbcCall.addDeclaredParameter(new SqlParameter("username"
,Types.VARCHAR));
simpleJdbcCall.addDeclaredParameter(new SqlParameter("scenario_name"
,Types.VARCHAR));
SqlParameterSource parameters = new MapSqlParameterSource()
.addValue("environment", environment)
.addValue("username", username)
.addValue("scenario_name", scenario);
simpleJdbcCall.setReturnValueRequired(true);
Integer scenario_id = simpleJdbcCall.executeFunction(
Integer.class, parameters);
All I want the routine to do is give me back the id of the newly inserted scenario.
What I get is:
SQL [{? = call scenarioregistration(?, ?)}]; Can't set IN parameter for return value of stored function call.
I find it interesting that it's taken my THREE input values and changed them to an output and TWO input values.
Anyone enlighten me as to the problem and how to fix it?
Thanks,
Steven.
I would refer to the latest docs here for your answer. It appears Spring is trying to infer the output because you didn't explicity specify one.
Per the docs above there are two valid approaches on calling the desired function with the SimpleJdbcCall:
Inferred Parameters
Because you've specified withoutProcedureColumnMetaDataAccess, Spring isn't going to look and see what the ins/outs are to your function. If you want it easy, just don't specify that and you should be able to do:
SqlParameterSource parameters = new MapSqlParameterSource()
.addValue("environment", environment)
.addValue("username", username)
.addValue("scenario_name", scenario);
Integer scenarioId = new SimpleJdbcCall(getJdbcTemplate())
.withFunctionName("ScenarioRegistration")
.executeFunction(Integer.class, parameters);
Explicit Parameters
If you want to keep withoutProcedureColumnMetaDataAccess turned off for whatever reason, you can do:
Integer scenarioId = new SimpleJdbcCall(getJdbcTemplate)
.withFunctionName("ScenarioRegistration")
.withoutProcedureColumnMetaDataAccess()
.useInParameterNames("environment", "username", "scenario_name")
.declareParameters(
new SqlOutParameter("scenario_id", Types.NUMERIC),
new SqlParameter("environment", Types.VARCHAR),
new SqlParameter("username", Types.VARCHAR),
new SqlParameter("scenario_name", Types.VARCHAR)
).executeFunction(Integer.class, parameters);
Note: It appears that order is critical in this example. The output parameter should be declared first, and the subsequent named IN parameters come last. That is, the order of the parameters ? are ordinal in [{? = call scenarioregistration(?, ?, ?)}])
Alternative NamedParameterJdbcTemplate Solution
Another way to invoke your function is via an actual JDBC call. This could hypothetically save you the grief of using the fine tuning of the SimpleJdbcCall.
Integer scenarioId = namedParameterJdbcTemplate.queryForObject(
"SELECT ScenarioRegistration(:environment, :username, :scenario_name)",
parameters,
Integer.class);

Laravel 5.4 formatting result set

Can someone help me convert this query so that my result set is in different format?
$sessions = new Session();
$results = $sessions->where('session_status', $status)->where('application_period_id', (int) ApplicationPeriod::all()->last()->id)->get()->pluck('speaker_id');
$speakers = Speaker::whereIn('id', $results)
->with('session.audiancesession.audiances')
->with('session.subjectsession.subjects')
->with(['session' =>
function ($query) use($status) {
$query->where('session_status', '=', $status);
}])->orderBy('last_name')->get();
This is requested via Ajax(axios)... Now this is how result is formatted:
Obj->data(array of objects)->[0]->name
->address
->session(array of objects)
->[0]->time
->fee
My issue is that my session parameter is array and there can only ever be (1) so I don't need to to be an array and I would like to have object (json) instead.
Thank you!
You might have more success if you change your client-side code to work with an array of sessions each session having its speaker, that means your original query would be like
$sessions = Sessions::with([
'speaker', 'audiancesession.audiances', 'subjectsession.subjects'
])->where('application_period_id', (int) ApplicationPeriod::orderBy('id','DESC')->first())->get();
Note the order by -> first in the ApplicationPeriod makes it so you don't have to get all application periods from the database to memory.
Then your client side should handle an array of sessions.
You can transform the above slightly using to get a similar result to what you need:
$speakers = $sessions->map(function ($session) {
$speaker = collect($session->speaker->toArray());
$speaker->put('session', collect($session->toArray())->except('speaker'));
return $speaker;
})->orderBy('last_name','DESC');
Though I wouldn't guarantee the result here as I've not tested it on your (complex looking) data.

Codeigniter -> 2 variables inside a controller

I am trying to set up a filter on my website. Here, I am trying to pass (2) variables (neighborhood and business category). My problem is when only (1) of them is true and the other is false or one variable does not exist. I am trying to pull this data from my URL
mydomain.com/controller/function/neighbrohood/biz-category
which translates
mydomain.com/ny/find/$neighborhood/$biz_filter
When I have both variables then there is no problem.
How do I resolve the page with only 1 of the 2 variables there?
Here is my model:
public function search($neighborhood = null, $biz_filter = null) {
$neighborhood = $this->uri->segment(3);
$biz_filter = $this->uri->segment(4);
// SELECT
$this->db->select('*');
// MAIN TABLE TO GRAB DATA
$this->db->from('biz');
// TABLES TO JOIN
$this->db->join('city', 'city.city_id = biz.biz_cityID');
$this->db->join('zip', 'zip.zip_id = biz.biz_zipID', 'zip.zip_cityID = city.city_id');
$this->db->join('state', 'state.state_id = city.city_stateID');
$this->db->join('neighborhood', 'biz.biz_neighborhoodID = neighborhood.neighborhood_id');
$this->db->join('biz_filter', 'biz_filter.bizfilter_bizID = biz.biz_id');
$this->db->join('biz_category', 'biz_filter.bizfilter_bizcategoryID = biz_category.bizcategory_id');
// RETURN VARIABLES
$this->db->where('neighborhood.neighborhood_slug', $neighborhood);
$this->db->where('biz_category.bizcategory_slug', $biz_filter);
// ORDER OF THE RESULTS
$this->db->order_by('biz_name asc');
// RUN QUERY
$query = $this->db->get();
// IF MORE THAN 0 ROWS ELSE DISPLAY 404 ERROR PAGE
if($query->num_rows() > 0){
return $query;
} else {
show_404('page');
}
}
Example. Say I am looking for a Restaurant in Little Italy:
URL = mydomain.com/ny/find/little-italy/restuarants
This part, I can resolve the query correctly and display the data. The issue is when there is no neighborhood or no category, I cannot figure out how to resolve the data.
I am new to codeigniter and a self-taught programmer, trying to figure this out as I go. Any help would be much appreciated.
Thank you in advance.
first of all it is optional to get the variables from the uri
$neighborhood = $this->uri->segment(3);
$biz_filter = $this->uri->segment(4);
You already have that from your function parameter.
You can check the condition where your $neighborhood or $biz_filter is available or not then you can use condition in your query.
Something like this
if($neighborhood) { // query for neighborhood } elseif($biz_filter) {}
Thanks
First of all you should get the variable values from your controller not your model, you should then pass such values to your controller from your model, its bad coding practice to allow your view interact with the model.
Also, if you want a value of "-" set for the variable. You should set "-" as the return value right from the parameters being passed to the controller.
What you should do is go to your controller and give it the two parameters, set default values for both and also go to your model and make it receive two parameters also, pass the parameters to the model when calling from the controller. Then get back if there are any more errors.

codeigniter model query not sending json data correctly

I have a codeigniter model function which queries a database and sends the result back to the controller, encoded as json.
the entire function is shown below:
function get_skufamily_cube($q){
$sql=("select min([Pieces]) as ProductCode from
(SELECT
[ProductCode]
,[Description]
,[Length]
,[Pieces]
,[Thickness]
,[Width]
,([width]*1000) w2
,([thickness]*1000) t2
,REPLACE((convert(varchar,convert(decimal(8,1),length))),'.','') AS l2
,concat(([width]*1000),([thickness]*1000),REPLACE((convert(varchar,convert(decimal(8,1),length))),'.','')) AS pc
,REPLACE([ProductCode],concat(([width]*1000),([thickness]*1000),REPLACE((convert(varchar,convert(decimal(8,1),length))),'.','')),'') as grade
,CONCAT(([width]*1000),([thickness]*1000),REPLACE([ProductCode],concat(([width]*1000),([thickness]*1000),REPLACE((convert(varchar,convert(decimal(8,1),length))),'.','')),'')) as options
FROM [hammerhead].[dbo].[ProductList]) as p
where Options like '%$q%' ");
$query=$this->db->query($sql);
if($query->num_rows > 0){
foreach ($query->result_array() as $row){
$row_set[] = htmlentities(stripslashes($row['ProductCode']));
echo $row['ProductCode']; // to see database result and troubleshoot
}
$this->output->set_content_type('application/json')->set_output(json_encode($row_set));
}
}
$q is being passed successfully to the query and the output of the query in echo $row['ProductCode']; is consistent with the result I require. in this case it is 108. the database query returns a single result in a single field.
For some reason, this is no tbeing passed back tot he controller correctly.
Controller is:
$this->load->model('Sales_model');
if (isset($_POST['data'])){
$q = strtolower($_POST['data']);
$data = $this->Sales_model->get_skufamily_cube($q);
$this->output->set_content_type('application/json')->set_output(json_encode($data));
}
}
In my developer tools, I can see the server response
108NULL. 108 being my echo and NULL being the json response. if I remove the echo this is simply NULL.
Laslty, I need to populate the input in my table row with the value. my view jquery syntax for this is:
$.post('get_skufamily_cubes', {data:selectedObj.value},function(result)
{
$(this).find('input[id^="cubesperbundle"]').val(result);
});
Currently nothing is populated. the html input name and id is:cubesperbundle but has the row number appended to it hence the 'input[id^="cubesperbundle"]'
Any assistance would be appreciated.
Thanks and Regards,
The mistake i see is that you are not returning anything to controller.
Model
function get_skufamily_cube($q)
{
$Query="select
min(Pieces) as ProductCode
from (SELECT
ProductCode,
Description,
Length,
Pieces,
Thickness,
Width,
(width*1000) w2,
(thickness*1000) t2,
REPLACE((convert(varchar,convert(decimal(8,1),length))),'.','') AS l2,
concat((width*1000),(thickness*1000),REPLACE((convert(varchar,convert(decimal(8,1),length))),'.','')) AS pc,
REPLACE(ProductCode,concat((width*1000),(thickness*1000),REPLACE((convert(varchar,convert(decimal(8,1),length))),'.','')),'') as grade,
CONCAT((width*1000),(thickness*1000),REPLACE(ProductCode,concat((width*1000),(thickness*1000),REPLACE((convert(varchar,convert(decimal(8,1),length))),'.','')),'')) as options
FROM hammerhead.dbo.ProductList) as p
where Options like '%$q%'";
return $this->db->query($Query)->row();
}
Controller
function getJson(){
$this->load->model('Sales_model');
if (isset($_POST['data'])){
$q = strtolower($_POST['data']);
$viewData = $this->Sales_model->get_skufamily_cube($q);
$data_json = json_encode($viewData);
echo $data_json;
}
}
EDITS:
Change the return instruction in model function.
$result = $this->db->query($Query)->row();
return $result->ProductCode;

How to pass one of the mysql query results in the model from controller?

In my controller I have called a model that makes a mysql query to fetch information from table. It is working okay but now under the same function I want to call another model and make a query based on one of the results from the previous mysql query. (The field name which I want to get the result of is "batch") . I have tried to get the value (batch) right in my controller, pass it into the model and then tried to make the second query but it seems like the second model is not getting the value from the controller and hence its not working. Would you please kindly help me with this?
Thanks in Advance :)
Here is my Controller
function Get($id){
$this->load->model('mod_studentprofile');
$data['query']= $this->mod_studentprofile->student_get($id);
// To get the batch name
$batch= $query ['batch']; // This I get from the above query result.
$this->load->model('batchname');
$data['query1']= $this->batchname->batchname($batch);
$data['tab'] = "Student Profile";
$data['main_content']='studentprofile';
$this->load->view('includes/template',$data);
}
Here is my model number 1
function student_get($id)
{
$query=$this->db->get_where('student',array('studentid'=>$id));
return $query->row_array();
}
Here is my model number 2
function batchname($batch)
{
$query1=$this->db->get_where('batch',array('batchid'=>$batch));
return $query1->row_array();
}
Well, you're not actually assigning anything to $batch, how about this:
$batch= $data['query'];
This now passes the variable along. As a side note, you can pass it as a paramater and be done with it in a single line, dependency injection style:
$data['query1']= $this->batchname->batchname($this->mod_studentprofile->student_get($id));
Are you getting a value back from the first query?
I would log the value you are getting back from the first query in your controller.
log_message('debug', 'Batch value is '.$batch);
And also put in some debug to see what the query that is being ran.
function batchname($batch)
{
$query1=$this->db->get_where('batch',array('batchid'=>$batch));
$str = $this->db->last_query();
log_message('debug', 'Batchname Query: '.$str);
return $query1->row_array();
}