Session data in Codeigniter - php

I have a simple program that manages documents' data. A document has a branch_id & subject_id.
Some documents have:
a) Only the branch_id & subject_id is null.
b) Only the subject_id & branch_id is null.
c) Both the branch_id & subject_id.
I need to separate all the files by the above criteria. In my project, I used the following code to do this
if ($this->session->userdata('branch_id'))
$this->db->where('tbl_documents.branch_id', $this->session->userdata('branch_id'));
if ($this->session->userdata('subject_id'))
$this->db->where('tbl_documents.subject_id', $this->session->userdata('subject_id'));
How can I modify above code to fulfill criteria c) mentioned above. Can anyone help me?

Try the Associative array method
if (($this->session->userdata('branch_id')) && ($this->session->userdata('subject_id')))
{
$where = array(
'branch_id' => $this->session->userdata('branch_id'),
'subject_id' => $this->session->userdata('subject_id')
);
}
else if($this->session->userdata('branch_id'))
{
$where = array('branch_id' => $this->session->userdata('branch_id'));
}
else if($this->session->userdata('subject_id'))
{
$where = array('subject_id' => $this->session->userdata('subject_id'));
}
else
{
$where = array('1' => '1'); //You probably don't need this case.
}
$this->db->where($where);
$this->db->get('tbl_documents');

I don't believe you need to do anything.
Let's assume you're asking for all fields from tbl_documents so the "base-line" query statement is
SELECT * FROM tbl_documents
That will not change unless one or both of the if statements are true.
If the first is true, then the query statement becomes
SELECT * FROM tbl_documents WHERE tbl_documents.branch_id = some_branch_id;
However, if the first were false and the second true then the statement would be
SELECT * FROM tbl_documents WHERE tbl_documents.subject_id = some_subject_id;
Should both if conditions be true the query statement would be
SELECT * FROM tbl_documents WHERE tbl_documents.branch_id = some_branch_id
AND tbl_documents.subject_id = some_subject_id;
Doesn't that satisfy the criteria "c"?
The question I have is, what if both conditions are false? Is SELECT * FROM tbl_documents (no WHERE conditions) a query you actually want to run?

Related

Yii2 - Ignore where clause if variable is empty

I have yii2 query with conditional where clause. this is my query :
$query = new Query();
$query->select
(['pengeluaran.id'])
->from('surat_jalan, pengeluaran')
->where('surat_jalan.no_bus=:no_bus',['no_bus'=>$no_bus])
//this is my conditional query
->andWhere(['between', 'pengeluaran.tgl_pengeluaran', $awal, $akhir])
->andWhere('pengeluaran.nama_toko=:nama_toko',['nama_toko'=>$nama_toko])
->andWhere('pengeluaran.metode_pembayaran=:metode_pembayaran',['metode_pembayaran'=>$metode_pembayaran])
->andWhere('pengeluaran.waktu_pembayaran=:waktu_pembayaran',['waktu_pembayaran'=>$waktu_pembayaran])
//this is my conditional query
->andWhere('surat_jalan.id_surat_jalan=pengeluaran.id_surat_jalan');
$command = $query->createCommand();
$data_id_pengeluaran = $command->queryAll();
I read some question from others and what I found is for mysql table field :
->andWhere(['not', ['activated_at' => null]]);
what I want is if the variable is empty, the conditional where() clause is ignore. Is it possible in yii2??
The filterWhere is the perfect tool to achieve your goals.
For example,
// This will not appear in the finally statement if $val is empty.
$query->andFilterWhere(['activated_at' => $val])
Note: A value is considered empty if it is null, an empty array, an empty string or a string consisting of whitespaces only.

Laravel Eloquent: how to filter multiple and/or criteria single table

