Cake Php Read function to retrieve result as 1-Dimensional array - cakephp

Cake Php Read function to retrieve result as simple array
$result = $this->Model->read('id, name, title', $id);
It will result as
Array
(
[Model] => Array
(
[id] => 1
[name] => test
[title] => New Head title
)
)
It there any way to retrieve result array directly from query as below
Array
(
[id] => 1
[name] => test
[title] => New Head title
)
Without using any temp storage of a variable.

Just run the result through a Set::extract call, like this:
$result = $this->Model->read('id, name, title', $id);
$result = Set::extract('/Model', $result);
Set is a very powerful class, I suggest you read on it. :)
Cheers.

CakePHP purity aside (agree with other posters though)
Is find('list') what you are looking for?
$result = $this->Model->find('list', array('fields' => array('id', 'name', 'title'), 'conditions' => array('id' => $id), 'recursive' => 0 ));

Unless you're going to hack the Cake core, Cake will always internally return the results using the extra model key. So "without using any temp storage of a variable" is pretty much impossible, if you mean this in terms of "speed optimization" (in quotes, because it hardly makes any difference).
You can make it work simply with:
$result = current($this->Model->read('id, name, title', $id));
You could override the model's read method so it always does this internally (not recommended, it'll come to bite you one day). You could do so in the AppModel to have this behavior globally.

Related

Ways to use array in cakephp

Hello I am having a tought time figuring out how to use arrays in cakephp. right now i have a view with 2 columns, active and startYear. i need to grab the start years for all of the columns in the view and sho i have this code.
public function initialize(array $config)
{
$this->setTable('odb.SchoolYear');
}
controller
public function index()
{
$deleteTable = $this->loadModel('DeletedTranscripts');
$this->$deleteTable->find('all', array(
'conditions' => array(
'field' => 500,
'status' => 'Confirmed'
),
'order' => 'ASC'
));
$this->set('startYear',$deleteTable );
}
once i have the array captured and put into lets say startYear can in input a statement like this into my dropdown list to populate it?
<div class="dropdown-menu">
<a class="dropdown-item" href="#"><?= $delete->startYear; ?></a>
</div>
i have been looking for answers for quite awhile any help would be awesome.
Couple of things:
Loading Tables in CakePHP
For this line:
$deleteTable = $this->loadModel('DeletedTranscripts');
While you can get a table this way, there's really no reason to set the return of loadModel to a variable. This function sets a property of the same name on the Controller, which almost correctly used on the next line. Just use:
$this->loadModel('DeletedTranscripts');
Then you can start referencing this Table with:
$this->DeletedTranscripts
Additionally, if you're in say the DeletedTranscriptsController - the corresponding Table is loaded for you automatically, this call might be unnecessary entirely.
Getting Query Results
Next, you're close on the query part, you've can start to build a new Query with:
$this->DeletedTranscripts->find('all', array(
'conditions' => array(
'field' => 500,
'status' => 'Confirmed'
),
'order' => 'ASC'
));
But note that the find() function does not immediately return results - it's just building a query. You can continue to modify this query with additional functions (like ->where() or ->contain()).
To get results from a query you need to call something like toArray() to get all results or first() to get a single one, like so:
$deletedTranscriptsList = $this->DeletedTranscripts->find('all', array(
'conditions' => array(
'field' => 500,
'status' => 'Confirmed'
),
'order' => 'ASC'
))->toArray();
Sending data to the view
Now that you've got the list, set that so it's available in your view as an array:
$this->set('startYear', $deletedTranscriptsList );
See also:
Using Finders to Load Data
Setting View Variables
I also noticed you've had a few other related questions recently - CakePHP's docs are really good overall, it does cover these systems pretty well. I'd encourage you to read up as much as possible on Controller's & View's.
I'd also maybe suggest running through the CMS Tutorial if you've not done so already, the section covering Controllers might help explain a number of CakePHP concepts related here & has some great working examples.
Hope this helps!

How to get only one row from a table using cakephp

I'm trying to retrieve data from one of the rows of a table using cakephp, and I want to get the values from the extracted row.
P.s. I've tried to follow cakephp's find(), but did not get anything, got an error instead.
Error`$login_id = $this->AppAuth->user('id');
$userSettings= $this->loadModel("UserSettings");
$userSetting= $this->$userSettings->find('first', array(
'conditions' => array('UserSettings.user_id' => $login_id)));`
From cakephp siteGot it.
$query = $internSettings->find('all', [
'conditions' => ['InternSettings.intern_id' => $login_id]
]);
$row = $query->first();
Now that I can retrieve a row, how am I suppose to access the values of the row?
$record = $internSettings->find('all', [ 'conditions' => ['InternSettings.intern_id' => $login_id]])->first();
This will returns Entity object in $record, you can access field by
echo $record->field_name;
or you can convert it in array and then you can access
$recordArr=$record->toArray();
echo $recordArr['field_name'];

Dynamically add virtual field in cakephp

