cakephp pagination with AND OR condition inside loop - pagination

I am working with cakephp pagination i am using 2 group of check box for filter materialtype and occasion so i wrote following code
public function index($category) {
if(!empty($this->params['url']['data']['filter']['materialtype']))
{
foreach ($this->params['url']['data']['filter']['materialtype'] as $v){
$conditions1[] ="(Product.materialtype LIKE '%$v%')";
}
$conditions[] = implode(' OR ', $conditions1);
}
if(!empty($this->params['url']['data']['filter']['occasion']))
{
foreach ($this->params['url']['data']['filter']['occasion'] as $v){
$conditions2[] ="`Product`.`occasion` LIKE '%$v%'";
}
$conditions[] = implode(' OR ', $conditions2);
}
}
My following code is generating this sql query
SELECT `Product`.`id`, `Product`.`category`, `Product`.`name`, FROM mydb`.`products` AS `Product` WHERE `Product`.`category` = 'Necklace' AND (`Product`.`materialtype` LIKE '%Yellow Gold%') OR (`Product`.`materialtype` LIKE '%White Gold%') AND (`Product`.`occasion` LIKE '%Traditional%') OR (`Product`.`occasion` LIKE '%Modern%')
But I am looking for this output.
SELECT `Product`.`id`, `Product`.`category`, `Product`.`name`, FROM mydb`.`products` AS `Product` WHERE `Product`.`category` = 'Necklace' AND ((`Product`.`materialtype` LIKE '%Yellow Gold%') OR (`Product`.`materialtype` LIKE '%White Gold%')) AND ((`Product`.`occasion` LIKE '%Traditional%') OR (`Product`.`occasion` LIKE '%Modern%'))

You need to remove inner bracket from the inner statement inside the foreach. and add it at with outside like below.
if(!empty($this->params['url']['data']['filter']['materialtype']))
{
foreach ($this->params['url']['data']['filter']['materialtype'] as $v){
$conditions1[] = "Product.materialtype LIKE '%$v%'";
}
$str_cond = implode(' OR ', $conditions1);
$conditions[] = '(' . $str_cond . ')';
}
if(!empty($this->params['url']['data']['filter']['occasion']))
{
foreach ($this->params['url']['data']['filter']['occasion'] as $v){
$conditions2[] = "Product.occasion LIKE '%$v%'";
}
$str_cond = implode(' OR ', $conditions2);
$conditions[] = '(' . $str_cond . ')';
}

Related

Importing images along with other fields (username,subjectname) from excel in laravel

I am using phpspreadsheet. I want to import an excel sheet that have images too, it looks something like this,
I am able to retrieve fields separately and images separately, I want to get them together. Problem I am facing is that Images are being accessed with
$spreadsheet->getActiveSheet()->getDrawingCollection()
and for others field i have to access them like this
$spreadsheet->getRowIterator()
as both of them requires separate loops, should i be merging them into one or what is the right way so that i am able to retrieve both(images and fields) together.
Images retrieve code:
$spreadsheet = IOFactory::load($request->import_file);
$i = 0;
foreach ($spreadsheet->getActiveSheet()->getDrawingCollection() as $key => $drawing) {
if ($drawing instanceof MemoryDrawing) {
ob_start();
call_user_func(
$drawing->getRenderingFunction(),
$drawing->getImageResource()
);
$imageContents = ob_get_contents();
ob_end_clean();
switch ($drawing->getMimeType()) {
case MemoryDrawing::MIMETYPE_PNG :
$extension = 'png';
break;
case MemoryDrawing::MIMETYPE_GIF:
$extension = 'gif';
break;
case MemoryDrawing::MIMETYPE_JPEG :
$extension = 'jpg';
break;
}
} else {
$zipReader = fopen($drawing->getPath(), 'r');
$imageContents = '';
while (!feof($zipReader)) {
$imageContents .= fread($zipReader, 1024);
}
fclose($zipReader);
$extension = $drawing->getExtension();
}
$myFileName = time() .++$i. '.' . $extension;
$imagesCollection['answerImages_'.$key] =$myFileName;
file_put_contents('images/products/' . $myFileName, $imageContents);
$a = Answers::create([
'answerImages'=>$myFileName,
'questionId'=>($key <=4)?1:2,
]);
}
I want to store them into my table in database such that in questionImage column of database it has image name like this
and it is storing it currently but as I mentioned earlier i have to store them separtely
This is how i am storing other fields
$spreadsheet = IOFactory::load($the_file->getRealPath());
$sheet = $spreadsheet->getActiveSheet();
$row_limit = $sheet->getHighestDataRow();
$column_limit = $sheet->getHighestDataColumn();
$row_range = range( 1, $row_limit );
$column_range = range( 'F', $column_limit );
$startcount = 2;
$data = array();
foreach ( $row_range as $row ) {
$data[] = [
'courseName' =>$sheet->getCell( 'A' . $row )->getValue(),
'subjectName' => $sheet->getCell( 'B' . $row )->getValue(),
'question' => $sheet->getCell( 'C' . $row )->getValue(),
'questionImage' => $sheet->getCell( 'D' . $row )->getValue(),
];
$startcount++;
}
DB::table('questions')->insert($data);
How to get them together so that i can store them in one table
you should try maatwebsite/excel package. it will save your time.