I am making a real estate related app and I've been having a hard time figuring out how to set up the query so that it would return "Only Apartments or Duplexes within selected areas" I'd like to user to be able to find multiple types of property in multiple selected quadrants of the city.
I have a database with a column "type" which is either "Apartment", "House", "Duplex", "Mobile"
In another column I have quadrant_main with values: "NW", "SW", "NE", "SE".
My code works when there is only 1 quadrant selected, but when I select multiple quadrants, I seem to get results which includes ALL the property types from the second or third or 4th quadrant, instead of only "Apartment" and "Duplex" or whatever types the user selects... Any help will be appreciated! thx in advance.
My controller function looks like this:
public function quadrants()
{
$input = \Request::all();
$currentPage = null;
$column = "price";
$order = "desc";
//
// Looks like the input is like 0 => { key: value } ...
// (an Array of key/value pairs)
$q = Listing::where('status','=','Active')->where(function($query) {
$input = \Request::all();
$currentPage = null;
$typeCount = 0;
$quadrantCount = 0;
foreach( $input as $index => $object ) {
$tempObj = json_decode($object);
$key = key((array)$tempObj);
$val = current((array)$tempObj);
if ( $key == "type" ) {
if ( $typeCount > 0 ) {
$query->orWhere('type', '=', $val );
}
else {
$query->where('type', '=', $val );
$typeCount++;
}
}
if ( $key == "quadrant_main" ) {
if ( $quadrantCount > 0 ) {
$query->orWhere('quadrant_main', '=', $val );
}
else {
$query->where('quadrant_main', '=', $val );
$quadrantCount++;
}
}
// else {
// $query->orWhere($key,$val);
// }
}
if( $currentPage ) {
//Force Current Page to Page of Val
Paginator::currentPageResolver(function() use ($currentPage) {
return $currentPage;
});
}
});
$listings = $q->paginate(10);
return $listings;
Looking at your question, its a bit confusing and not much is given to answer definitely. Probable causes of your troubles may be bad data in database, or maybe corrupted input by user.
Disclaimer: Please note that chances are my answer will not work for you at all.
In that case please provide more information and we will work things
out.
There is one thing that I think you have overlooked and thus you are getting awry results. First let me assume a few things.
I think a sample user input should look like this:
array(
0: '{type: Apartment}',
1: '{type: Duplex}',
2: '{quadrant_main: NW}',
3: '{quadrant_main: SW}',
)
What the user meant was give me any apartment or duplex which belongs in NW or SW region.
So after your loop is over, the final SQL statement should be something like this:
Oh and while we are at SQL topic, you can also log the actual
generated SQL query in laravel so you can actually see what was the
final SQL getting generated. If you can post it here, it would help a
lot. Look here.
select * from listings where status = 'Active' and (type = 'Apartment' or type = 'Duplex' and quadrant_main = 'NW' or quadrant_main = 'SW');
What this query will actually produce is this:
Select any listing which is active and:
1. Type is an apartment, or,
2. Type is a duplex, or,
3. Quadrant is SW, and,
4. Quadrant is NW
So assuming you have a database like this:
id|type|quadrant_main
=====================
1|Apartment|NW
2|Apartment|SW
3|Apartment|NE
4|Apartment|SE
5|Duplex|NW
6|Duplex|SW
7|Duplex|NE
8|Duplex|SE
9|House|NW
10|House|SW
11|House|NE
12|House|SE
You will only receive 1, and 5 in the result set. This result set is obviously wrong, plus it is depended on NW because that was the and condition.
The correct SQL query would be:
select * from listings where status = 'Active' and (type = 'Apartment' or type = 'Duplex') and (quadrant_main = 'NW' or quadrant_main = 'SW');
So structure your L5 app such that it produces this kind of SQL query. Instead of trying to cram everything in one loop, have two loops. One loop should only handle type and another loop should only handle quadrant_main. This way you will have the necessary and condition in the right places.
As a side note:
Never directly use user input. Always sanitize it first.
Its not a best practice to put all your logic in the controller. Use repository pattern. See here.
Multiple where clauses are generally applied via Criteria. Check that out in the above linked repository pattern.
You code logic is very complicated and utterly un-necessary. Instead of sending JSON objects, simply send the state of checkboxes. Don't try to generalize the function by going in loop. Instead handle all checkboxes one by one i.e. is "Apartments" selected, if yes, add that to your clause, if not, don't add.

How to interact with preview and save using flourishlib's fRecordSet's build method?

Let's suppose I have a database table called local_ads.
Now, when a local ad is created, one has to be able to view its preview and if he is satisfied, then save it. Also, if one wants to update a local ad, then he might want to see its preview before he overwrites the live version of the record.
So, I have a foreign key for the local_ads table called parent_id. If this is null, then it is a preview (at least according to my initial thoughts). Otherwise it is live. When one saves a preview, there are two cases:
Case 1: There was no live record yet linked to the preview. In this case a new record is inserted into the local_ads table with the parent_id pointing to the preview.
Case 2: There is a live record linked to the preview. In this case the live record is updated.
Everything looks and works nicely, but I have a problem showing the results in a grid. I want to show the preview if no live version of the record exists and only the live version if it exists. I would like to show something in the spirit of
select col1, col2, col3, col4
from local_ads glob
where (not (parent_id is null))
or ((select id from local_ads temp where temp.parent_id = glob.id limit 0, 1) is null)
but I have several problems. We have a logical or (I wonder how can I use logical or between logical operands using the build method of fRecordSet of flourishlib). Also, this query is of two dimensions, it is slow. Also, I wonder how can a sub-query be executed. Also, I do not know how can I use the is operator as in is null.
So, I had to re-think my idea and I came up with the following:
select col1, col2, col3, col4
from local_ads
where parent_id < id or parent_id >= id
the idea is simple: If a preview does not have a live version, then parent_id matches the id, otherwise the parent_id of a preview is null. I know this is an ugly hack, but this was the best idea I could came up with to solve the problem and decrease memory and performance complexity.
So, the only problem which remained was to check the two logical values in the where clause separated by the logical or.
From the documentation I have seen this:
* 'column<:' => 'other_column' // column < other_column
and this:
* 'column>=:' => 'other_column' // column >= other_column
so I know how can I add these to the filters, but how am I supposed to 'or' them?
So far I have tried it this way:
public static function localAd() {
$User = Globe::load('CurrentUser');
$Smarty = Globe::load('Smarty');
//handle default options
$options = array(
'recordsPerPage' => 20,
'pageLinks' => 10,
);
$page = 0;
if (isset($_GET['p'])) {
$page = $_GET['p'];
}
//get the data
$startIndex = (isset($page)) ? $page * $options['recordsPerPage'] : 0;
$filters = array();
if ($User->getType() == 'local_admin') {
$filters['domain='] = $User->getDomain();
}
$records = fRecordSet::build('LocalAd', $filters, array('created' => 'desc'), $options['recordsPerPage'], $page + 1);
//create result object for pagination
$Result = array(
"recordsReturned" => $records->count(),
"totalRecords" => $records->count(true),
"startIndex" => intval($startIndex),
"records" => $records->export(),
'recordsPerPage' => $options['recordsPerPage'],
'pageLinks' => $options['pageLinks'],
'currentPage' => $page,
//'options' => $options
);
$Result['totalPages'] = ceil($Result['totalRecords'] / $Result['recordsPerPage']);
$Smarty->assign('Result', $Result);
$Smarty->assign('ManagerURL', '?a=localAd');
AdminView::display('Admin/LocalAd/main.tpl');
}
Note, that in some cases I have to check the domain as well.
In the meantime I have managed to solve the problem. This is how we can define the filter set to solve the problem mentioned in the question:
$filters = array();
if ($User->getType() == 'local_admin') {
$filters['domain='] = $User->getDomain();
}
$filters['parent_id<:|parent_id>=:'] = array('id', 'id');

multiple where clauses in redbeanphp

I'm using readbeanphp as ORM for my php project. I'm trying to load a bean with an additional where clasue. But i'm not sure how to do this.
Normally i'd get a 'bean' like this:
$book = R::load('book', $id);
Which is basically like saying:
SELECT * FROM book WHERE id = '$id'
But i need to add another condition in the where clause:
SELECT * FROM book WHERE id = '$id' AND active = 1
How can i do this with redbeanphp?
R::find() and R::findOne() is what you are looking for:
$beans=R::find("books","active=? AND id=?",array(1,1));
Or if you want a single bean only:
$bean=R::findOne("books","active=? AND id=?",array(1,1));
R::find() will return multiple beans, while R::findOne() returns just a single bean.
You technically could use R::load() but would have to use PHP to check the active field after the bean is loaded to test if it is valid:
$bean=R::load("book",$id);
if($bean->active==1){//valid
//do stuff
}else{//not valid
//return error
}
Hope this helps!
RedBean_Facade::load is using for primary key only.
if you want get beans by a complex query
use
R::find like,
$needles = R::find('needle',' haystack = :haystack
ORDER BY :sortorder',
array( ':sortorder'=>$sortorder, ':haystack'=>$haystack ));
Read more about R::find
http://www.redbeanphp.com/manual/finding_beans
try to use getAll to write your query directly with parameters
R::getAll( 'select * from book where
id= :id AND active = :act',
array(':id'=>$id,':act' => 1) );
Read more about queries,
http://www.redbeanphp.com/manual/queries
these answers are fine but can be simplified. What you should use is:
$book = R::find('books', id =:id AND active =:active, array('id' => $id, 'active' => 1));
And then you can do your standard foreach to loop through the returned array of data.

Codeigniter omit where clause for empty criterion

I have a page for browsing db records. The viewer can filter records by category, author, and tags. I'm using a form instead of url segments for filtering records (it feels more secure because I can validate inputs.)
For instance, when all form inputs are populated the query looks like this:
SELECT * FROM (`posts`) WHERE `category` = 'technolgy' AND `author` = 'lila' AND `tags` = 'ebook'
However if one input or more is empty, I get no results. For example:
SELECT * FROM (`posts`) WHERE `category` = '' AND `author` = 'lila' AND `tags` = ''
I want the inputs to be optional so for example if just author name is entered, I can return records made by that author regardless of category and tags. How can I omit the and where clause if empty?
Note: or_where clause is not the solution because it doesn't return a precise query if all filter inputs all filled.
My Model
function filter($form_values)
{
$query = $this->db->get('posts');
$this->db->where($form_values); //adds clause to all array items
return $query->result();
}
The function parameter is an array with input values from my view. Example,
$form_values = array('category' => $category, 'author' => $author, 'tags' => $tags);
and my View
$form_values = array (
'category' => $this->input->post('category'),
'author' => $this->input->post('author'),
'tags' => $this->input->post('tags')
);
$this->Records_model->filter($form_values);
I know that in Codeigniter if $_POST' are empty they are set to FALSE. Can that be used to achieve what I'm trying? I'm not sure if I'm on the right track
You are correct that $this->input->post() will return FALSE if the $_POST value is not set. Unless you specifically want IS NULL to be part of the query (which I believe will happen by passing FALSE to param 2 of where(), not 100% sure), just filter out the empty values:
function filter($form_values)
{
$form_values = array_filter($form_values);
// NOTE:
// where() needs to be called first, or your query won't use the WHERE clause
// You may need to make sure there is at least one value in $form_values
if ( ! empty($form_values)) // however you wish to check for a value
{
$this->db->where($form_values); //adds clause to all array items
}
$query = $this->db->get('posts');
return $query->result();
}
http://php.net/manual/en/function.array-filter.php
The important part to note on array_filter():
If no callback is supplied, all entries of input equal to FALSE (see converting to boolean) will be removed.

Categories