How to change this: [ [object1], [object2] ] to this: [ object1, object2 ] in php - php

controller:
$sold_fruits = [];
foreach ($clients as $client) {
$sold_fruits[] = $client->bought_fruits;
}
$supermarkets = [];
foreach ($sold_fruits as $sold_fruit) {
// HERE: I want to stop using this [0]
$supermarkets[] = $sold_fruit[0]->supermarket;
}
client model:
public function bought_fruits()
{
return $this->hasMany(BoughtFruits::class);
}
sold fruits model:
public function supermarket()
{
return $this->belongsTo(Supermarket::class);
}
In the first loop Im getting something like this:
[[obj1],[obj2]]. Thats why I have to use that [0] in there!
Is there any good way to stop using that [0]??

You can achieve your goal easily by using Laravel collection functions.
Use flatMap() when where there is an array of items in a property.
Use map() when there is only one item in a property.
In your case
There are many bought_fruits for a client, so use flatMap()
There is one supermarket for a bought_fruit, so use map()
$superMarkets = collect($clients)
->flatMap->bought_fruits
->map->supermarket;

You try to put index number in the array like these below.
$sold_fruits = [];
foreach($clients as $key => $value){
$sold_fruits[$key] = $value;
}
$supermarkets = [];
foreach($sold_fruits as $key => $value){
$supermarkets[$key] = $value;
}
NOTE: This is just to answer the question, scroll down more to see the other approach.

Related

Laravel Foreach Controller vs View