I am using CakePHP 2.1.3; I want to create a virtual field dynamically in a controller. Is it possible?
The problem is when I am trying to find max value in a table it gives me another array from the model array. Please ask if you need more information.
When I am trying to execute the following query,
$find_max_case_count = $this->CaseMaster->find('first', array(
'conditions' => array(
'CaseMaster.CLIENT_ID' => $client_id,
'CaseMaster.CASE_NO LIKE' => '%-%'
),
'fields' => array('max(CaseMaster.CASE_NO) AS MAX_NO')
));
It is giving me an array like:
[0]=> array([MAX_NO]=> 52)
However I want it to be like as:
[CaseMaster] => array([MAX_NO] => 52)
I found a solution. I can make the virtual field at runtime. The code should looks like:
$this->CaseMaster->virtualFields['MAX_NO'] = 0;
Write it just above the find query and the query will remain same as it was written.
This link was helpful to find out the solution.
There is no way (as far as I am knowledgeable) to create virtual fields "on the fly". What virtual fields are is "arbitrary SQL expressions" that will be executed when a find runs through the Model and "will be indexed under the Model's key alongside other Model fields".
What do you need to do with "dynamically created virtual fields"? If you explain what exactly you need to accomplish maybe we can provide a different (even more suitable? :) ) solution? I'd personally be happy to help you.
After you editing your question I can say that what you're getting is the way the array should be returned, this is because of the fields parameter. If you want to get a different structure out of it I suggest applying a callback to format it.
Firstly move the method inside the CaseMaster Model:
public function getMaxCaseCount($client_id){
$data = $this->find('first', array(
'conditions' => array(
'CaseMaster.CLIENT_ID' => $client_id,
'CaseMaster.CASE_NO LIKE' => '%-%'),
'fields' => array('max(CaseMaster.CASE_NO) AS MAX_NO')));
return array_map(array('CaseMaster', '__filterMaxCaseCount'), $data);
}
private function __filterMaxCaseCount($input){
//This is just an example formatting
//You can do whatever you would like here.
$output['CaseMaster'] = $input[0];
return $output;
}
The array_map function will apply the __filterMaxCaseCount callback method so that when you call:
$this->CaseMaster->getMaxCaseCount($client_id);
from your controller you will get the data in the way you need it. The array_map function could also look like this:
return array_map(array($this, '__filterMaxCaseCount'), $data);
because you're in the same Class.
Just adding your model alias to field definition also works for this purpose
'fields' => array('max(CaseMaster.CASE_NO) AS CaseMaster__MAX_NO')

Complex find statement, don't know how to write multiple values for one condition

I am trying to build a paginated find call to my Unit model. I need the condition to be that it looks for unit.type of condo and rentalco, house and rentalco, but NOT rentalco and hotel. Additionally, the way I have my code worded, cake only returns unit types that are rentalco.
public function view($type=null) {
$this->set('title', 'All '.$type.' in and near Gulf Shores');
$this->set('featured', $this->Unit->getFeatured());
$this->paginate['Unit']=array(
'limit'=>9,
'order' => 'RAND()',
'contain'=>array(
'User'=>array('id'),
'Location',
'Complex',
'Image'
),
'conditions'=>array(
'Unit.type'=>array($type, 'rentalco'),
'Unit.active'=>1)
);
$data = $this->paginate('Unit');
$this->set('allaccommodations', $data);
$this->set('type', $type);
}
UPDATE I figured out why my find statement wasn't working (just had been passing the word condos instead of condo into my browser bar....derp derp); however, I would still love to know how I can tell cake to NOT allow a find with both type hotel and rentalco.
You are looking for the NOT. It would be something like:
'conditions' => array(
'NOT' => array('Unit.type' => array('hotel', 'rentalco')),
),
To be more specific, I would need to see your model schema.

Get threaded results for associated model in CakePHP

I have 2 database-tables which are connected as followed:
ProjectProduct hasMany Bde
Bde belongsTo ParentBde / Bde hasMany ChildBde
The first association is new and shall be added into the application now. Since then I used $this->Bde->find('threaded') to get an threaded array of these records.
Now I need/want to query the ProjectProduct-table and wanted to use the containable-behavior to get all associated Bdes.
Now I'm wondering: Is it possible (in a Cake way) to still get threaded results with a call of find on ProjectProduct?
I tried doing $this->ProjectProduct->find('threaded', array('contain' => 'Bde')) but this will try to get threaded results on ProjectProduct.
I'm expecting an array like this:
Array (
[ProjectProduct] => Array (
[id] => 17,
[Bde] => Array (
[0] => Array (
[id] => 1,
[project_product_id] => 17,
[children] => Array()
)
)
)
)
Since I couldn't find any information how this can be done in one call or the "Cakish" way, I've done it like this:
$project_products = $this->Project->ProjectProduct->find('all');
foreach ($project_products as $key => $project_product) {
$project_products[$key]['Bde'] = $this->Project->Bde->find('threaded', array('conditions' => array('Bde.project_product_id' => $project_product['ProjectProduct']['id'])));
}
If someone has a better way in doing this I really appreciate any other ideas!

Resources