Alewa's avatar
Level 2

I am having array object with string error in my react js and laravel api

How do I add this product attribute into my database from react without getting this error foreach() argument must be of type array|object, string given any help?

ProductController.php

import { Link, useNavigate, useParams } from "react-router-dom"; import { useContext, useEffect, useState } from "react"; import DashboardSidebar from "../DashboardSidebar"; import { AppContext } from "../../Context/AppContext";

export default function ViewProductAttributes() { const { id } = useParams(); const navigate = useNavigate(); const { name, token } = useContext(AppContext); const [product, setProduct] = useState([]); const [productAttributes, setProductAttributes] = useState([]); const [productAttributeInput, setProductAttributeInput] = useState({ size: [], sku: [], cost_price: [], sales_price: [], stock: [], });

const [errors, setErrors] = useState({});

async function getProductDetails() {
    const res = await fetch(`/api/view_product_attribute/${id}`, {
        headers: {
            Authorization: `Bearer ${token}`,
        },
    });
    const data = await res.json();

    if (res.ok) {
        setProduct(data.product); //this product is the one comming from ProductController.php @ viewProductAttribute function
    }
}

async function getProductAttributes() {
    const res = await fetch(`/api/view_product_attribute/${id}`, {
        headers: {
            Authorization: `Bearer ${token}`,
        },
    });
    const data = await res.json();

    if (res.ok) {
        setProductAttributes(data.productattributes); //this productattributes is the one comming from ProductController.php @ viewProductAttribute function
    }
}

const handleInput = (e) => {
    e.persist();
    setProductAttributeInput({
        ...productAttributeInput,
        [e.target.name]: e.target.value,
    });
};

async function addProductAttribute(e) {
    e.preventDefault();

    const Formdata = {
        size: productAttributeInput.size,
        sku: productAttributeInput.sku,
        cost_price: productAttributeInput.cost_price,
        sales_price: productAttributeInput.sales_price,
        stock: productAttributeInput.stock,
    };

    const res = await fetch(`/api/add_product_attribute/${id}`, {
        method: "post",
        headers: {
            Authorization: `Bearer ${token}`,
        },
        body: JSON.stringify(Formdata),
    });

    const data = await res.json();

    if (data.errors) {
        setErrors(data.errors);
    } else {
        navigate("/view_products");
        alert(data.message);
    }
}

//this useEffect is calling the getProductAttributes function at the top
useEffect(() => {
    getProductDetails();
    getProductAttributes();
}, []);

return (
    <>
        <div className="xsm:h-[200px] md:h-[220px] w-full bg-primary">
            <div className="container">
                <div className="flex justify-between">
                    <div className="xsm:pt-[20px] md:pt-[50px]">
                        <h1 className="font-roboto text-secondary xsm:text-[30px] md:text-[50px] animation-delay-300 xsm:leading-8 md:leading-[50px]">
                            Modern Courses
                        </h1>
                        <p className="text-white text-[17px] pb-9 xsm:pt-2 md:pt-4">
                            Lorem ipsum dolor sit amet consectetur
                            adipisicing elit. Debitis reiciendis corrupti.
                        </p>
                    </div>
                </div>
            </div>
        </div>

        <div className="pt-10">
            <div className="container grid grid-cols-4 gap-6 pt-4 pb-16 items-start">
                <div className="lg:col-span-3 xsm:col-span-4">
                    <div className="flex items-center mb-3">
                        <Link
                            to="/view_products"
                            className="flex items-center rounded border border-red-600 py-1 px-2 text-white bg-red-600 hover:bg-tertiary hover:border-tertiary"
                        >
                            <i className="fa-light fa-arrow-left mr-1"></i>
                            BACK
                        </Link>
                    </div>
                    <div className="space-y-4">
                        <div className="bg-white p-3 border border-gray-200 rounded">
                            <h1 className="font-roboto text-[25px] text-primary font-semibold capitalize mb-4">
                                ADD PRODUCT ATTRIBUTE
                            </h1>
                            <div
                                className="grid xsm:grid-cols-1 md:grid-cols-4 gap-4"
                                key={product.id}
                            >
                                <div>
                                    <label className="text-gray-600 mb-2 block">
                                        Product
                                        <span className="text-red-600">
                                            *
                                        </span>
                                    </label>
                                    <input
                                        type="text"
                                        className="block w-full border border-gray-300 px-4 py-3 text-gray-600 text-sm rounded placeholder-gray-400 focus:border-primary focus:ring-0"
                                        value={product.product_name}
                                        readOnly
                                    />
                                </div>
                                <div>
                                    <label className="text-gray-600 mb-2 block">
                                        Code
                                        <span className="text-red-600">
                                            *
                                        </span>
                                    </label>
                                    <input
                                        type="email"
                                        className="block w-full border border-gray-300 px-4 py-3 text-gray-600 text-sm rounded placeholder-gray-400 focus:border-primary focus:ring-0"
                                        value={product.product_code}
                                        readOnly
                                    />
                                </div>
                                <div>
                                    <label className="text-gray-600 mb-2 block">
                                        Cost Price
                                        <span className="text-red-600">
                                            *
                                        </span>
                                    </label>
                                    <input
                                        type="email"
                                        className="block w-full border border-gray-300 px-4 py-3 text-gray-600 text-sm rounded placeholder-gray-400 focus:border-primary focus:ring-0"
                                        value={product.product_cost_price}
                                        readOnly
                                    />
                                </div>
                                <div>
                                    <label className="text-gray-600 mb-2 block">
                                        Sales Price
                                        <span className="text-red-600">
                                            *
                                        </span>
                                    </label>
                                    <input
                                        type="text"
                                        className="block w-full border border-gray-300 px-4 py-3 text-gray-600 text-sm rounded placeholder-gray-400 focus:border-primary focus:ring-0"
                                        value={product.product_sales_price}
                                        readOnly
                                    />
                                </div>
                            </div>

                            <form
                                onSubmit={addProductAttribute}
                                className="mt-10"
                            >
                                <div className="grid xsm:grid-cols-1 md:grid-cols-5 gap-4">
                                    <div>
                                        <input
                                            type="text"
                                            className="block w-full border border-gray-300 px-4 py-3 text-gray-600 text-sm rounded placeholder-gray-400 focus:border-primary focus:ring-0"
                                            placeholder="Size"
                                            name="size"
                                            onChange={handleInput}
                                            value={
                                                productAttributeInput.size
                                            }
                                        />
                                        {errors.size && (
                                            <p className="text-red-600">
                                                {errors.size[0]}
                                            </p>
                                        )}
                                    </div>
                                    <div>
                                        <input
                                            type="text"
                                            className="block w-full border border-gray-300 px-4 py-3 text-gray-600 text-sm rounded placeholder-gray-400 focus:border-primary focus:ring-0"
                                            placeholder="SKU"
                                            name="sku"
                                            onChange={handleInput}
                                            value={
                                                productAttributeInput.sku
                                            }
                                        />
                                        {errors.sku && (
                                            <p className="text-red-600">
                                                {errors.sku[0]}
                                            </p>
                                        )}
                                    </div>
                                    <div>
                                        <input
                                            type="text"
                                            className="block w-full border border-gray-300 px-4 py-3 text-gray-600 text-sm rounded placeholder-gray-400 focus:border-primary focus:ring-0"
                                            placeholder="Cost Price"
                                            name="cost_price"
                                            onChange={handleInput}
                                            value={
                                                productAttributeInput.cost_price
                                            }
                                        />
                                        {errors.cost_price && (
                                            <p className="text-red-600">
                                                {errors.cost_price[0]}
                                            </p>
                                        )}
                                    </div>
                                    <div>
                                        <input
                                            type="text"
                                            className="block w-full border border-gray-300 px-4 py-3 text-gray-600 text-sm rounded placeholder-gray-400 focus:border-primary focus:ring-0"
                                            placeholder="Sales Price"
                                            name="sales_price"
                                            onChange={handleInput}
                                            value={
                                                productAttributeInput.sales_price
                                            }
                                        />
                                        {errors.sales_price && (
                                            <p className="text-red-600">
                                                {errors.sales_price[0]}
                                            </p>
                                        )}
                                    </div>
                                    <div>
                                        <input
                                            type="number"
                                            className="block w-full border border-gray-300 px-4 py-3 text-gray-600 text-sm rounded placeholder-gray-400 focus:border-primary focus:ring-0"
                                            placeholder="Stock"
                                            name="stock"
                                            onChange={handleInput}
                                            value={
                                                productAttributeInput.stock
                                            }
                                        />
                                        {errors.stock && (
                                            <p className="text-red-600">
                                                {errors.stock[0]}
                                            </p>
                                        )}
                                    </div>
                                </div>
                                <div class="pt-2">
                                    <button class="bg-primary border border-primary text-white px-8 py-2 mb-3 font-medium rounded text-uppercase flex items-center gap-2 hover:bg-transparent hover:text-primary transition">
                                        ADD
                                    </button>
                                </div>
                            </form>
                        </div>
                    </div>
                    <div>
                        <table className="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
                            <thead className="text-xs text-gray-500 uppercase bg-gray-50 dark:text-gray-400 border-b-2 border-gray-400">
                                <tr className="text-nowrap">
                                    <th className="px-3 py-2">ID</th>
                                    <th className="px-3 py-2">
                                        Product ID
                                    </th>
                                    <th className="px-3 py-2">Size</th>
                                    <th className="px-3 py-2">SKU</th>
                                    <th className="px-3 py-2">
                                        Cost Price
                                    </th>
                                    <th className="px-3 py-2">
                                        Sales Price
                                    </th>
                                    <th className="px-3 py-2">Status</th>
                                    <th className="px-3 py-2">Action</th>
                                </tr>
                            </thead>
                            <tbody>
                                {productAttributes.length > 0 ? (
                                    productAttributes.map(
                                        (productAttribute) => (
                                            <tr
                                                key={productAttribute.id}
                                                className="bg-white border-b dark:bg-gray-800 dark:border-gray-700"
                                            >
                                                <td className="px-3 py-2">
                                                    1
                                                </td>
                                                <td className="px-3 py-2">
                                                    {
                                                        productAttribute.product_id
                                                    }
                                                </td>
                                                <td className="px-3 py-2">
                                                    {productAttribute.size}
                                                </td>
                                                <td className="px-3 py-2">
                                                    {productAttribute.sku}
                                                </td>
                                                <td className="px-3 py-2">
                                                    {
                                                        productAttribute.cost_price
                                                    }
                                                </td>
                                                <td className="px-3 py-2">
                                                    {
                                                        productAttribute.sales_price
                                                    }
                                                </td>
                                                <td className="px-3 py-2 text-nowrap">
                                                    {
                                                        productAttribute.status
                                                    }
                                                </td>
                                                <td className="px-3 py-2">
                                                    <div className="flex text-center gap-2">
                                                        <button >
                                                            <i className="fa-light fa-trash"></i>
                                                        </button>
                                                    </div>
                                                </td>
                                            </tr>
                                        )
                                    )
                                ) : (
                                    <p className="py-4 text-red-500 text-[20px]">
                                        No product attributes
                                    </p>
                                )}
                            </tbody>
                        </table>
                        {/* pagination */}
                    </div>
                </div>

                <div className="xsm:col-span-4 md:col-span-4 lg:col-span-1 px-4 pb-6 shadow rounded overflow-hidden xsm:mt-10 md:mt-[0px]">
                    <div className="divide-y divide-gray-200 space-y-5">
                        <DashboardSidebar />
                    </div>
                </div>
            </div>
        </div>
    </>
);

}```

When I try to add the product attribute to my database, get foreach() argument must be of type array|object, string given error and the same thing was happening when I was testing my api with Thunder Client, but when i added [ ] next to my name attribute in input field everything worked fine eg. <input name="size[]"> The moment I added the [] from my Thunder Client everything worked, but when i add [ ] next to my name attribute in input field at my react.js file, when typing nothing happenings. But in my console I get the codes like this

{size: "Small", sku: "APT-SM", cost_price: "20", sales_price: "30", stock: "4"}
cost_price
: 
"20"
sales_price
: 
"30"
size
: 
"Small"
sku
: 
"APT-SM"
stock
: 
"4"```
But no entry because of the ```foreach() argument must be of type array|object, string given```   error, any help?
0 likes
13 replies
Alewa's avatar
Level 2