I realized something I can't figure out by myself.
I get a different result when I loop through first in a Controller and pass then the result to my view. Versus loop straight in my view.
For instance:
I have this in my Controller:
public function index()
{
$subscribers = Subscriber::where('user_id', Auth::user()->id)->orderBy('created_at','asc')->get();
foreach ($subscribers as $key => $subscriber) {
$var = $subscriber->name;
}
return view('backend.newsletter.contacts.index')->withSubscribers($subscribers)
->withVar($var);
}
by using {{$var}} in my view I get only "John" as a result.
But when I use the foreach loop in my view instead of in the Controller:
#foreach($subscribers as $key => $subscriber)
{{$subscriber->name}}
#endforeach
I get two results, "John" and "Dan". This makes totaly sense as I have two entries in my DB.
So how does it come that I get two different results here ?
When you're doing this:
foreach ($subscribers as $key => $subscriber) {
$var = $subscriber->name;
}
With each iteration you overwrite $var so you always get the last value. For example, if you have ['Dan', 'John, 'Alice', 'Alan'], you'll get Alan.
Good practice is too pass data to a view and iterate it with #foreach.
Because only the last loop iteration is stored in $var.
You need to
$var = [];
foreach ($subscribers as $key => $subscriber) {
$var[] = $subscriber->name;
}
You are overriding $var in the loop.
Try this:
$var = [];
foreach ($subscribers as $key => $subscriber) {
$var[] = $subscriber->name; // Appends name to array
}

My Array inside a foreach loop is not accepting a variable in PHP & Laravel

I have a Category array that I'm looping through and counting the subcategories that have their Category ID as the ID of the current item in the loop. It is retrieving the county just fine, uynfportunately when adding to the array it adds the value of zero. When echoed out, the values are as they should be, its only when inserting into the array the value becomes a zero.
This is the code I'm working with in PHP. I am using the Laravel framework.
public function index()
{
$categories = $this->categories->get()->toArray();
$categories_array = array();
$stats = array();
// dd($categories);
foreach ($categories as $key => $value)
{
$subcats_number = sub_categories::whereCategory_id($value['id'])->count();
$stats = array_add($stats, 'subcategories', $subcats_number);
echo $subcats_number.'<br/>';
$listings = classifieds::whereCategory_id($value['id'])->count();
$stats = array_add($stats, 'listings', $listings);
$categories_array = array_add($categories_array, $value['name'], $stats);
}
dd($categories_array);
// return view('admin.categories', compact('categories_array'));
}
The result of my dd:
Dump Result
I am not sure that array_add() helper is appropriate for your function here. As the doc says "The array_add function adds a given key / value pair to the array if the given key doesn't already exist in the array", and I am not sure that this is the proper behavior you need.
I would rather use a simple array_push() here:
public function index()
{
$categories = $this->categories->get()->toArray();
$categories_array = array();
foreach ($categories as $key => $value)
{
$subcats_number = sub_categories::whereCategory_id($value['id'])->count();
$listings = classifieds::whereCategory_id($value['id'])->count();
$stats = array('subcategories' => $subcats_number,'listings' => $listings);
array_push($categories_array,$value['name'] => $stats);
}
dd($categories_array);
}
Otherwise, you should also declare the $stats array into your loop if you choose to keep the array_add() function...

Laravel 5 WhereIn Not Working

I have no idea why my query is suddenly not working (although maybe it was never working to begin with). Is there anything wrong here?
My controller;
$dataset = $postcode_lookup->dataset; // will return "201502_postcode"
$postcode_extract = new PostcodeExtract;
$postcode_extract = $postcode_extract->setTableByDate($dataset);
foreach ($input as $column => $values) {
$postcode_extract->orWhere(function ($query) use ($column, $values) {
$query->whereIn($column, $values);
});
}
/*
* Temporarily print out the raw SQL...
*/
$sql = str_replace(['%', '?'], ['%%', "'%s'"], $postcode_extract->toSql());
$fullSql = vsprintf($sql, $postcode_extract->getBindings());
print_r($fullSql);
exit;
My model;
<?php namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class PostcodeExtract extends Model {
protected $connection = 'postcodes';
public function setTableByDate($selected_tablename)
{
$this->table = $selected_tablename;
// Return $this for method chaining
return $this;
}
public function getTable()
{
if (isset($this->table))
$this->setTableByDate($this->table);
return $this->table;
}
All that the print out of the raw sql is returning is select * from 201502_postcode and is just ignoring the rest of the query.
This is my $input array;
Array
(
[country] => Array
(
[0] => L93000001
[1] => M83000003
)
[county] => Array
(
[0] => 95
)
)
orWhere and whereIn is just being ignored it seems..
--- UPDATE ---
I didn't know about orWhereIn. But having tried this;
foreach ($input as $column => $values) {
$postcode_extract->orWhereIn($column, $values);
print "<br>";
print $column;
print "<br>";
print_r($values);
print "<br>";
}
I still get the same result. It's like this loop is being totally ignored - even though I can get these print's/print_r's to work. The raw SQL is still just select * from 201502_postcode.
Try this
$postcode_extract->orWhereIn($column, $values)
Also, if that doesnt work, try making the first one condition a whereIn and the rest a orWhereIn
Oh this is so frustratingly obvious I think I might cry...
foreach ($input as $column => $values) {
$postcode_extract = $postcode_extract->orWhereIn($column, $values);
}

decode mysql query before returning it to view

I'm running a query to mysql that returns encrypted data. I'd like, if possible, to decode the results before sending it to the view. It seems like better form to handle the decoding in the controller (or even the model) rather than inside the view.
I can't seem to wrap my head around how to do it, though.
I was thinking I could iterate through the object, decodode it, and push it to another array that would be sent to the view. Problem with this is I won't know (and need to keep) the indexes of the query.
So the query might return something like:
[id] => 742
[client_id] => 000105
[last] => dNXcw6mQPaGQ4rXfgIGJMq1pZ1dYAim0
[first] => dDF7VoO37qdtYoYKfp1ena5mjBXXU0K3dDlcq1ssSvCgpOx75y0A==
[middle] =>iXy6OWa48kCamViDZFv++K6okIkalC0am3OMPcBwK8sA==
[phone] => eRY3zBhAw2H8tKE
Any ideas?
Ended up with:
function name(){
$data['e_key']=$this->e_key;
$clid = $this->uri->segment(3);
$name = $this->Clients_model->getNameData('*','client_id='.$clid,'');
$nameArray= array();
foreach ($name->result() as $row){
$x = $row;
$keys = array('id','client_id');
$unenc = array();
foreach ($x as $key=>$value){
if(! in_array($key, $keys)){
$unenc[$key]=$this->encrypt->decode($value,$this->e_key);
}else{
$unenc[$key]=$value;
}
}
array_push($nameArray,$unenc);
}
$data['name'] = $nameArray;
$this->load->view('names/name_view',$data);
}
Assuming you know how to decrypt the data, it's but a matter of iterating over the object, decrypting the encrypted fields.
If $YOUR_OBJECT is your object and your function for decryption is decode() then the following code should do the trick.
// The keys corresponding to the encrypted fields
$encoded = array('last', 'first', 'middle', 'phone');
$decoded = array();
foreach($YOUR_OBJECT as $key => $value)
{
if (in_array($key, $encoded))
{
$decoded[$key] = decode($value);
}
}
if it's a particular index, you could decode it like
$result['last'] = base64_decode($result['last']);
or in the model, use mutators and accessors:
public function setUp() {
$this->setTableName('tablename');
$this->actAs('Timestampable');
$this->hasMutator('last', '_encode64');
$this->hasAccessor('last', '_decode64');
}
protected function _encode($value) {
$this->_set('last',base64_encode($value));
}
protected function _decode($value) {
return base64_decode($value); // not sure on this one - might have to
// return $this->set('last', base64_decode($value));
}

Declarative access to structured PHP variable without foreach loops

Background
Assume I have the following nested variable in PHP.
$data = Array(
Array('lname' => 'Simpson','fname' => 'Homer','age' => '35','motto' => '_blank_'),
Array('lname' => 'Simpson','fname' => 'Marge','age' => '34','motto' => '_blank_'),
Array('lname' => 'Flintstone','fname' => 'Fred','age' => '33','motto' => '_blank_'),
Array('lname' => 'Flintstone','fname' => 'Wilma','age' => '29','motto' => '_blank_')
);
Assume also the standard methods for accessing specific values:
print($data[0]['fname']); // Homer
print($data[1]['age']); // 34
Question
Is there an existing library or framework that would allow me to easily
acess specific values declaratively, without using foreach loops?
$test = $data->get_record_by_fname['Homer']
print $test['age'] //35
If you really wanted to overkill everything, you could try an approach using magical methods!
class Simpsons
{
protected $_data = array();
public function __construct(array $data)
{
$this->_data = array_map(function ($i) { return (object)$i; }, $data);
}
public function __call($method, $args)
{
if (count($args) == 0)
return NULL;
foreach ($this->_data as $row)
{
if (property_exists($row, $method) && $row->$method == $args[0])
{
return $row;
}
}
return NULL;
}
}
Usage:
$p = new Simpsons($data); // Stored in the format provided
var_dump($p->fname('Homer')); // Gets the record with fname = Homer
Is there a particular reason you don't want to use foreach loops? If it's merely for conciseness, you could just declare the function yourself, it's fairly trivial:
function get_record($set, $field, $value) {
foreach($set as $key => $val) {
if($val[$field] === $value) return $set[$key];
}
return NULL;
}
Then your example would become:
$test = get_record($data, 'fname', 'Homer');
print $test['age']; //35
class SomeClass{
// Stores the Array of Data
public $data;
// Sets up the object. Only accepts arrays
public function __construct(array $data)
{
$this->data = $data;
}
// Gets a record based on the key/value pair
public function getByKey($key, $value)
{
foreach($this->data as $array)
{
if(is_array($array)
{
if(array_key_exists($key, $array) && $array[$key] == $value)
{
return $array;
}
}
}
}
}
$array = array( 1 => array("Test" => "Hello"));
$obj = new SomeClass($array);
$record = $obj->getByKey('Test', 'Hello');
This lets you get a record based on what a key/value pair inside the array is. Note, the type hinting in the constructor is PHP 5.3(?)
BTW, No, there is no way to escape the foreach as even internal PHP functions (anything beginning with array_) uses a foreach or some other type of loop. However, if you encapsulate the loop into a class, you don't have to think about it.

Categories