How to extract initials from a name using Laravel

I have the method below that returns me a list of registered users:
$users = \App\Models\User::all();
It turns out that I would like to present only the initials of the names on that list.
Example:
Carlos Pereira do Nascimento = CN
Marcos Aurelio = MA
Sandra Lopes = SL
How could I do this by getting this data from the list?
Is it possible for me to treat this list by taking only the initials of the variable $ name?
You can use Laravel's accessor to get the initials modifying the following code:
public function getInitialsAttribute(){
$name = 'Carlos Pereira do Nascimento';
$name_array = explode(' ',trim($name));
$firstWord = $name_array[0];
$lastWord = $name_array[count($name_array)-1];
return $firstWord[0]."".$lastWord[0];
}
Now, you can get the initals using {{ $user->initials }}
Something like this should work:
$names = \App\Models\User::pluck('name');
$initials = [];
foreach($names as $name) {
$nameParts = explode(' ', trim($name));
$firstName = array_shift($nameParts);
$lastName = array_pop($nameParts);
$initials[$name] = (
mb_substr($firstName,0,1) .
mb_substr($lastName,0,1)
);
}
var_dump($initials);
Output:
array(1) {
["Carlos Pereira do Nascimento"]=>
string(2) "CN"
["Marcos Aurelio"]=>
string(2) "MA"
["Émile Durkheim"]=>
string(2) "ÉD"
}
Note the use of mb_substr as opposed to regular substr or a string index. This will return correct values for names starting with non ASCII characters like for example "Émile"
echo substr('Émile Durkheim', 0, 1);
// output: b"Ã"
echo 'Émile Durkheim'[0];
// output: b"Ã"
echo mb_substr('Émile Durkheim', 0, 1);
// output: É
For anyone looking for a simple, one-line, framework-agnostic solution:
$initials = preg_filter('/[^A-Z]/', '', $str);
I have just made the following PR to introduce a new Str::initials() String helper function in Laravel framework: https://github.com/laravel/framework/pull/40381
For those who already want to use this before it's accepted/merged, just extend Illuminate\Support\Str with this macro in your AppServiceProvider's boot() method:
Str::macro('initials', fn($value, $sep = ' ', $glue = ' ') => trim(collect(explode($sep, $value))->map(function ($segment) {
return $segment[0] ?? '';
})->join($glue)));
and then just use Str::initials('Foo Bar') or as an Eloquent accessor in your User model:
public function getInitialsAttribute(): string
{
return \Illuminate\Support\Str::initials($this->name);
}
so you can simply use something like {{ Auth::user()->initials }}.
Just Put this 2 line code
function initials($str) {
$ret = '';
foreach (explode(' ', $str) as $word)
$ret .= strtoupper($word[0]);
return $ret;
}
I just wanted to expand the answers above to help others looking to do the same.
Here's an example on what I did.
Create an Accessor in your user model:
public function getNameInitials()
{
$name = $this->name;
$name_array = explode(' ',trim($name));
$firstWord = $name_array[0];
$lastWord = $name_array[count($name_array)-1];
return mb_substr($firstWord[0],0,1)."".mb_substr($lastWord[0],0,1);
}
Then you can access it in your view as {{ $user->getNameInitials() }}
or you could easily access the initials of the authenticated user as follows {{ Auth::user()->getNameInitials() }}

I want to de-spaghettify this function

How can I make this function better? I don't like the fact I have to use a forEach to define manipulable content. I was thinking of running a reduce on find, but It's all too confusing for me.
_replace (content, find, replace, delimiter = '', findDelimiter = '') {
if (!Array.isArray(find)) find = [find]
let result = content
find.forEach(ref => {
result = result.split(findDelimiter).reduce((a, e) => a + delimiter + (this._reference[replace][this._reference[ref].indexOf(e)] || e), '')
})
return result
}

script score function not working but addDecayFunction is working of FunctionScore query

