I want to store a list of departments in my database. I do not create the departments in my system, I obtain them from Active Directory. In the view for departments, I display all the departments. I also have a button to update departments in the database.
This function at the moment looks like the following
public function updateDepartments()
{
$departments = Helper::returnDepartmentsFromLdap();
dd($departments);
}
The dd produces something like the following
array:16 [▼
0 => "Department 1"
8 => "Department 2"
21 => "Department 3"
22 => "Department 4"
29 => "Department 5"
43 => "Department 6"
47 => "Department 7"
48 => "Department 8"
]
You have to remember though that this list is not being obtained from my database, it is being obtained from Active Directory. However, I now want to add them to my database. So in the same function I do the following
public function updateDepartments()
{
$departments = Helper::returnDepartmentsFromLdap();
foreach($departments as $departmentID => $departmentName) {
$department = new Department();
$department->departmentID = $departmentID;
$department->departmentName = $departmentName;
$department->save();
}
return Redirect::route('departments.index')->with('message', 'Departments updated.');
}
Now the problem with the above is that every time the button is pushed, the database will insert new rows. Say I push the button for the first time, my database will be populated with the list. Say I then push it a second time, I do not want the same list added again. If it already exist in the database, it should overwrite it or something. It should only perform a save if a new item is in the list.
Is something like this possible?
Thanks
Try this approach:
public function updateDepartments()
{
$departments = Helper::returnDepartmentsFromLdap();
foreach($departments as $departmentID => $departmentName) {
$department = Department::firstOrCreate(['departmentID' => $departmentID, 'departmentName' => $departmentName]);
}
return Redirect::route('departments.index')->with('message', 'Departments updated.');
}
This is basic idea. Now if this is not clear give me info what you want to update and I will change this impl according to your requirements. For example you could do this:
public function updateDepartments()
{
$departments = Helper::returnDepartmentsFromLdap();
foreach($departments as $departmentID => $departmentName) {
$department = Department::firstOrNew(['departmentID' => $departmentID]);
$department->departmentName = $departmentName;
$department->save();
}
return Redirect::route('departments.index')->with('message', 'Departments updated.');
}
This is according to eloquent documentation
Other Creation Methods
There are two other methods you may use to create models by mass assigning attributes: firstOrCreate and firstOrNew.
The firstOrCreate method will attempt to locate a database record using the given column / value pairs. If the model can not be found in the database, a record will be inserted with the given attributes.
The firstOrNew method, like firstOrCreate will attempt to locate a record in the database matching the given attributes. However, if a model is not found, a new model instance will be returned. Note that the model returned by firstOrNew has not yet been persisted to the database. You will need to call save manually to persist it:
// Retrieve the flight by the attributes, or create it if it doesn't exist...
$flight = App\Flight::firstOrCreate(['name' => 'Flight 10']);
// Retrieve the flight by the attributes, or instantiate a new instance...
$flight = App\Flight::firstOrNew(['name' => 'Flight 10']);
public function updateDepartments()
{
$departments = Helper::returnDepartmentsFromLdap();
$savedDepartments = Department::select('departmentID')->get();
foreach ($departments as $departmentID => $departmentName) {
$alreadySaved = false;
foreach ($savedDepartments as $item) {
if ($item->departmentID == $departmentID) {
$alreadySaved = true;
break;
}
}
if (!$alreadySaved) {
$department = new Department();
$department->departmentID = $departmentID;
$department->departmentName = $departmentName;
$department->save();
}
}
return Redirect::route('departments.index')->with('message', 'Departments updated.');
}
Little more complex but should be faster
Related
The problem is when I entered a new name no data is added. A similar thing happen when I entered an already existing name. Still, no data is added to the database. I am still new to CodeIgniter and not entirely sure my query builder inside the model is correct or not.
In the Model, I check if the name already exists insert data only into the phone_info table. IF name does not exist I insert data into user_info and phone_info.
Controller:
public function addData()
{
$name = $this->input->post('name');
$contact_num = $this->input->post('contact_num');
if($name == '') {
$result['message'] = "Please enter contact name";
} elseif($contact_num == '') {
$result['message'] = "Please enter contact number";
} else {
$result['message'] = "";
$data = array(
'name' => $name,
'contact_num' => $contact_num
);
$this->m->addData($data);
}
echo json_encode($result);
}
Model:
public function addData($data)
{
if(mysqli_num_rows($data['name']) > 0) {
$user = $this->db->get_where('user_info', array('name' => $data['name']))->result_array();
$user_id = $user['id'];
$phone_info = array(
'contact_num' => $data['contact_num'],
'user_id' => $user_id
);
$this->db->insert('phone_info',$phone_info);
} else {
$user_info = array(
'name' => $data['name']
);
$this->db->insert('user_info', $user_info);
$user = $this->db->get_where('user_info', array('name' => $data['name']))->result_array();
$user_id = $user['id'];
$phone_info = array(
'contact_num' => $data['contact_num'],
'user_id' => $user_id
);
$this->db->insert('phone_info', $phone_info);
}
}
DB-Table user_info:
DB-Table phone_info:
Extend and change your model to this:
public function findByTitle($name)
{
$this->db->where('name', $name);
return $this->result();
}
public function addData($data)
{
if(count($this->findByTitle($data['name'])) > 0) {
//.. your code
} else {
//.. your code
}
}
Explanation:
This:
if(mysqli_num_rows($data['name']) > 0)
..is not working to find database entries by name. To do this you can use codeigniters built in model functions and benefit from the MVC Pattern features, that CodeIgniter comes with.
I wrapped the actual findByName in a function so you can adapt this to other logic and use it elswehere later on. This function uses the query() method.
Read more about CodeIgniters Model Queries in the documentation.
Sidenote: mysqli_num_rows is used to iterate find results recieved by mysqli_query. This is very basic sql querying and you do not need that in a MVC-Framework like CodeIgniter. If you every appear to need write a manual sql-query, even then you should use CodeIgniters RawQuery methods.
I don't know how to get just one record from the database. I'm doing it with foreach, as if it were several records. How can i get just one record?
this is my code:
$usuario = \DB::select('SELECT * FROM usuarios where id=:id',['id' => session('id')]);
foreach ($usuario as $u)
{
$nombre=$u->nombre;
$email=$u->email;
}
As pointed out by #lagbox, you are using the select function which will return an array.
So in order to get the first element, you would do:
$usuarios = \DB::select('SELECT * FROM usuarios where id=:id',['id' => session('id')])->get();
if(!empty($usuarios)) {
$usuario = $usuarios[0];
}
But you'd probably be better using the query builder, like this:
$usuario = \DB::table('usuarios')->where('id', session('id'))->first();
// $nombre = $usuario->nombre;
// $email = $usuario->email;
I try to update a component that has a relationship, from frontend I send the correct data, but in back works to update only the main table.
public function updateCustomer(Request $request, Customer $customer)
{
$customer->$customerNames->update();
$customer->update($request->all());
return response($customer, 200);
}
You may use
$customer->account_name = $request->account_name;
$customer->sage_id = $request->sage_id;
$customer->update();
$customerNames = [];
foreach($request->customer_names as $customer_name) {
$customerNames[] = new CustomerName(
[
'name' => $customer_name['name'],
'name_type' => $customer_name['name_type'],
'movation_date' => customer_name['movation_date']
]
);
}
$customer->customerNames()->delete();
$customer->customerNames()->saveMany($customerNames);
//...
I am doing a peer marking system which requires a function that lecturer adds id list and when students enroll in a course, he enters his id needed to match the id on lecturer id list.
Controller
public function store(Request $request)
{
$this->validate($request, [
'course_code' => 'required',
'studentid' => 'required'
]);
$enrollment = new Enrollment;
$enrollment->user_id = auth()->user()->id;
$enrollment->course_id = $request->course;
$enrollment->user_StudentID = $request->studentid;
$input_course_id = $request->input('course_code');
$input_studentid = $request->input('studentid');
$course = Course::find($enrollment->course_id);
$course_identifiers = $course->identifiers;
// Need all the data in the database course table for comparison
//$course represents the contents of the course table in all databases, then you need to loop first, then judge
//$course stands for list $signleCourse for each piece of data
foreach ($course_identifiers as $course_identifier) {
// if ($course_identifier->studentid == $input_studentid )
if ($input_studentid == $course_identifier->studentid) {
if ($request->course == $input_course_id) {
//if true,save and redirect
$enrollment->save();
return redirect('/enrollment')->with('success', 'Course Enrolled');
} else {
return redirect('/enrollment')->with('error', 'Please Enter Correct Confirmation Code');
//If false do nothing
}
} else {
return redirect('/enrollment')->with('error', 'Please Enter Correct Student ID');
//If false do nothing
}
}
}
It can only match the first value, but other values I enter cannot be recognized.
Turn off your redirects. It's really hard to understand the context of that code but it looks like if it fails to match it redirects so doesn't go through the second and subsequent values of $course_identifiers.
I used Yii 2.
To be clear:
The two tables, content and task, is 1:1 relation, task.content_id =
content.id;
and I referenced
doc.
in view file, I used Gridview to show data.
and I wanna the content is also searchable even it is in another
table.
Maybe the following sql can explain what I want:
SELECT
c.content,
t.publish_status
FROM
content c, task t
WHERE
c.content LIKE '%keywordInContent%' AND
t.publish_status = 1 AND
c.id = t.content_id
ORDER BY
updated_at
LIMIT 20;
Here is my controller code:
public function actionIndex()
{
$searchModel = new TaskSearch;
$dataProvider = $searchModel->search(Yii::$app->getRequest()->get());
return $this->render('index', [
'dataProvider' => $dataProvider,
'searchModel' => $searchModel,
]);
}
and search model code:
public function search($params)
{
$query = Task::find()->trashed(Task::TRASHED_NO);
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
if (!($this->load($params) && $this->validate())) {
return $dataProvider;
}
$query->andFilterWhere(['publish_status' => $this->publish_status]);
return $dataProvider;
}
I have settled it by searching like clause before and adding the resulted content_id to searchModel query, code like follow:
if (!empty($this->keyword)) {
$contentIdArr = Content::find()->select('id')->where(['like', 'content', $this->keyword])->column();
if (empty($contentIdArr)) {
$contentIdArr = -1;
}
$query->andFilterWhere(['content_id' => $contentIdArr]);
}
I wonder is there a way to construct the sql I wrote at begin in Yii 2 ?
thanks for help.
Could you try this:
public function search($params)
{
$query = Task::find()->trashed(Task::TRASHED_NO);
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
if (!($this->load($params) && $this->validate())) {
return $dataProvider;
}
if(!empty($this->keyword))
$query->leftJoin('content', 'content.id=task.content_id')
->andWhere(['publish_status' => 1])
->andWhere(['LIKE', 'content', $this->keyword])
->orderBy('updated_at');
return $dataProvider;
}
But the updated_at shouldn't be part of the search, I guess. This is more about sorting. Look here for an example.
I think you can do it by first getting Content data and have a relation with Task model.
You can achieve relation by this link. Relation in Content model:
public function getTask()
{
return $this->hasOne(Task::className(), ['content_id' => 'id']);
}
and search query
$searchResult = Content::find()
->select('content, publish_status')
->with('task')
->where(['LIKE', 'content', 'keywordInContent'])
->andWhere(['publish_status' => 1])
->orderBy('updated_at')
->limit(20)
->all();
I think this might help you.