CI: Select max return integer? - codeigniter

I think I've not found this answer on stackoverflow. I've need codeigniter function that will return me 0 if table is empty and max int from table if there is some data.
songs(IDSon, title)
I've tried with:
$this->db->select_max('IDSon');
$query = $this->db->get('songs');
But how can I access "IDSon" field, and to add IF clause if table is empty to get 0?
Thanks

function get_max_number() {
$result = $this->db->select_max('IDSon')->get('songs')->result_array();
return (int) $result[0]['IDSon'];
}

Related

Is there any way to explode a table inside query?

I have this table in my database.
ยป roles, and have content of 0,0,0,0,0,0
In this table i store user permissions. Example if he is an administrator it can be 0,0,0,0,0,1 or if he is an moderator and an administrator in the same time it can be 0,0,0,1,0,1.
But i don't know how i can show them in a query separated.
Example for administrator query only last parameter from that list 0,0,0,0,0,0.
So for it i have to do a explode in the query but i don't know how to do this.
I tried something like that to see if i can get the tables and explode it before query execute.
$query = User::where(
function($results) {
dd($results);
foreach($results as $result) {
print($result);
}
})->first();
Someone have an idea how i can do this?
if you have a fixed pattern you can "explode" it easily.
for example:
$result = "0,0,0,0,0,1"; // your data in for is string so:
$permission = explode(",",$result); // convert to an array.
// outpult is:
print ($permission);
[0 , 0 , 0 , 0 , 0 , 1 ];
print ($permission[5]);
// output is:
1
now you can access each cell of the array.
but It's not a clear way to make permission and role.
I suggest you use the different tables with different relationships.
I think this is not convenient way of implementing roles and permissions. If you are using Laravel then there is already a way to implement permissions in the form of gates and policies.
or you can implement it through a package like
Spatie Package
This might help it will return permissions ending with 1
User::where(function ($builder){
$builder->where('permission', 'regex','%1');
});
as a simple and appropriate solution,
you can also write your, where condition as below
->whereRaw("SUBSTRING_INDEX(SUBSTRING_INDEX(permission_column_name, ',', 6), ',', -1) = 1")
as you can see in the above code,
With SUBSTRING_INDEX(permission_column_name, ',', 6) function we will be able to extract everything up to the sixth value in your column separated by a comma.
Because SUBSTRING_INDEX() function also allows us to use negative values to extract fields counting from the right, we are using this ability to extract the rightmost field containing the last value of string with -1.
using the same above method you can also find any value available at any position as required in the given comma-separated string in a column.
Assuming that each user has a role, you can add some methods to the User model to handle permissions.
Class User extends Authenticatable {
private function getPermissions(): array {
return explode(',', $this->role)
}
public function isAdministrator(): bool {
$permissions = $this->getPermissions();
return $permissions[5] == 1;
}
public function isModerator(): bool {
$permissions = $this->getPermissions();
return $permissions[3] == 1;
}
}
Now you can use it in your code. Like this:
$user = auth()->user() // Or User::find($id) ...
if ($user->isAdministrator() || $user->isModerator()) {
// Do something
}

Laravel 5 - how to get a random row from first 30 records in eloquent?

I am trying to get a random row from the top 30 records in a table. I sort all the records by score first, and take 30 records in a scope of the eloquent model:
public function scopePopular($query, $d)
{
return $query->where('d', $d)->orderBy('score', 'desc')->take(30);
}
Then in a class:
$cnt = Record::popular($d)->count();
if ($cnt == 0)
return;
$randIndex = rand(0, $cnt-1);
$record = Record::popular($d)->skip($randIndex)->take(1)->first();
return $record;
But when I check in php artisan tinker, I found that Record::popular($d)->count(); will return all the records number instead of 30. How can I correct this problem? Thanks.
Use get() before count() to run the query before count:
$cnt = Record::popular($d)->get()->count();
You are running the query 2 times. That is not necessary.
$cnt = Record::popular($d)->count(); // First query
if ($cnt == 0)
return;
$randIndex = rand(0, $cnt-1);
$record = Record::popular($d)->skip($randIndex)->take(1)->first(); // Second query
return $record;
Instead you can do it like this:
return Record::popular($d)->get()->random(); // One query only

Using whereIn method to return multiple results for the same array value but at different index