I am using Elastica and going to use \Elastica\Query\FunctionScore(); function score --> script_score. Here addDecayFunction() woking fine but addScriptScoreFunction() not work and not through any exception.
DecyFunction is commented because it is working
Here is code
$scriptString = "doc['geo_location'].distanceInMiles('42.946697', '-76.113623')";
$script = new \Elastica\Script($scriptString);
$query = new \Elastica\Query\FunctionScore();
$query->addScriptScoreFunction($script);
// $locationOrigin = "32.804654, -117.242594";
// $locationScale = '2mi';
// $query->addDecayFunction(\Elastica\Query\FunctionScore::DECAY_GAUSS, 'geo_location', $locationOrigin, $locationScale);
$resultSet = $type->search($query);
$results = $resultSet->getResults();
$totalResults = $resultSet->getTotalHits();
if ( $totalResults > 0 ) {
echo "<b>Total Results Found are:</b> " . $totalResults . "<br>";
foreach ( $results as $result ) {
echo $result->getScore();
$data = $result->getData();
var_dump($data);
}
}
maybe you forget to enable scripts?
script.disable_dynamic: false

Yii search with criteria and add parameters

I have one form and i want to search in my database. I create the object with all parameters but i have one problem. When write in one textfield search works fine and the query run correctly . When write two or more textfields params doesn't work and i have a fail execution of query :
WHERE
((((id_reservation=:id_reservation) AND (start=:start)) AND (end=:end)) AND
(fkCustomer.first_name=:first_name))
params doesn't replace.
$criteria=new CDbCriteria;
$criteria->with =array('fkCustomer');
if(!empty($start))
{
$criteria->addCondition('start=:start');
$criteria->params=array(':start'=>$start);
}
if(!empty($end))
{
$criteria->addCondition('end=:end');
$criteria->params=array(':end'=>$end);
}
if(!empty($merge->customer_name))
{
$criteria->addCondition('fkCustomer.first_name=:first_name');
$criteria->params=array(':first_name'=>$merge->customer_name);
}
if(!empty($merge->customer_surname))
{
$criteria->addCondition('fkCustomer.last_name=:last_name');
$criteria->params=array(':last_name'=>$merge->customer_surname);
}
if(!empty($merge->customer_email))
{
$criteria->addCondition('fkCustomer.email=:email');
$criteria->params=array(':email'=>$merge->customer_email);
}
$criteria->limit = 100;
It's because in every if block you replace the params array. Build an array in the if blocks then add it to $criteria->params on the last line, outside the blocks.
For instance:
$criteria=new CDbCriteria;
$criteria->with =array('fkCustomer');
$my_params = array();
if(!empty($end))
{
$criteria->addCondition('end=:end');
$my_params['end'] = $end;
}
if(!empty($merge->customer_name))
{
$criteria->addCondition('fkCustomer.first_name=:first_name');
$my_params['first_name'] = $merge->customer_name;
}
// other ifs ..
//then
$criteria->limit = 100;
$criteria->params = $my_params;
Also, if I remember correctly, you don't need to write ':end' and ':first_name' in the params array, it will work without the colon.
You also have the following alternative
$criteria=new CDbCriteria;
$criteria->with = 'fkCustomer';
if(!empty($end))
{
$criteria->compare('end', $end);
}
if(!empty($merge->customer_name))
{
$criteria->compare('fkCustomer.first_name', $merge->customer_name);
}
// The following conditions ..
// Limit:
$criteria->limit = 100;
Hi i think this is the same problem i have before with the params variable, for avoid this problem i use the CMap::mergeArray function
this happens because you overwrite the variable each time that the condition passed over it.
This is the syntax for avoid it, its an example
$criteria=new CDBCriteria;
$criteria->addBetweenCondition("Date",$datestart,$dateend);
$criteria->addCondition("Type=:type");
//$criteria->params=array(":type"=>"1"); //This is wrong, overwrites addBetweenCondition params
$criteria->params=CMap::mergeArray($criteria->params,array(
":type"=>"1",
)); //This is ok, mantain all parameters in the params var
$query=Model::findAll($criteria);
можно обратиться напрямую
$criteria=new CDbCriteria;
$criteria->with =array('fkCustomer');
if(!empty($start))
{
$criteria->addCondition('start=:start');
$criteria->params['start']=$start;
}
if(!empty($end))
{
$criteria->addCondition('end=:end');
$criteria->params['end']=$end;
}
if(!empty($merge->customer_name))
{
$criteria->addCondition('fkCustomer.first_name=:first_name');
$criteria->params['first_name']=$merge->customer_name;
}
if(!empty($merge->customer_surname))
{
$criteria->addCondition('fkCustomer.last_name=:last_name');
$criteria->params['last_name']=$merge->customer_surname;
}
if(!empty($merge->customer_email))
{
$criteria->addCondition('fkCustomer.email=:email');
$criteria->params['email']=$merge->customer_email;
}
$criteria->limit = 100;

Resources