ViewProductAttribute.jsx the one above did not come well

jlrdw's avatar

In your other post I asked what does:

dd($data['sku']);

show. Or a print_r?

Alewa's avatar
Level 2

@jlrdw it is working perfectly with the api, but want to know how to add it through react, without any foreach error. any help?

jlrdw's avatar

@Alewa It;s hard to tell without seeing results of a dd($data['sku']);

Alewa's avatar
Level 2

@jlrdw where in the code should I dd($data['sku']);?

jlrdw's avatar

@Alewa

        $data = $request->all();
        dd($data['sku']);
        foreach($data['sku'] as $key => $value){
            if(!empty($value)){
Alewa's avatar
Level 2

@jlrdw I am having this

<script> Sfdump = window.Sfdump || (function (doc) { doc.documentElement.classList.add('sf-js-enabled'); var rxEsc = /([.*+?^${}()|\[\]\/\\])/g, idRx = /\bsf-dump-\d+-ref[012]\w+\b/, keyHint = 0 <= navigator.platform.toUpperCase().indexOf('MAC') ? 'Cmd' : 'Ctrl', addEventListener = function (e, n, cb) { e.addEventListener(n, cb, false); }; if (!doc.addEventListener) { addEventListener = function (element, eventName, callback) { element.attachEvent('on' + eventName, function (e) { e.preventDefault = function () {e.returnValue = false;}; e.target = e.srcElement; callback(e); }); }; } function toggle(a, recursive) { var s = a.nextSibling || {}, oldClass = s.className, arrow, newClass; if (/\bsf-dump-compact\b/.test(oldClass)) { arrow = '&#9660;'; newClass = 'sf-dump-expanded'; } else if (/\bsf-dump-expanded\b/.test(oldClass)) { arrow = '&#9654;'; newClass = 'sf-dump-compact'; } else { return false; } if (doc.createEvent && s.dispatchEvent) { var event = doc.createEvent('Event'); event.initEvent('sf-dump-expanded' === newClass ? 'sfbeforedumpexpand' : 'sfbeforedumpcollapse', true, false); s.dispatchEvent(event); } a.lastChild.innerHTML = arrow; s.className = s.className.replace(/\bsf-dump-(compact|expanded)\b/, newClass); if (recursive) { try { a = s.querySelectorAll('.'+oldClass); for (s = 0; s < a.length; ++s) { if (-1 == a[s].className.indexOf(newClass)) { a[s].className = newClass; a[s].previousSibling.lastChild.innerHTML = arrow; } } } catch (e) { } } return true; }; function collapse(a, recursive) { var s = a.nextSibling || {}, oldClass = s.className; if (/\bsf-dump-expanded\b/.test(oldClass)) { toggle(a, recursive); return true; } return false; }; function expand(a, recursive) { var s = a.nextSibling || {}, oldClass = s.className; if (/\bsf-dump-compact\b/.test(oldClass)) { toggle(a, recursive); return true; } return false; }; function collapseAll(root) { var a = root.querySelector('a.sf-dump-toggle'); if (a) { collapse(a, true); expand(a); return true; } return false; } function reveal(node) { var previous, parents = []; while ((node = node.parentNode || {}) && (previous = node.previousSibling) && 'A' === previous.tagName) { parents.push(previous); } if (0 !== parents.length) { parents.forEach(function (parent) { expand(parent); }); return true; } return false; } function highlight(root, activeNode, nodes) { resetHighlightedNodes(root); Array.from(nodes||[]).forEach(function (node) { if (!/\bsf-dump-highlight\b/.test(node.className)) { node.className = node.className + ' sf-dump-highlight'; } }); if (!/\bsf-dump-highlight-active\b/.test(activeNode.className)) { activeNode.className = activeNode.className + ' sf-dump-highlight-active'; } } function resetHighlightedNodes(root) { Array.from(root.querySelectorAll('.sf-dump-str, .sf-dump-key, .sf-dump-public, .sf-dump-protected, .sf-dump-private')).forEach(function (strNode) { strNode.className = strNode.className.replace(/\bsf-dump-highlight\b/, ''); strNode.className = strNode.className.replace(/\bsf-dump-highlight-active\b/, ''); }); } return function (root, x) { root = doc.getElementById(root); var indentRx = new RegExp('^('+(root.getAttribute('data-indent-pad') || ' ').replace(rxEsc, '\\$1')+')+', 'm'), options = {"maxDepth":1,"maxStringLength":160,"fileLinkFormat":false}, elt = root.getElementsByTagName('A'), len = elt.length, i = 0, s, h, t = []; while (i < len) t.push(elt[i++]); for (i in x) { options[i] = x[i]; } function a(e, f) { addEventListener(root, e, function (e, n) { if ('A' == e.target.tagName) { f(e.target, e); } else if ('A' == e.target.parentNode.tagName) { f(e.target.parentNode, e); } else { n = /\bsf-dump-ellipsis\b/.test(e.target.className) ? e.target.parentNode : e.target; if ((n = n.nextElementSibling) && 'A' == n.tagName) { if (!/\bsf-dump-toggle\b/.test(n.className)) { n = n.nextElementSibling || n; } f(n, e, true); } } }); }; function isCtrlKey(e) { return e.ctrlKey || e.metaKey; } function xpathString(str) { var parts = str.match(/[^'"]+|['"]/g).map(function (part) { if ("'" == part) { return '"\'"'; } if ('"' == part) { return "'\```
jlrdw's avatar

@Alewa might be easier to show results of:

echo "<pre>";
print_r($data['sku']);
die;

so do this:

       $data = $request->all();
        echo "<pre>";
        print_r($data['sku']);
        die;
        foreach($data['sku'] as $key => $value){
            if(!empty($value)){
Alewa's avatar
Level 2

@jlrdw I get this

<pre>Array
(
    [0] => NUWWS-38
)</pre>```
jlrdw's avatar

@Alewa so you have just a single item. You don't need a foreach there.

Edit:

What does:

$data = $request->input('sku');

Show?

Or do a print_r($data); with the pre.

Alewa's avatar
Level 2

@jlrdw I understand that I am only sending a single item, but want to send multiple items, that is why I am using foreach. I have created a website with only laravel and html using the same code and it is working perfectly for adding multiple items at once, and I want to use the same code to add multiple items at once using react js

jlrdw's avatar

@Alewa if

foreach($data['sku'] as $key => $value){

Has more than one piece of data in one application, but not the other. You need to use your network tools and start trouble shooting what is going on.

Somehow in the react app you're not getting the data where it belongs.

So troubleshoot one little section of code at a time and check the results.

Please or to participate in this conversation.