$pidArray contains product ID's, some of those product ID's can be the same. I.E: 34 34 56 77 99 34. As is, it appears the whereIn method does not return results for a productId it has already found in $pidArray, even if it has a different index.
$productDataForOrder = Product::whereIn('id', $pidArray)->get(['id','price']);
$totalAmount = $productDataForOrder->sum('price');
$productDataForOrder now contains product data, but only for unique ProductID's in $pidarray. So when sum function is run, the sum is wrong as it does not take into account the price for multiple instances of the same productID.
The following code also does not return objects for every product ID in the array which are the same. So if $pidArray contains three identical product ID's, the query will only return a collection with one object, instead of three.
$query = Product::select();
foreach ($pidArray as $id)
{
$query->orWhere('id', '=', $id);
}
$productDataForOrder = $query->get(['id','price']);
$totalAmount = $productDataForOrder->sum('price');
You're not going to be able to get duplicate data the way that you're trying. SQL is returning the rows that match your where clause. It is not going to return duplicate rows just because your where clause has duplicate ids.
It may help to think of it this way:
select * from products where id in (1, 1)
is the same as
select * from products where (id = 1) or (id = 1)
There is only one record in the table that satisfies the condition, so that is all you're going to get.
You're going to have to do some extra processing in PHP to get your price. You can do something like:
// First, get the prices. Then, loop over the ids and total up the
// prices for each id.
// lists returns a Collection of key => value pairs.
// First parameter (price) is the value.
// Second parameter (id) is the key.
$prices = Product::whereIn('id', $pidArray)->lists('price', 'id');
// I used array_walk, but you could use a plain foreach instead.
// Or, if $pidArray is actually a Collection, you could use
// $pidArray->each(function ...)
$total = 0;
array_walk($pidArray, function($value) use (&$total, $prices) {
$total += $prices->get($value, 0);
});
echo $total;
The whereIn method only limits the results to the values in the given array. From the docs:
The whereIn method verifies that a given column's value is contained within the given array
Id make a query variable and loop through the array adding to the query variable in each pass. Something like this:
$query = Product::select();
foreach ($pidArray as $id)
{
$query->where('id', '=', $id);
}
$query->get(['id','price']);
Here is a code that would work for your use case expanding on #patricus
You first fetch an array of key as id and value as price from the products table
$prices = Product::whereIn('id', $pidArray)->lists('price', 'id');
$totalPrice = collect([$pidArray])->reduce(function($result, $id) use ($prices) {
return $result += $prices[$id];
}, 0);

Doctrine create function from another

I have the following function that counts the unanswered questions:
public function getUnansweredQuestions(Company $company){
$qb = $this->createQueryBuilder("q");
$andX = $qb->expr()->andX();
$andX->add($qb->expr()->isNull("q.answer"));
$andX->add("user.company = :company");
$qb->setParameter("company", $company);
$andX->add($qb->expr()->in("bid.status", ":status"));
$qb->setParameter("status", [PurchaseBid::STATUS_PUBLISHED, PurchaseBid::STATUS_CLOSED]);
$qb->leftJoin("q.purchaseBid", "bid");
$qb->leftJoin("bid.createdBy", "user");
$qb->where($andX);
return $qb->getQuery()->getResult();
}
I need to ask only if there is a question (answered or unanswered). I don't understand the code very well, but a way from this function should be exists.
See Count Rows in Doctrine QueryBuilder for solutions how to count number of rows using the Doctrine Query Builder. I guess this solves your problem. Count > 1 => you have questions.

Get column number from column name

Is there any method to get the column number from the column name?
I can only retrieve the column name, and I need the column number for getCellMeta.
Thanks
Made this function that solved my problem:
function GetColFromName(name)
{
var n_cols = $editorTableContainer.handsontable('countCols');
var i = 1;
for (i=1; i<=n_cols; i++)
{
if (name.toLowerCase() == $editorTableContainer.handsontable('getColHeader', i).toLowerCase()) {
return i;
}
}
return -1; //return -1 if nothing can be found
}
This is almost what I required but not quite as I needed the column prop. I couldn't find the answer anywhere so thought I would add this to the thread that helped me.
instead of using 'getColHeader' use 'colToProp'.
Use propToCol("Column Name"). This returns the column's index.

Resources