Return object base on request uri - php

so I have this modular web application that has doctrine2 intergrated with zend framework 1.12.
So I want to return one object base on the request uri, for example: url/api/people/1, which return the person one base on their id.
*side note, I can return all objects of people, I just want to select one object once the user enter's a number.
What I have tried, was to grab the parameter from the url and just pass it through the find function, but doctrine doesn't understand these numbers passed through the uri, and believes they're actions.
if($this->getRequest()->isGet())
{
$request = $this->getRequest();
$id = $request->getParam('peopleId');
$em = $this->getEntityManager();
$peopleRepo = $em->getRepository('API\Entity\People');
$people = $peopleRepo->find(3); //$id goes into find function
$resultArray[] =
[
'id' => $people->getId(),
'firstname' => $people->getFirstName(),
'lastname' => $people->getLastName(),
"food" => $people->getFavoriteFood()
];
echo json_encode($resultArray, JSON_PRETTY_PRINT);
var_dump($people);
*****EDIT*****
So I have added code that I can manually find one person, but I want to do that through the url, how can I achieve this?

Try:
$peopleRepo = $em->getRepository('API\Entity\People')->findBy(array('id' => $id));
Or
$peopleRepo = $em->getRepository('API\Entity\People')->findById($id);
See Doctrine docs:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-objects.html#by-simple-conditions

Related

How to get insert id after save to database in CodeIgniter 4

I'm using Codeigniter 4.
And inserting new data like this,
$data = [
'username' => 'darth',
'email' => 'd.vader#theempire.com'
];
$userModel->save($data);
Which is mentioned here: CodeIgniter’s Model reference
It's doing the insertion.
But I haven't found any reference about to get the inserted id after insertion.
Please help! Thanks in advance.
This also works.
$user= new UserModel();
$data = [
'username' => 'darth',
'email' => 'd.vader#theempire.com'
];
$user->insert($data);
$user_id = $user->getInsertID();
I got a simple solution after researching on the core of the CI 4 framework.
$db = db_connect('default');
$builder = $db->table('myTable');
$data = [
'username' => 'darth',
'email' => 'd.vader#theempire.com'
];
$builder->insert($data);
echo $db->insertID();
Hope they'll add a clear description on the docs soon.
There are three way to get the ID in ci4:
$db = \Config\Database::connect();
$workModel = model('App\Models\WorkModel', true, $db);
$id = $workModel->insert($data);
echo $id;
echo '<br/>';
echo $workModel->insertID();
echo '<br/>';
echo $db->insertID();
In fact, what you did is correct.
You did it in the best and easiest way and following the Codeigniter 4 Model usage guide.
You just missed: $id = $userModel->insertID;
Complete code using your example:
$data = [
'username' => 'darth',
'email' => 'd.vader#theempire.com'
];
$userModel->save($data);
$id = $userModel->insertID;
That's it. You don't need all this code from the examples above nor calling database service or db builder if you're using codeigniter's models.
Tested on CodeIgniter 4.1.1 on 3/19/2021
To overcome this, I modified system/Model.php in the save() method---
$response = $this->insert($data, false);
// add after the insert() call
$this->primaryKey = $this->db->insertID();
Now, in your models, you can just reference "$this->primaryKey" and it will give you the needed info, while maintaining the data modeling functionality.
I'm going to submit this over to the CI developers, hopefully it will be added in.
For CI4
$settings = new SettingsModel();
$settingsData = $settings->find(1);
<?php namespace App\Models;
use App\Models\BaseModel;
class SettingsModel extends BaseModel
{
protected $table = 'users';
protected $primaryKey = 'id';
}
$settings->find(1); will return a single row. it will find the value provided as the $primaryKey.
hi guys in my case i use ci model to save data and my code is :
$x=new X();
$is_insert= $x->save(['name'=>'test','type'=>'ss']);
if($is_insert)
$inserted_id=$x->getInsertID()
I'm using mysql for my database then I ran this inside my seeder
$university = $this->db->table('universities')->insert([
'name' => 'Harvard University'
]);
$faculty = $this->db->table('faculties')->insert([
'name' => 'Arts & Sciences',
'university' => $university->resultID
]);
Look at code line 6
$university->resultID
variable $university here is type object of CodeIgniter\Database\MySQLi\Result class
Corect me if I'm wrong or any room for improvements
I had the same problem but, unfortunately, the CI4 documentation doesn't help much. The solution using a builder woks, but it's a workaround the data modeling. I believe you want a pure model solution, otherwise you wouldn't be asking.
$data = [
'username' => 'darth',
'email' => 'd.vader#theempire.com'
];
$id = $userModel->save($data);
Trying everything I could think of I decided to store the result of the save method to see if returned a boolean value to indicate if the saving was sucessful. Inspecting the variable I realized it returns exactly what I wanted: the lost insertID.
I believe CodeIgniter 4 is quite an easy and capable framework that does a decent job in shared hosts where other frameworks can be a little demanding if you're learning but lacks the same fantastic documentation and examples of CI3. Hopefully, that's only temporary.
By the way, you code works only if you are using the $userModel outside the model itself, for example, from a Controller. You need to create a model object like:
$userModel = New WhateverNameModel();
$data = [any data];
$userModel->save($data);
Alternatively, if you are programming a method inside the model itself (my favorite way), you should write
$this->save($data);

Firebase PHP: Updating also deletes the other children

I am using the Firebase PHP Admin SDK: https://firebase-php.readthedocs.io/en/stable/realtime-database.html#update-specific-fields
Here is the example it gives to update specific fields:
$uid = 'some-user-id';
$postData = [
'title' => 'My awesome post title',
'body' => 'This text should be longer',
];
// Create a key for a new post
$newPostKey = $db->getReference('posts')->push()->getKey();
$updates = [
'posts/'.$newPostKey => $postData,
'user-posts/'.$uid.'/'.$newPostKey => $postData,
];
$db->getReference() // this is the root reference
->update($updates);
From that, I created a users class and in that I have an update function. Like so:
public function update() {
$data = array('users' => array('1' => 'David'));
$this->database->getReference()->update($data);
return true;
}
In my database I have this structure:
Now if I run that function $users->update();
It removes the other child and only leaves David. Like so:
How can I update only a specific value of a specified key without it overriding the other data?
There's nothing specific to PHP here. That's the way Realtime Database update operations work. If you want a minimal update, you have to target the deepest key that you want to update. In your case, since you're storing an array type object, the keys are the number indexes of the array items you've written. If you want to modify one of them, you need to build a reference that includes the child number you want update. In that case, none of the sibling values will be touched.
Try this instead:
$this->database->getReference('users')->update(array('1' => 'David'));
Notice here that the update is rooted at "users", and you're updating just the immediate child "1" of that.
The example on docs is a little bit hard to grasp as a beginner. I have made it simpler for you to understand.
Once you get the newPostKey, prepare the url for child and run the code. It will only change the specific fields.
$ref = 'users/' . $newPostKey;
$updates = [
'title' => 'Updated title',
'body' => 'Updated body text',
];
$set = $db->getReference($ref)->update($updates);

PhalconPHP - get specific object with multiple relations

I have a model, call it Robot, which has multiple manyToMany relationships with other models - Part, Country and Permision. Relation models being RobotsParts, RobotsCountries and RobotsPermissions.
Each robot can have multiple or no parts, countries and permissions linked to them.
To get all the robots with a certain part, PhalconPHP makes it easy. (aliases being properly set in models, of course).
$part = Part::findFirstByName("arm");
$robotsWithPart = $part->robots;
The same thing applies for robots with a certain country:
$country = Country::findFirstByCode("HR");
$robotsWithCountry = $country->robots;
But how can one get only robots with a certain part, country and permission?
I've had futile attempts like:
$country = Country::findFirstByCode("HR");
$part = Part::findFirstByName("arm");
$robots = $country->getRobots([
'conditions' => "(partId = :pid:)",
'bind' => [
'pid' => $part->id
]
]);
But, of course, partId is not recognized as it doesn't belong to any of the selected models;
You can use the $model->getRelated('model', $parameters = []) option.
$parameters = [] works the same as how you would normally query a model. i.e; it takes the parameters order, limit, conditions, ...
$country = Country::findFirstByCode("HR");
$part = Part::findFirstByName("arm");
$robots = $country->getRelated('Robot', ['partId = ' . $part->id]);
You can find this in the documentation
UPDATE
That sounds like it wouldn't be possible. You will have to call a custom query on your Robot model. Something like this:
$result = Robot::query()
->join('Country', 'Country.id = Robot.countryId')
->join('Part', 'Part.robotId = Robot.id')
->where('Country.code = :code:')
->where('Part.name = :name:')
->bind(['code' => 'HR', 'name' => 'arm'])
->execute();
You can also use the Querybuilder, if you prefer to use that.

Passing dependency parameters to App::make() or App::makeWith() in Laravel

I have a class that uses a dependency. I need to be able to dynamically set parameters on the dependency from the controller:
$objDependency = new MyDependency();
$objDependency->setSomething($something);
$objDependency->setSomethingElse($somethingElse);
$objMyClass = new MyClass($objDependency);
How do I achieve this through the Service Container in Laravel? This is what I've tried but this seems wrong to me. In my AppServiceProvider:
$this->app->bind('MyClass', function($app,$parameters){
$objDependency = new MyDependency();
$objDependency->setSomething($parameters['something']);
$objDependency->setSomethingElse($parameters['somethingElse']);
return new MyClass($objDependency);
}
And then in the controller i'd use this like:
$objMyClass = App:make('MyClass', [
'something' => $something,
'somethingElse' => $somethingElse
]);
Is this correct? Is there a better way I can do this?
Thanks
You can see detailed documentation here: https://laravel.com/docs/5.6/container#the-make-method
It's done like this:
$api = $this->app->makeWith('HelpSpot\API', ['id' => 1]);
Or use the app() helper
$api = app()->makeWith(HelpSpot\API::class, ['id' => 1]);
It is essential to set the array key as the argument variable name, otherwise it will be ignored. So if your code is expecting a variable called $modelData, the array key needs to be 'modelData'.
$api = app()->makeWith(HelpSpot\API::class, ['modelData' => $modelData]);
Note: if you're using it for mocking, makeWith does not return Mockery instance.
You can also do it this way:
$this->app->make(SomeClass::class, ["foo" => 'bar']);

How to reconstruct a url using cakephp while removing selected query parameters?

I am using CakePHP 2.4
I have a url for e.g. /sent?note=123&test=abc
I want to remove the note parameter while giving me the rest of the url back. i.e.
/sent?test=abc
I have a piece of code that works but only for query parameters. I would like to find out how to improve my code so that it works with:
named parameters
passed parameters
hashtag
E.g.
/sent/name1:value1?note=123&test=abc#top
This is the code I have written so far. https://github.com/simkimsia/UtilityComponents/blob/master/Controller/Component/RequestExtrasHandlerComponent.php#L79
UPDATE PART III:
Let me illustrate with more examples to demonstrate what I mean by a more generic answer.
The more generic answer should assume no prior knowledge about the url patterns.
Assuming given this url
/sent/name1:value1?note=123&test=abc
I want to get rid of only the query parameter note and get back
/sent/name1:value1?test=abc
The more generic solution should work to give me back this url.
Another example. This time to get rid of named parameters.
Assuming given this url again
/sent/name1:value1?note=123&test=abc
I want to get rid of name1 and get back:
/sent?note=123&test=abc
Once again, the more generic solution should be able to accomplish this as well.
UPDATE PART II:
I am looking for a more generic answer. Assuming the web app does not know the url is called sent. You also do not know if the query parameters contain the word note or test. How do I still accomplish the above?
I want to be able to use the same code for any actions. That way, I can package it into a Component to be reused easily.
UPDATE PART I:
I understand that hashtag will not be passed to PHP. So please ignore that.
Clues on how to get the values from the hashtag:
https://stackoverflow.com/a/7817134/80353
https://stackoverflow.com/a/940996/80353
What about using mod_rewrite ?
You can handle your URLS in an other way :
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^/sent/name:(.*)?note=(.*)&test=([az-AZ])(#(.*))$ /sent/name:$1/note:$2/test:$3$4
</IfModule>
I'm not sure about the regex, but this may pass variables to cakePHP in a clean way (but I haven't tested it, though)
[EDIT]
But if you want to work without knowing urls patterns, then you can use the $this->request array : with an URL like
action/id:10/test:sample?sothertest=othersample&lorem=ipsum
I can get all the arguments using this in my controller :
// In your controller's method
$arguments= array_merge_recursive($this->request->named,$this->request->query);
Then, $arguments will be an array containing both named and passed params :
array(
'id' => '10',
'test' => 'sample',
'sothertest' => 'othersample',
'lorem' => 'ipsum'
)
Is it better ?
[EDIT 2]
If you know which parameter you have to get rid of, and directly redirect to the new URL, this should work:
action/id:10/test:sample?knownParam=value&lorem=ipsum
or with
action/id:10/knownParam:value?othertest=othersample&lorem=ipsum
In your controller/appController action:
// Name of the known param
$knownParam = 'knownParam';
// Arguments
$arguments = array_merge_recursive($this->request->named, $this->request->query);
if (key_exists($knownParam, $arguments)) {
// Unset in named params:
unset($arguments[$knownParam]);
// Creating url:
$url = array(
'admin' => $this->request->params['prefix'],
'plugin' => $this->request->params['plugin'],
'controller' => $this->request->params['controller'],
'action' => $this->request->params['action']
);
// Adding args
foreach ($arguments as $k => $v) {
$url[$k] = $v;
}
// Redirect
$this->redirect($url);
}
This will redirect both urls to
action/id:10/param1:value1/param2:value2
without the "know param"...
Let us say you have created the following routes:
Router::connect('/projects/:id/quotations/:quotation_id/*',
array(
'controller' => 'quotations',
'action' => 'get_all_by_project', "[method]" => "GET"),
array(
'pass' => array('id', 'quotation_id'),
'id' => '[0-9]+',
'quotation_id' => '[0-9]+'
),
array(
'named' => array(
'name1',
'name2',
'name3'
)
)
);
In this route:
Passed parameters will be the compulsory parameters id and quotation_id obeying the order as the first and second passed parameter
Named parameters will be the optional parameters name1, name2, and name3.
Query parameters will, of course, be optional as well and depend on what you actually have in the url.
you need the asterisk at the end so that the named parameters can pass through
Let us assume the following pretty url and the ugly url of the same action:
/projects/1/quotations/23/name2:value2/name3:value3/name1:value1?note=abc&test=123 (pretty)
/quotations/get_all_by_project/1/23/name2:value2/name3:value3/name1:value1?note=abc&test=123 (ugly)
First part of the answer:
Let us consider only the scenario of removing the query parameter note.
We should get back
/projects/1/quotations/23/name2:value2/name3:value3/name1:value1?test=123 (pretty)
/quotations/get_all_by_project/1/23/name2:value2/name3:value3/name1:value1?test=123 (ugly)
The following Component method will work. I have tested it on both the ugly and pretty urls.
public function removeQueryParameters($parameters, $here = '') {
if (empty($here)) {
$here = $this->controller->request->here;
}
$query = $this->controller->request->query;
$validQueryParameters = array();
foreach($query as $param=>$value) {
if (!in_array($param, $parameters)) {
$validQueryParameters[$param] = $value;
}
}
$queryString = $this->_reconstructQueryString($validQueryParameters);
return $here . $queryString;
}
protected function _reconstructQueryString($queryParameters = array()) {
$queryString = '';
foreach($queryParameters as $param => $value) {
$queryString .= $param . '=' . $value . '&';
}
if (strlen($queryString) > 0) {
$queryString = substr($queryString, 0, strlen($queryString) - 1);
$queryString = '?' . $queryString;
}
return $queryString;
}
This is how you call the Component method.
$newUrl = $this->RequestExtrasHandler->removeQueryParameters(array('note'));
RequestExtrasHandler is the name of Component I wrote that has the above method.
Second part of the answer:
Let us consider only the scenario of removing the named parameter name2.
We should get back
/projects/1/quotations/23/name3:value3/name1:value1?test=123 (pretty)
/quotations/get_all_by_project/1/23/name3:value3/name1:value1?test=123 (ugly)
The following Component method will work. I have tested it on both the ugly and pretty urls.
public function removeNamedParameters($parameters, $here = '') {
if (empty($here)) {
$here = $this->controller->request->here;
}
$query = $this->controller->request->query;
$named = $this->controller->request->params['named'];
$newHere = $here;
foreach($named as $param=>$value) {
if (in_array($param, $parameters)) {
$namedString = $param . ':' . $value;
$newHere = str_replace($namedString, "", $newHere);
}
}
$queryString = $this->_reconstructQueryString($query);
return $newHere . $queryString;
}
This is how you call the Component method.
$newUrl = $this->RequestExtrasHandler->removeNamedParameters(array('name2'));
RequestExtrasHandler is the name of Component I wrote that has the above method.
Third part of the answer:
After I realized that passed parameters are compulsory, I found that there is no real business need to remove passed parameters if at all.
Another problem is that unlike named parameters and query parameters, passed parameters tend not to have the keys present in the $this->controller->request->params['pass']
$this->controller->request->params['pass'] is usually in the form of a numerically indexed array.
Hence, there is huge challenge to take out the correct passed parameters.
Because of that, I will not create any method to remove passed parameters.
Check out the code here in details:
https://github.com/simkimsia/UtilityComponents/blob/d044da690c7b83c72a50ab97bfa1843c14355507/Controller/Component/RequestExtrasHandlerComponent.php#L89
maybe simple php functions can do what you want
$url = '/sent?note=123&test=abc'; //for example
$unwanted_string = substr($url, 0,strrpos($url,'&') + 1);
$unwanted_string = str_replace('/sent?', '', $unwanted_string);
$url = str_replace($unwanted_string, '', $url);

Categories