Get value of Entity Object - php

I have picture like below.
I want to get value of project_id is 2,and number_request is 1.
But i can't get it.
I have use $data['items][0][project_id] and I print $data->items but i can't show it on screen.
Please help me.
Thank you so much.

Dumping objects doesn't necessarily give you an actual representation of the objects structure, but custom formatted debug information, defined via the magic __debugInfo() method.
Properties enclosed in brackets are special debug info, what is being shown there might have been gathered from anywhere but a property with the same name, see
https://github.com/cakephp/cakephp/blob/3.3.4/src/ORM/ResultSet.php#L593-L598
What you have there is basically a collection, so if you want the first entry of the collection, you can simply call first(), like
$entity = $data->first();
$projectId = $entity->project_id;
$numberRequest = $entity->numberRequest;
I would highly suggest that you study the docs a little more, as data access is really basic stuff.
See also
Cookbook > Database Access & ORM > Retrieving Data & Results Sets
Cookbook > Database Access & ORM > Query Builder > Selecting Rows From A Table
Cookbook > Database Access & ORM > Entities > Accessing Entity Data
Cookbook > Collections
API > \Cake\ORM\ResultSet

First you have to collect first object into an variable like
$val = $data->items; //its an object
$val1 = $val[0];
$projectId = $val1->project_id;
$NumberRequest = $val1->number_request;

Related

CakePHP ORM : Query with a join on the same table with a non-standard association

I have a very particular use case, and i can't find a clean solution with the ORM. I've searched a lot, and maybe my database model is not correct, I'm not sure.
I use CakePHP 3.8.11.
So, I have a table "MaintenanceTypes" with 3 important fields : id, name, and periodicity. Periodicity (in days) means "this maintenance is to be done every (for instance) 30 days".
Periodicity are like 7 (week), 30 (month), 90 (trimester) and so on.
I also have a table "Operations", they are little unit tests that belongs to a "MaintenanceType" (fields are id, name, maintenance_type_id).
What is special in this case, is that, as a business rule, Operations belonging to a MaintenanceType with a periodicity of 7 days is "included" in every MaintenanceType with a greater periodicity; that means that every trimester, you should do every Operations associated directly to the trimester, but also every Operations associated with the month, and the week, etc.
In raw SQL it's trivial :slight_smile:
mt_ref is the reference MaintenanceType, mt_inc are the included MaintenanceTypes (with a lesser periodicity) and finally, every Operations belonging to any of the MaintenanceTypes found.
SELECT mt_ref.id, mt_ref.name, mt_ref.periodicity,
mt_inc.name, mt_inc.periodicity, o.name
FROM maintenance_types mt_ref
LEFT JOIN maintenance_types mt_inc
ON (mt_inc.periodicity <= mt_ref.periodicity)
LEFT JOIN operations o ON (o.maintenance_type_id = mt_inc.id)
WHERE mt_ref.id = 3
I've tried to declare the association between MaintenanceTypes, but I can't find a way to declare that the association is done on the periodicity field, and, extra points, not on a equality but on a "less or equal".
To add extra difficulties, I use this query for a (very good) JQuery Datatables CakePHP plugin (https://github.com/allanmcarvalho/cakephp-datatables), so I can't simply pass the raw SQL, and I must use the ORM...
I hope this is clear, and that someone could help me on this one !
Thanks a lot !
If you need query builder instances, then pretty much have two options here that are more or less straightforward, that is either use associations with custom conditions, or manual joins.
Custom association conditions
With associations you'd probably do something like a self-association with MaintenanceTypes with a disabled foreign key and custom conditions, like so in your MaintenanceTypesTable class:
$this
->hasMany('MaintenanceTypesInc')
->setClassName('MaintenanceTypes')
->setForeignKey(false)
->setConditions(function (
\Cake\Database\Expression\QueryExpression $exp,
\Cake\ORM\Query $query
) {
return $exp->lte(
$query->identifier('MaintenanceTypesInc.periodicity'),
$query->identifier('MaintenanceTypes.periodicity')
);
});
Disabling the foreign key will prevent the ORM from creating the default A.fk = B.fk condition when joining in the association. It should be noted that you cannot contain a hasMany association with a disabled foreign key, you can only join it in! You could use a hasOne or even belongsTo association instead, but it would kinda be a lie, as you don't have a 1:1 relationship here (at least as far as I understand it).
Also note that you don't neccesarily have to use a callback with all expressions for the conditions, you could pass the conditions as a key => value array with a manually instantiated identifier expression, or even as simple string (the latter however will not be recognized when using automatic identifier quoting):
->setConditions([
'MaintenanceTypesInc.periodicity <=' =>
new \Cake\Database\Expression\IdentifierExpression('MaintenanceTypes.periodicity');
]);
->setConditions('MaintenanceTypesInc.periodicity <= MaintenanceTypes.periodicity');
Assuming you also have an association for Operations in your MaintenanceTypesTable class, you should be able to join in both, the new association and the Operations association via the query builders *JoinWith() methods, like this:
$query = $maintenanceTypesTable
->find()
->select([
'MaintenanceTypes.id', 'MaintenanceTypes.name', 'MaintenanceTypes.periodicity',
'MaintenanceTypesInc.name', 'MaintenanceTypesInc.periodicity',
'Operations.name',
])
->leftJoinWith('MaintenanceTypesInc.Operations');
In the results, the association data will be put under the _matchingData key, ie you can obtain it like $entity->_matchingData->MaintenanceTypesInc and $entity->_matchingData->Operations. If you don't want that, then you need to use aliases for the fields of the associations, like:
->select([
'MaintenanceTypes.id', 'MaintenanceTypes.name', 'MaintenanceTypes.periodicity',
'mt_inc_name' => 'MaintenanceTypesInc.name', 'mt_inc_periodicity' => 'MaintenanceTypesInc.periodicity',
'op_name' => 'Operations.name',
])
If you don't want to select all the fields everytime, use a custom finder as in the manual joins example below.
Manual joins
Using manual joins gives you complete freedom, with the query builders *Join() methods you can create whatever joins you like, and you don't have to use possible workarounds with associations.
You can add them in a custom finder for proper reusability, it could look something like this in your MaintenanceTypesTable class:
public function findWithIncludedMaintenanceTypes(\Cake\ORM\Query $query, array $options)
{
return $query
->select(/* ... */)
->leftJoin(
['MaintenanceTypesInc' => 'maintenance_types'],
function (
\Cake\Database\Expression\QueryExpression $exp,
\Cake\ORM\Query $query
) {
return $exp->lte(
$query->identifier('MaintenanceTypesInc.periodicity'),
$query->identifier('MaintenanceTypes.periodicity')
);
}
)
->leftJoin(
['Operations' => 'operations'],
function (
\Cake\Database\Expression\QueryExpression $exp,
\Cake\ORM\Query $query
) {
return $exp->equalFields(
'Operations.maintenance_type_id ',
'MaintenanceTypesInc.id'
);
}
);
}
Then you simply use the finder wherever you need it, like this:
$query = $maintenanceTypesTable
->find('withIncludedMaintenanceTypes');
Note that just like in the associations example, you can use string or array conditions for the custom joins too.
See also
Cookbook > Database Access & ORM > Associations - Linking Tables Together
Cookbook > Database Access & ORM > Query Builder > Loading Associations
Cookbook > Database Access & ORM > Query Builder > Loading Associations > Using leftJoinWith
Cookbook > Database Access & ORM > Query Builder > Loading Associations > Adding Joins
Cookbook > Database Access & ORM > Retrieving Data & Results Sets > Using Finders to Load Data
Cookbook > Database Access & ORM > Retrieving Data & Results Sets > Custom Finder Methods

MapReduce not working in CakePHP 3.x

I'm using CakePHP 3.x, my application has add/edit pages, in edit action I'm using this code.
$patient = $this->Patients->get($patientId);
to get record of patient.
Now I want to modify value of some field after find operation, let say I want to convert dob field (date_of_birth) into different date format, in CakePHP 2.x it's possible in afterFind callback but in CakePHP 3.x here in last paragraph it state that,
If you need to modify the results after they have been fetched you should use a Modifying Results with Map/Reduce function to modify the results. The map reduce features replace the ‘afterFind’ callback found in previous versions of CakePHP.
I had also use MapReduce but it won't work for me.
Map/reduce is kind of an overkill for such a simple task, I'd suggest to use a result formatter instead, ie Query::formatResults().
In order to use any of this, ie a mapper/reducer or a formatter, you must use Table::find() instead of Table::get(), as the latter doesn't return a query, but the result, and the options do not support mappers/reducers or formatters.
However, depending on where you need the formatted value, a helper, a virtual field, or just formatting when necessary might be the better option.
Anyways, here's a basic example:
$patient = $this->Patients
->find();
->where([
'id' => $patientId
])
->formatResults(function($results) {
/* #var $results \Cake\Datasource\ResultSetInterface|\Cake\Collection\CollectionInterface */
return $results->map(function($row) {
// note that now `dob` is a string!
$row['dob'] = $row['dob']->i18nFormat('dd. MMMM yyyy');
return $row;
});
})
->firstOrFail();
See also
Cookbook > Database Access & ORM > Entities > Creating Virtual Fields
Cookbook > Database Access & ORM > Query Builder > Adding Calculated Fields
API > \Cake\Datasource\QueryTrait::formatResults()
API > \Cake\I18n\Time::i18nFormat

Retrieving computed subset of columns in doctrine

I want to develop a RESTful API based on Slim Framework and Doctrine 2. I have a detailed permission management. So I have permissions defined as:
role:admin|entity:person|column:name|write:1
Im considering the most effective way to implement the right management into the web service.
Therefore I need to filter a computed subset of columns when building my query. What is the best place to do that, still enabling me to use all the default methods like findAll() etc. I could of course filter my fields like below:
$all = Article::createQuery('a')->getArrayResult();
/*this is getting ALL the fields -it would be better to filter before
retrieving from the db
*/
$allFiltered = array();
foreach($all as $index=>$article){
$filteredArticle = new Article();
foreach($user->getPermission('Article','r') as $permission){
$column = $permission->column;
$filteredArticle->$column = $article->$column;
}
$allFiltered[$index]=$filteredArticle
)
$app->response->setBody(json_encode($all));
Is there a way to do this at one place for all retrieving methods ?
Doctrrine2 can select partial object doc
You can fetch all permitted columns and just concatenate with a query ...

manipulate a result set from laravel eloquent

I've just picked up laravel after deciding to move to a php framework. I'm retrieving a result set of articles from a database using an eloquent query:
$posts = Article::select(array('articles.id','articles.article_date','articles.image_link','articles.headline','articles.category', 'articles.published'));
this works fine and results come out as expected.
However I now want to change the format of the article date from the mysql date format to another for the entire collection.
I thought about iterating through the object and changing using the usual php methods but wondered if there was an easier way to manipulate the data either when initiating the query or en mass with the object itself.
I've looked at mutators? but wasnt sure if this was appropriate or how to implement
Any help, pointers appreciated
You're right, mutators are the way to go. (Laravel 3 syntax)
Getter and Setter documentation for Eloquent models
public function get_article_date()
{
return date('d-m-Y H:i:s', strtotime($this->get_attribute('article_date'));
}
Getting the attribute
$articles = Articles::get(array(
'article_date',
'image_link',
'headline',
'published'
));
foreach($articles as $article)
{
echo $article->article_date;
}
Every time you get the date from your model it will run through the mutator first returning your modified result.
Absolutely no need to run raw queries for something like this.
EDIT got set and get mixed up... more coffee needed (answer edited)
Im not sure if this is working, but give it a try
$posts = Article::select(array('articles.id',DB::raw('CAST(articles.article_date as date)'),'articles.image_link','articles.headline','articles.category', 'articles.published'));

Can someone explain this snippet of magento code?

could some one please explain this snippet of magento code found in loadByCustomerId() in the class Mage_Sales_Model_Mysql4_Quote.
$read = $this->_getReadAdapter();
$select = $this->_getLoadSelect('customer_id', $customerId, $quote)
->where('is_active=1')
->order('updated_at desc')
->limit(1);
$data = $read->fetchRow($select);
When i var_dump($data) i see that its an array of customer data. What is model associated with this $data array? Thanks.
Magento "Models" (meaning the entities that allow you to interact with the database, not general purpose server/domain models) have two layers. The first is the "Model" layer. This contains methods for logical interactive with an model. (get me a customer's address, place the order, etc). The second layer is the "Resource Model" layer. Resource Models handle any interactive with the database (or,more generally, the data-store,or the persistance layer, or etc.).
The way a Resource Model interacts with the database is via adapter objects. One for reading information, another for writing information.
So, you're in the class Mage_Sales_Model_Mysql4_Quote. This is a Resource Model. It's the backend for the Mage_Sales_Model_Quote object, instantiated with
$model = Mage::getModel('sales/quote');
With this line
$read = $this->_getReadAdapter();
you're getting a reference to the model's read adapter. This will let you make queries to the database.
With this line
$select = $this->_getLoadSelect('customer_id', $customerId, $quote)
->where('is_active=1')
->order('updated_at desc')
->limit(1);
You're getting a reference to the SQL statement (also an object) that this Resource Model will use to load a sales/quote object.
//gets a reference
$this->_getLoadSelect('customer_id', $customerId, $quote)
Then, you're calling methods on that object to alter it with additional logic
->where('is_active=1')
->order('updated_at desc')
->limit(1);
In pseudo sql, a query might look like this normally
SELECT * FROM quote_table;
But after you call those methods, the query will look something like
SELECT * FROM quote_table
WHERE is_active = 1
ORDER BY updated_at desc
LIMIT 1;
Finally,
$data = $read->fetchRow($select);
here you're using the read adapter you fetched earlier to make a query into the database for the specific quote item row that your query will fetch.
_getReadAdapter() gets the read-only database connection. _getLoadSelect creates a select query on the model's (Mage_Sales_Model_Mysql4_Quote) main table. The data returned is just raw data from the SQL query not associated with any particular backend model.

Categories